author | Andrea Marchesini <amarchesini@mozilla.com> |
Tue, 17 Apr 2018 20:51:03 +0200 | |
changeset 414223 | 52a992c65070d7f996dd3bfd38bc1521f49ec277 |
parent 414222 | 0d3ab01ff51bc77b7f616beefd355e70c0d7de41 |
child 414224 | 05cb4efbcd693d8c64f4b4df8a3d055c518b9d76 |
push id | 33861 |
push user | ccoroiu@mozilla.com |
push date | Wed, 18 Apr 2018 10:50:38 +0000 |
treeherder | mozilla-central@4af4ae0aee55 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | asuth |
bugs | 1450644 |
milestone | 61.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
dom/workers/WorkerPrivate.cpp | file | annotate | diff | comparison | revisions | |
dom/workers/WorkerPrivate.h | file | annotate | diff | comparison | revisions |
--- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -971,16 +971,59 @@ class SimpleWorkerHolder final : public public: SimpleWorkerHolder() : WorkerHolder("SimpleWorkerHolder") {} virtual bool Notify(WorkerStatus aStatus) override { return true; } }; +// A runnable to cancel the worker from the parent thread when self.close() is +// called. This runnable is executed on the parent process in order to cancel +// the current runnable. It uses a normal WorkerRunnable in order to be sure +// that all the pending WorkerRunnables are executed before this. +class CancelingOnParentRunnable final : public WorkerRunnable +{ +public: + explicit CancelingOnParentRunnable(WorkerPrivate* aWorkerPrivate) + : WorkerRunnable(aWorkerPrivate, ParentThreadUnchangedBusyCount) + {} + + bool + WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override + { + aWorkerPrivate->Cancel(); + return true; + } +}; + +// This runnable starts the canceling of a worker after a self.close(). +class CancelingRunnable final : public Runnable +{ +public: + CancelingRunnable() + : Runnable("CancelingRunnable") + {} + + NS_IMETHOD + Run() override + { + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + MOZ_ASSERT(workerPrivate); + workerPrivate->AssertIsOnWorkerThread(); + + // Now we can cancel the this worker from the parent process. + RefPtr<CancelingOnParentRunnable> r = + new CancelingOnParentRunnable(workerPrivate); + r->Dispatch(); + + return NS_OK; + } +}; + } /* anonymous namespace */ class WorkerPrivate::EventTarget final : public nsISerialEventTarget { // This mutex protects mWorkerPrivate and must be acquired *before* the // WorkerPrivate's mutex whenever they must both be held. mozilla::Mutex mMutex; WorkerPrivate* mWorkerPrivate; @@ -3604,16 +3647,23 @@ WorkerPrivate::InterruptCallback(JSConte } // Make sure the periodic timer gets turned back on here. SetGCTimerMode(PeriodicTimer); return true; } +void +WorkerPrivate::CloseInternal() +{ + AssertIsOnWorkerThread(); + NotifyInternal(Closing); +} + bool WorkerPrivate::IsOnCurrentThread() { // May be called on any thread! MOZ_ASSERT(mPRThread); return PR_GetCurrentThread() == mPRThread; } @@ -4473,18 +4523,27 @@ WorkerPrivate::NotifyInternal(WorkerStat } // If the worker script never ran, or failed to compile, we don't need to do // anything else. if (!GlobalScope()) { return true; } - // Don't abort the script. + // Don't abort the script now, but we dispatch a runnable to do it when the + // current JS frame is executed. if (aStatus == Closing) { + if (mSyncLoopStack.IsEmpty()) { + // Here we use a normal runnable to know when the current JS chunk of code + // is finished. We cannot use a WorkerRunnable because they are not + // accepted any more by the worker, and we do not want to use a + // WorkerControlRunnable because they are immediately executed. + RefPtr<CancelingRunnable> r = new CancelingRunnable(); + mThread->nsThread::Dispatch(r.forget(), NS_DISPATCH_NORMAL); + } return true; } MOZ_ASSERT(aStatus == Terminating || aStatus == Canceling || aStatus == Killing); // Always abort the script.
--- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -258,22 +258,18 @@ public: DoRunLoop(JSContext* aCx); bool InterruptCallback(JSContext* aCx); bool IsOnCurrentThread(); - bool - CloseInternal() - { - AssertIsOnWorkerThread(); - return NotifyInternal(Closing); - } + void + CloseInternal(); bool FreezeInternal(); bool ThawInternal(); void