Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(753)

Unified Diff: third_party/WebKit/Source/core/workers/WorkerThread.cpp

Issue 1978163002: Worker: Initiate worker thread shutdown always on the main thread (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address kinuko's comments Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/core/workers/WorkerThread.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/workers/WorkerThread.cpp
diff --git a/third_party/WebKit/Source/core/workers/WorkerThread.cpp b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
index 2df2a5ffec5362845b46e7bfd7fa33cca75aacea..e98767bbb1badde01a636a3c9a84cbd2c9d6f94d 100644
--- a/third_party/WebKit/Source/core/workers/WorkerThread.cpp
+++ b/third_party/WebKit/Source/core/workers/WorkerThread.cpp
@@ -71,8 +71,12 @@ public:
if (WorkerOrWorkletScriptController* scriptController = globalScope->scriptController())
scriptController->getRejectedPromises()->processQueue();
if (globalScope->isClosing()) {
+ // |m_workerThread| will eventually be requested to terminate.
m_workerThread->workerReportingProxy().workerGlobalScopeClosed();
- m_workerThread->terminateFromWorkerThread();
+
+ // Dispose WorkerGlobalScope to stop associated ActiveDOMObjects
+ // and close the event queue.
+ m_workerThread->prepareForShutdown();
}
}
}
@@ -104,6 +108,12 @@ unsigned WorkerThread::workerThreadCount()
void WorkerThread::performTask(std::unique_ptr<ExecutionContextTask> task, bool isInstrumented)
{
DCHECK(isCurrentThread());
+ {
+ MutexLocker lock(m_threadStateMutex);
+ if (m_readyToShutdown)
+ return;
+ }
+
WorkerGlobalScope* globalScope = workerGlobalScope();
// If the thread is terminated before it had a chance initialize (see
// WorkerThread::Initialize()), we mustn't run any of the posted tasks.
@@ -128,13 +138,7 @@ std::unique_ptr<CrossThreadClosure> WorkerThread::createWorkerThreadTask(std::un
}
WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, WorkerReportingProxy& workerReportingProxy)
- : m_started(false)
- , m_terminated(false)
- , m_shutdown(false)
- , m_pausedInDebugger(false)
- , m_runningDebuggerTask(false)
- , m_shouldTerminateV8Execution(false)
- , m_inspectorTaskRunner(adoptPtr(new InspectorTaskRunner()))
+ : m_inspectorTaskRunner(adoptPtr(new InspectorTaskRunner()))
, m_workerLoaderProxy(workerLoaderProxy)
, m_workerReportingProxy(workerReportingProxy)
, m_terminationEvent(adoptPtr(new WaitableEvent(
@@ -234,29 +238,16 @@ void WorkerThread::initialize(PassOwnPtr<WorkerThreadStartupData> startupData)
postInitialize();
}
-void WorkerThread::shutdown()
+void WorkerThread::performShutdownTask()
{
DCHECK(isCurrentThread());
+#if DCHECK_IS_ON
{
MutexLocker lock(m_threadStateMutex);
- if (m_shutdown)
- return;
- m_shutdown = true;
+ DCHECK(m_terminated);
+ DCHECK(m_readyToShutdown);
}
-
- // This should be called before we start the shutdown procedure.
- workerReportingProxy().willDestroyWorkerGlobalScope();
-
- InspectorInstrumentation::allAsyncTasksCanceled(workerGlobalScope());
- workerGlobalScope()->dispose();
-
- workerBackingThread().backingThread().removeTaskObserver(m_microtaskRunner.get());
- postTask(BLINK_FROM_HERE, createSameThreadTask(&WorkerThread::performShutdownTask, this));
-}
-
-void WorkerThread::performShutdownTask()
-{
- DCHECK(isCurrentThread());
+#endif
// The below assignment will destroy the context, which will in turn notify
// messaging proxy. We cannot let any objects survive past thread exit,
@@ -298,43 +289,47 @@ void WorkerThread::terminate()
if (m_terminationEvent)
m_terminationEvent->signal();
- // If the thread has already initiated shutdown, just return.
- if (m_shutdown)
- return;
-
// If the worker thread was never initialized, don't start another
// shutdown, but still wait for the thread to signal when shutdown has
// completed on initialize().
if (!m_workerGlobalScope)
return;
- // Ensure that tasks are being handled by thread event loop. If script
- // execution weren't forbidden, a while(1) loop in JS could keep the thread
- // alive forever.
- m_workerGlobalScope->scriptController()->willScheduleExecutionTermination();
-
- if (workerBackingThread().workerScriptCount() == 1) {
- // This condition is not entirely correct because other scripts
- // can be being initialized or terminated simuletaneously. Though this
+ if (!m_readyToShutdown) {
+ // Ensure that tasks are being handled by thread event loop. If script
+ // execution weren't forbidden, a while(1) loop in JS could keep the
+ // thread alive forever.
+ // If |m_readyToShutdown| is set, the worker thread has already noticed
+ // that the thread is about to be terminated and the worker global scope
+ // is already disposed, so we don't have to explicitly terminate the
+ // execution.
+ m_workerGlobalScope->scriptController()->willScheduleExecutionTermination();
+
+ // This condition is not entirely correct because other scripts can
+ // be being initialized or terminated simuletaneously. Though this
// function itself is protected by a mutex, it is possible that
// |workerScriptCount()| here is not consistent with that in
// |initialize| and |shutdown|.
- // TODO(yhirano): TerminateExecution should be called more carefully.
- // https://crbug.com/413518
- if (m_runningDebuggerTask) {
- // Terminating during debugger task may lead to crash due to heavy
- // use of v8 api in debugger. Any debugger task is guaranteed to
- // finish, so we can postpone termination after task has finished.
- // Note: m_runningDebuggerTask and m_shouldTerminateV8Execution
- // access must be guarded by the lock.
- m_shouldTerminateV8Execution = true;
- } else {
- isolate()->TerminateExecution();
+ if (workerBackingThread().workerScriptCount() == 1) {
+ if (m_runningDebuggerTask) {
+ // Terminating during debugger task may lead to crash due to
+ // heavy use of v8 api in debugger. Any debugger task is
+ // guaranteed to finish, so we can postpone termination after
+ // task has finished.
+ // Note: m_runningDebuggerTask and m_shouldTerminateV8Execution
+ // access must be guarded by the lock.
+ m_shouldTerminateV8Execution = true;
+ } else {
+ // TODO(yhirano): TerminateExecution should be called more
+ // carefully (https://crbug.com/413518).
+ isolate()->TerminateExecution();
+ }
}
}
m_inspectorTaskRunner->kill();
- workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::shutdown, AllowCrossThreadAccess(this)));
+ workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::prepareForShutdown, AllowCrossThreadAccess(this)));
+ workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&WorkerThread::performShutdownTask, AllowCrossThreadAccess(this)));
}
void WorkerThread::terminateAndWait()
@@ -358,10 +353,20 @@ void WorkerThread::terminateAndWaitForAllWorkers()
thread->m_shutdownEvent->wait();
}
-void WorkerThread::terminateFromWorkerThread()
+void WorkerThread::prepareForShutdown()
{
DCHECK(isCurrentThread());
- shutdown();
+ {
+ MutexLocker lock(m_threadStateMutex);
+ if (m_readyToShutdown)
+ return;
+ m_readyToShutdown = true;
+ }
+
+ workerReportingProxy().willDestroyWorkerGlobalScope();
+ InspectorInstrumentation::allAsyncTasksCanceled(workerGlobalScope());
+ workerGlobalScope()->dispose();
+ workerBackingThread().backingThread().removeTaskObserver(m_microtaskRunner.get());
}
WorkerGlobalScope* WorkerThread::workerGlobalScope()
@@ -403,7 +408,7 @@ void WorkerThread::appendDebuggerTask(std::unique_ptr<CrossThreadClosure> task)
{
{
MutexLocker lock(m_threadStateMutex);
- if (m_shutdown)
+ if (m_readyToShutdown)
return;
}
m_inspectorTaskRunner->appendTask(threadSafeBind(&WorkerThread::runDebuggerTask, AllowCrossThreadAccess(this), passed(std::move(task))));
« no previous file with comments | « third_party/WebKit/Source/core/workers/WorkerThread.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698