Bug 1484524: Allow creating a StrongWorkerRef for IPC in the Canceling state r=asuth

By allowing the creation of StrongWorkerRefs in the Canceling state we
ensure that IPC will not fail and lead to crashes.

Differential Revision: https://phabricator.services.mozilla.com/D21920

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Yaron Tausky 2019-03-04 23:05:34 +00:00
Родитель ff5c70a292
Коммит 842cf2b27c
3 изменённых файлов: 43 добавлений и 9 удалений

Просмотреть файл

@ -145,8 +145,26 @@ WorkerPrivate* WeakWorkerRef::GetUnsafePrivate() const {
/* static */
already_AddRefed<StrongWorkerRef> StrongWorkerRef::Create(
WorkerPrivate* aWorkerPrivate, const char* aName,
WorkerPrivate* const aWorkerPrivate, const char* const aName,
std::function<void()>&& aCallback) {
if (RefPtr<StrongWorkerRef> ref =
CreateImpl(aWorkerPrivate, aName, Canceling)) {
ref->mCallback = std::move(aCallback);
return ref.forget();
}
return nullptr;
}
/* static */
already_AddRefed<StrongWorkerRef> StrongWorkerRef::CreateForcibly(
WorkerPrivate* const aWorkerPrivate, const char* const aName) {
return CreateImpl(aWorkerPrivate, aName, Killing);
}
/* static */
already_AddRefed<StrongWorkerRef> StrongWorkerRef::CreateImpl(
WorkerPrivate* const aWorkerPrivate, const char* const aName,
WorkerStatus const aFailStatus) {
MOZ_ASSERT(aWorkerPrivate);
MOZ_ASSERT(aName);
@ -155,12 +173,11 @@ already_AddRefed<StrongWorkerRef> StrongWorkerRef::Create(
// The worker is kept alive by this holder.
UniquePtr<Holder> holder(
new Holder(aName, ref, WorkerHolder::PreventIdleShutdownStart));
if (NS_WARN_IF(!holder->HoldWorker(aWorkerPrivate, Canceling))) {
if (NS_WARN_IF(!holder->HoldWorker(aWorkerPrivate, aFailStatus))) {
return nullptr;
}
ref->mHolder = std::move(holder);
ref->mCallback = std::move(aCallback);
return ref.forget();
}

Просмотреть файл

@ -129,12 +129,31 @@ class StrongWorkerRef final : public WorkerRef {
WorkerPrivate* aWorkerPrivate, const char* aName,
std::function<void()>&& aCallback = nullptr);
// This function creates a StrongWorkerRef even when in the Canceling state of
// the worker's lifecycle. It's intended to be used by system code, e.g. code
// that needs to perform IPC.
//
// This method should only be used in cases where the StrongWorkerRef will be
// used for an extremely bounded duration that cannot be impacted by content.
// For example, IPCStreams use this type of ref in order to immediately
// migrate to an actor on another thread. Whether the IPCStream ever actually
// is streamed does not matter; the ref will be dropped once the new actor is
// created. For this reason, this method does not take a callback. It's
// expected and required that callers will drop the reference when they are
// done.
static already_AddRefed<StrongWorkerRef> CreateForcibly(
WorkerPrivate* aWorkerPrivate, const char* aName);
WorkerPrivate* Private() const;
private:
friend class WeakWorkerRef;
friend class ThreadSafeWorkerRef;
static already_AddRefed<StrongWorkerRef> CreateImpl(
WorkerPrivate* aWorkerPrivate, const char* aName,
WorkerStatus aFailStatus);
explicit StrongWorkerRef(WorkerPrivate* aWorkerPrivate);
~StrongWorkerRef();
};

Просмотреть файл

@ -119,12 +119,10 @@ bool IPCStreamSource::Initialize() {
// worker threads, but not other threads. Main-thread and PBackground thread
// do not need anything special in order to be kept alive.
if (!NS_IsMainThread()) {
mozilla::dom::WorkerPrivate* workerPrivate =
mozilla::dom::GetCurrentThreadWorkerPrivate();
if (workerPrivate) {
RefPtr<mozilla::dom::StrongWorkerRef> workerRef =
mozilla::dom::StrongWorkerRef::Create(workerPrivate,
"IPCStreamSource");
if (const auto workerPrivate = dom::GetCurrentThreadWorkerPrivate()) {
RefPtr<dom::StrongWorkerRef> workerRef =
dom::StrongWorkerRef::CreateForcibly(workerPrivate,
"IPCStreamSource");
if (NS_WARN_IF(!workerRef)) {
return false;
}