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

Side by Side Diff: third_party/WebKit/Source/core/workers/WorkerThread.cpp

Issue 2011763002: Worker: Attempt to gracefully terminate WorkerThread as much as possible (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@reorder_functions
Patch Set: fix test expectations Created 4 years, 6 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 24 matching lines...) Expand all
35 #include "core/inspector/WorkerThreadDebugger.h" 35 #include "core/inspector/WorkerThreadDebugger.h"
36 #include "core/workers/WorkerBackingThread.h" 36 #include "core/workers/WorkerBackingThread.h"
37 #include "core/workers/WorkerClients.h" 37 #include "core/workers/WorkerClients.h"
38 #include "core/workers/WorkerReportingProxy.h" 38 #include "core/workers/WorkerReportingProxy.h"
39 #include "core/workers/WorkerThreadStartupData.h" 39 #include "core/workers/WorkerThreadStartupData.h"
40 #include "platform/ThreadSafeFunctional.h" 40 #include "platform/ThreadSafeFunctional.h"
41 #include "platform/WaitableEvent.h" 41 #include "platform/WaitableEvent.h"
42 #include "platform/WebThreadSupportingGC.h" 42 #include "platform/WebThreadSupportingGC.h"
43 #include "platform/heap/SafePoint.h" 43 #include "platform/heap/SafePoint.h"
44 #include "platform/heap/ThreadState.h" 44 #include "platform/heap/ThreadState.h"
45 #include "platform/scheduler/CancellableTaskFactory.h"
45 #include "platform/weborigin/KURL.h" 46 #include "platform/weborigin/KURL.h"
46 #include "public/platform/WebThread.h" 47 #include "public/platform/WebThread.h"
47 #include "wtf/Functional.h" 48 #include "wtf/Functional.h"
48 #include "wtf/Noncopyable.h" 49 #include "wtf/Noncopyable.h"
49 #include "wtf/text/WTFString.h" 50 #include "wtf/text/WTFString.h"
50 #include <limits.h> 51 #include <limits.h>
51 52
52 namespace blink { 53 namespace blink {
53 54
54 class WorkerThread::WorkerMicrotaskRunner : public WebThread::TaskObserver { 55 // TODO(nhiroki): Adjust the delay based on UMA.
56 const long long kForceTerminationDelayInMs = 2000; // 2 secs
57
58 // ForceTerminationTask is used for posting a delayed task to terminate the
59 // worker execution from the main thread. This task is expected to run when the
60 // shutdown sequence does not start in a certain time period because of an
61 // inifite loop in the JS execution context etc. When the shutdown sequence is
62 // started before this task runs, the task is simply cancelled.
63 class WorkerThread::ForceTerminationTask final {
64 public:
65 static PassOwnPtr<ForceTerminationTask> create(WorkerThread* workerThread)
66 {
67 return adoptPtr(new ForceTerminationTask(workerThread));
68 }
69
70 void schedule()
71 {
72 DCHECK(isMainThread());
73 Platform::current()->mainThread()->getWebTaskRunner()->postDelayedTask(B LINK_FROM_HERE, m_cancellableTaskFactory->cancelAndCreate(), m_workerThread->m_f orceTerminationDelayInMs);
74 }
75
76 private:
77 explicit ForceTerminationTask(WorkerThread* workerThread)
78 : m_workerThread(workerThread)
79 {
80 DCHECK(isMainThread());
81 m_cancellableTaskFactory = CancellableTaskFactory::create(this, &ForceTe rminationTask::run);
82 }
83
84 void run()
85 {
86 DCHECK(isMainThread());
87 MutexLocker lock(m_workerThread->m_threadStateMutex);
88 if (m_workerThread->m_readyToShutdown) {
89 // Shutdown sequence is now running. Just return.
90 return;
91 }
92
93 m_workerThread->forciblyTerminateExecution();
94 DCHECK_EQ(WorkerThread::ExitCode::NotTerminated, m_workerThread->m_exitC ode);
95 m_workerThread->m_exitCode = WorkerThread::ExitCode::AsyncForciblyTermin ated;
96 }
97
98 WorkerThread* m_workerThread;
99 OwnPtr<CancellableTaskFactory> m_cancellableTaskFactory;
100 };
101
102 class WorkerThread::WorkerMicrotaskRunner final : public WebThread::TaskObserver {
55 public: 103 public:
56 explicit WorkerMicrotaskRunner(WorkerThread* workerThread) 104 explicit WorkerMicrotaskRunner(WorkerThread* workerThread)
57 : m_workerThread(workerThread) 105 : m_workerThread(workerThread)
58 { 106 {
59 } 107 }
60 108
61 void willProcessTask() override 109 void willProcessTask() override
62 { 110 {
63 // No tasks should get executed after we have closed. 111 // No tasks should get executed after we have closed.
64 DCHECK(!m_workerThread->workerGlobalScope() || !m_workerThread->workerGl obalScope()->isClosing()); 112 DCHECK(!m_workerThread->workerGlobalScope() || !m_workerThread->workerGl obalScope()->isClosing());
(...skipping 28 matching lines...) Expand all
93 } 141 }
94 142
95 static HashSet<WorkerThread*>& workerThreads() 143 static HashSet<WorkerThread*>& workerThreads()
96 { 144 {
97 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); 145 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ());
98 return threads; 146 return threads;
99 } 147 }
100 148
101 WorkerThread::~WorkerThread() 149 WorkerThread::~WorkerThread()
102 { 150 {
151 DCHECK(isMainThread());
103 MutexLocker lock(threadSetMutex()); 152 MutexLocker lock(threadSetMutex());
104 DCHECK(workerThreads().contains(this)); 153 DCHECK(workerThreads().contains(this));
105 workerThreads().remove(this); 154 workerThreads().remove(this);
155
156 // TODO(nhiroki): Record how this thread is terminated (i.e. m_exitCode)
157 // in UMA.
158 DCHECK_NE(ExitCode::NotTerminated, m_exitCode);
106 } 159 }
107 160
108 void WorkerThread::start(PassOwnPtr<WorkerThreadStartupData> startupData) 161 void WorkerThread::start(PassOwnPtr<WorkerThreadStartupData> startupData)
109 { 162 {
110 DCHECK(isMainThread()); 163 DCHECK(isMainThread());
111 164
112 if (m_started) 165 if (m_started)
113 return; 166 return;
114 167
115 m_started = true; 168 m_started = true;
116 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBi nd(&WorkerThread::initializeOnWorkerThread, AllowCrossThreadAccess(this), passed (std::move(startupData)))); 169 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBi nd(&WorkerThread::initializeOnWorkerThread, AllowCrossThreadAccess(this), passed (std::move(startupData))));
117 } 170 }
118 171
119 void WorkerThread::terminate() 172 void WorkerThread::terminate()
120 { 173 {
121 DCHECK(isMainThread()); 174 DCHECK(isMainThread());
122 175 terminateInternal(TerminationMode::Graceful);
123 // Prevent the deadlock between GC and an attempt to terminate a thread.
124 SafePointScope safePointScope(BlinkGC::HeapPointersOnStack);
125
126 // Protect against this method, initializeOnWorkerThread() or termination
127 // via the global scope racing each other.
128 MutexLocker lock(m_threadStateMutex);
129
130 // If terminate has already been called, just return.
131 if (m_terminated)
132 return;
133 m_terminated = true;
134
135 // Signal the thread to notify that the thread's stopping.
136 if (m_terminationEvent)
137 m_terminationEvent->signal();
138
139 // If the worker thread was never initialized, don't start another
140 // shutdown, but still wait for the thread to signal when shutdown has
141 // completed on initializeOnWorkerThread().
142 if (!m_workerGlobalScope)
143 return;
144
145 // Determine if we should terminate the isolate so that the task can
146 // be handled by thread event loop. If script execution weren't forbidden,
147 // a while(1) loop in JS could keep the thread alive forever.
148 //
149 // (1) |m_readyToShutdown|: It this is set, the worker thread has already
150 // noticed that the thread is about to be terminated and the worker global
151 // scope is already disposed, so we don't have to explicitly terminate the
152 // isolate.
153 //
154 // (2) |workerScriptCount() == 1|: If other WorkerGlobalScopes are running
155 // on the worker thread, we should not terminate the isolate. This condition
156 // is not entirely correct because other scripts can be being initialized or
157 // terminated simuletaneously. Though this function itself is protected by a
158 // mutex, it is possible that |workerScriptCount()| here is not consistent
159 // with that in |initialize| and |shutdown|.
160 //
161 // (3) |m_runningDebuggerTask|: Terminating during debugger task may lead to
162 // crash due to heavy use of v8 api in debugger. Any debugger task is
163 // guaranteed to finish, so we can wait for the completion.
164 bool shouldTerminateIsolate = !m_readyToShutdown && (workerBackingThread().w orkerScriptCount() == 1) && !m_runningDebuggerTask;
165
166 if (shouldTerminateIsolate) {
167 // TODO(yhirano): TerminateExecution should be called more
168 // carefully (https://crbug.com/413518).
169 m_workerGlobalScope->scriptController()->willScheduleExecutionTerminatio n();
170 isolate()->TerminateExecution();
171 }
172
173 m_inspectorTaskRunner->kill();
174 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBi nd(&WorkerThread::prepareForShutdownOnWorkerThread, AllowCrossThreadAccess(this) ));
175 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBi nd(&WorkerThread::performShutdownOnWorkerThread, AllowCrossThreadAccess(this)));
176 } 176 }
177 177
178 void WorkerThread::terminateAndWait() 178 void WorkerThread::terminateAndWait()
179 { 179 {
180 DCHECK(isMainThread()); 180 DCHECK(isMainThread());
181 terminate(); 181
182 // The main thread will be blocked, so asynchronous graceful shutdown does
183 // not work.
184 terminateInternal(TerminationMode::Forcible);
182 m_shutdownEvent->wait(); 185 m_shutdownEvent->wait();
183 } 186 }
184 187
185 void WorkerThread::terminateAndWaitForAllWorkers() 188 void WorkerThread::terminateAndWaitForAllWorkers()
186 { 189 {
187 DCHECK(isMainThread()); 190 DCHECK(isMainThread());
188 191
189 // Keep this lock to prevent WorkerThread instances from being destroyed. 192 // Keep this lock to prevent WorkerThread instances from being destroyed.
190 MutexLocker lock(threadSetMutex()); 193 MutexLocker lock(threadSetMutex());
191 HashSet<WorkerThread*> threads = workerThreads(); 194 HashSet<WorkerThread*> threads = workerThreads();
195
196 // The main thread will be blocked, so asynchronous graceful shutdown does
197 // not work.
192 for (WorkerThread* thread : threads) 198 for (WorkerThread* thread : threads)
193 thread->terminate(); 199 thread->terminateInternal(TerminationMode::Forcible);
194 200
195 for (WorkerThread* thread : threads) 201 for (WorkerThread* thread : threads)
196 thread->m_shutdownEvent->wait(); 202 thread->m_shutdownEvent->wait();
197 } 203 }
198 204
199 v8::Isolate* WorkerThread::isolate() 205 v8::Isolate* WorkerThread::isolate()
200 { 206 {
201 return workerBackingThread().isolate(); 207 return workerBackingThread().isolate();
202 } 208 }
203 209
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 } 274 }
269 275
270 PlatformThreadId WorkerThread::platformThreadId() 276 PlatformThreadId WorkerThread::platformThreadId()
271 { 277 {
272 if (!m_started) 278 if (!m_started)
273 return 0; 279 return 0;
274 return workerBackingThread().backingThread().platformThread().threadId(); 280 return workerBackingThread().backingThread().platformThread().threadId();
275 } 281 }
276 282
277 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work erReportingProxy& workerReportingProxy) 283 WorkerThread::WorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, Work erReportingProxy& workerReportingProxy)
278 : m_inspectorTaskRunner(adoptPtr(new InspectorTaskRunner())) 284 : m_forceTerminationDelayInMs(kForceTerminationDelayInMs)
285 , m_inspectorTaskRunner(adoptPtr(new InspectorTaskRunner()))
279 , m_workerLoaderProxy(workerLoaderProxy) 286 , m_workerLoaderProxy(workerLoaderProxy)
280 , m_workerReportingProxy(workerReportingProxy) 287 , m_workerReportingProxy(workerReportingProxy)
281 , m_terminationEvent(adoptPtr(new WaitableEvent( 288 , m_terminationEvent(adoptPtr(new WaitableEvent(
282 WaitableEvent::ResetPolicy::Manual, 289 WaitableEvent::ResetPolicy::Manual,
283 WaitableEvent::InitialState::NonSignaled))) 290 WaitableEvent::InitialState::NonSignaled)))
284 , m_shutdownEvent(adoptPtr(new WaitableEvent( 291 , m_shutdownEvent(adoptPtr(new WaitableEvent(
285 WaitableEvent::ResetPolicy::Manual, 292 WaitableEvent::ResetPolicy::Manual,
286 WaitableEvent::InitialState::NonSignaled))) 293 WaitableEvent::InitialState::NonSignaled)))
287 { 294 {
288 MutexLocker lock(threadSetMutex()); 295 MutexLocker lock(threadSetMutex());
289 workerThreads().add(this); 296 workerThreads().add(this);
290 } 297 }
291 298
292 std::unique_ptr<CrossThreadClosure> WorkerThread::createWorkerThreadTask(std::un ique_ptr<ExecutionContextTask> task, bool isInstrumented) 299 std::unique_ptr<CrossThreadClosure> WorkerThread::createWorkerThreadTask(std::un ique_ptr<ExecutionContextTask> task, bool isInstrumented)
293 { 300 {
294 if (isInstrumented) 301 if (isInstrumented)
295 isInstrumented = !task->taskNameForInstrumentation().isEmpty(); 302 isInstrumented = !task->taskNameForInstrumentation().isEmpty();
296 if (isInstrumented) { 303 if (isInstrumented) {
297 DCHECK(isCurrentThread()); 304 DCHECK(isCurrentThread());
298 InspectorInstrumentation::asyncTaskScheduled(workerGlobalScope(), "Worke r task", task.get()); 305 InspectorInstrumentation::asyncTaskScheduled(workerGlobalScope(), "Worke r task", task.get());
299 } 306 }
300 return threadSafeBind(&WorkerThread::performTaskOnWorkerThread, AllowCrossTh readAccess(this), passed(std::move(task)), isInstrumented); 307 return threadSafeBind(&WorkerThread::performTaskOnWorkerThread, AllowCrossTh readAccess(this), passed(std::move(task)), isInstrumented);
301 } 308 }
302 309
310 void WorkerThread::terminateInternal(TerminationMode mode)
311 {
312 // Prevent the deadlock between GC and an attempt to terminate a thread.
313 SafePointScope safePointScope(BlinkGC::HeapPointersOnStack);
314
315 // Protect against this method, initializeOnWorkerThread() or termination
316 // via the global scope racing each other.
317 MutexLocker lock(m_threadStateMutex);
318
319 // If terminate has already been called.
320 if (m_terminated) {
321 // The synchronous forcible termination request should overtake the
322 // scheduled termination task because the request will block the main
323 // thread and the scheduled termination task never runs.
324 if (mode == TerminationMode::Forcible && m_exitCode == ExitCode::NotTerm inated) {
325 DCHECK(m_scheduledForceTerminationTask);
326 m_scheduledForceTerminationTask.reset();
327 forciblyTerminateExecution();
328 DCHECK_EQ(ExitCode::NotTerminated, m_exitCode);
329 m_exitCode = ExitCode::SyncForciblyTerminated;
330 }
331 return;
332 }
333 m_terminated = true;
334
335 // Signal the thread to notify that the thread's stopping.
336 if (m_terminationEvent)
337 m_terminationEvent->signal();
338
339 // If the worker thread was never initialized, don't start another
340 // shutdown, but still wait for the thread to signal when shutdown has
341 // completed.
342 if (!m_workerGlobalScope) {
343 // Post a task to notify the worker reporting proxy of shutdown. When
344 // |m_started| is set, it will be notified on initializeOnWorkerThread()
345 // instead.
346 if (!m_started)
kinuko 2016/06/02 02:31:28 I wonder if we should just DCHECK(m_started) in te
nhiroki 2016/06/02 06:20:20 It looks like the worker thread is always supposed
347 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, thre adSafeBind(&WorkerThread::notifyOfShutdownOnWorkerThread, AllowCrossThreadAccess (this)));
348 m_readyToShutdown = true;
349 DCHECK_EQ(ExitCode::NotTerminated, m_exitCode);
350 m_exitCode = ExitCode::TerminatedBeforeStarting;
351 return;
352 }
353
354 // Determine if we should synchronously terminate or schedule to terminate
355 // the worker execution so that the task can be handled by thread event
356 // loop. If script execution weren't forbidden, a while(1) loop in JS could
357 // keep the thread alive forever.
358 //
359 // (1) |m_readyToShutdown|: It this is set, the worker thread has already
360 // noticed that the thread is about to be terminated and the worker global
361 // scope is already disposed, so we don't have to explicitly terminate the
362 // worker execution.
363 //
364 // (2) |workerScriptCount() == 1|: If other WorkerGlobalScopes are running
365 // on the worker thread, we should not terminate the worker execution. This
366 // condition is not entirely correct because other scripts can be being
367 // initialized or terminated simuletaneously. Though this function itself is
368 // protected by a mutex, it is possible that |workerScriptCount()| here is
369 // not consistent with that in |initialize| and |shutdown|.
370 //
371 // (3) |m_runningDebuggerTask|: Terminating during debugger task may lead to
372 // crash due to heavy use of v8 api in debugger. Any debugger task is
373 // guaranteed to finish, so we can wait for the completion.
374 bool shouldScheduleToTerminateExecution = !m_readyToShutdown && (workerBacki ngThread().workerScriptCount() == 1) && !m_runningDebuggerTask;
375
376 if (shouldScheduleToTerminateExecution) {
377 if (mode == TerminationMode::Forcible) {
378 forciblyTerminateExecution();
379 DCHECK_EQ(ExitCode::NotTerminated, m_exitCode);
380 m_exitCode = ExitCode::SyncForciblyTerminated;
381 } else {
382 DCHECK_EQ(TerminationMode::Graceful, mode);
383 DCHECK(!m_scheduledForceTerminationTask);
384 m_scheduledForceTerminationTask = ForceTerminationTask::create(this) ;
385 m_scheduledForceTerminationTask->schedule();
386 }
387 }
388
389 m_inspectorTaskRunner->kill();
390 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBi nd(&WorkerThread::prepareForShutdownOnWorkerThread, AllowCrossThreadAccess(this) ));
391 workerBackingThread().backingThread().postTask(BLINK_FROM_HERE, threadSafeBi nd(&WorkerThread::performShutdownOnWorkerThread, AllowCrossThreadAccess(this)));
392 }
393
394 void WorkerThread::forciblyTerminateExecution()
395 {
396 DCHECK(m_workerGlobalScope);
397 m_workerGlobalScope->scriptController()->willScheduleExecutionTermination();
398 isolate()->TerminateExecution();
399 }
400
303 void WorkerThread::initializeOnWorkerThread(PassOwnPtr<WorkerThreadStartupData> startupData) 401 void WorkerThread::initializeOnWorkerThread(PassOwnPtr<WorkerThreadStartupData> startupData)
304 { 402 {
305 KURL scriptURL = startupData->m_scriptURL; 403 KURL scriptURL = startupData->m_scriptURL;
306 String sourceCode = startupData->m_sourceCode; 404 String sourceCode = startupData->m_sourceCode;
307 WorkerThreadStartMode startMode = startupData->m_startMode; 405 WorkerThreadStartMode startMode = startupData->m_startMode;
308 OwnPtr<Vector<char>> cachedMetaData = std::move(startupData->m_cachedMetaDat a); 406 OwnPtr<Vector<char>> cachedMetaData = std::move(startupData->m_cachedMetaDat a);
309 V8CacheOptions v8CacheOptions = startupData->m_v8CacheOptions; 407 V8CacheOptions v8CacheOptions = startupData->m_v8CacheOptions;
310 408
311 { 409 {
312 MutexLocker lock(m_threadStateMutex); 410 MutexLocker lock(m_threadStateMutex);
313 411
314 // The worker was terminated before the thread had a chance to run. 412 // The worker was terminated before the thread had a chance to run.
315 if (m_terminated) { 413 if (m_terminated) {
316 // Notify the proxy that the WorkerGlobalScope has been disposed of. 414 // In this case the shutdown sequence does not run, so notify of
317 // This can free this thread object, hence it must not be touched 415 // thread shutdown here instead.
318 // afterwards. 416 notifyOfShutdownOnWorkerThread();
319 m_workerReportingProxy.workerThreadTerminated();
320
321 // Notify the main thread that it is safe to deallocate our
322 // resources.
323 m_shutdownEvent->signal();
324 return; 417 return;
325 } 418 }
326 419
327 workerBackingThread().attach(); 420 workerBackingThread().attach();
328 421
329 if (shouldAttachThreadDebugger()) 422 if (shouldAttachThreadDebugger())
330 V8PerIsolateData::from(isolate())->setThreadDebugger(adoptPtr(new Wo rkerThreadDebugger(this, isolate()))); 423 V8PerIsolateData::from(isolate())->setThreadDebugger(adoptPtr(new Wo rkerThreadDebugger(this, isolate())));
331 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); 424 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this));
332 workerBackingThread().backingThread().addTaskObserver(m_microtaskRunner. get()); 425 workerBackingThread().backingThread().addTaskObserver(m_microtaskRunner. get());
333 426
(...skipping 28 matching lines...) Expand all
362 } 455 }
363 456
364 void WorkerThread::prepareForShutdownOnWorkerThread() 457 void WorkerThread::prepareForShutdownOnWorkerThread()
365 { 458 {
366 DCHECK(isCurrentThread()); 459 DCHECK(isCurrentThread());
367 { 460 {
368 MutexLocker lock(m_threadStateMutex); 461 MutexLocker lock(m_threadStateMutex);
369 if (m_readyToShutdown) 462 if (m_readyToShutdown)
370 return; 463 return;
371 m_readyToShutdown = true; 464 m_readyToShutdown = true;
465 if (m_exitCode == ExitCode::NotTerminated)
466 m_exitCode = ExitCode::GracefullyTerminated;
372 } 467 }
373 468
374 workerReportingProxy().willDestroyWorkerGlobalScope(); 469 workerReportingProxy().willDestroyWorkerGlobalScope();
375 InspectorInstrumentation::allAsyncTasksCanceled(workerGlobalScope()); 470 InspectorInstrumentation::allAsyncTasksCanceled(workerGlobalScope());
376 workerGlobalScope()->dispose(); 471 workerGlobalScope()->dispose();
377 workerBackingThread().backingThread().removeTaskObserver(m_microtaskRunner.g et()); 472 workerBackingThread().backingThread().removeTaskObserver(m_microtaskRunner.g et());
378 } 473 }
379 474
380 void WorkerThread::performShutdownOnWorkerThread() 475 void WorkerThread::performShutdownOnWorkerThread()
381 { 476 {
(...skipping 12 matching lines...) Expand all
394 // is enabled, we detach of the context/global scope, with the final heap 489 // is enabled, we detach of the context/global scope, with the final heap
395 // cleanup below sweeping it out. 490 // cleanup below sweeping it out.
396 m_workerGlobalScope->notifyContextDestroyed(); 491 m_workerGlobalScope->notifyContextDestroyed();
397 m_workerGlobalScope = nullptr; 492 m_workerGlobalScope = nullptr;
398 493
399 workerBackingThread().detach(); 494 workerBackingThread().detach();
400 // We must not touch workerBackingThread() from now on. 495 // We must not touch workerBackingThread() from now on.
401 496
402 m_microtaskRunner = nullptr; 497 m_microtaskRunner = nullptr;
403 498
404 // Notify the proxy that the WorkerGlobalScope has been disposed of. 499 notifyOfShutdownOnWorkerThread();
405 // This can free this thread object, hence it must not be touched afterwards . 500 }
501
502 void WorkerThread::notifyOfShutdownOnWorkerThread()
503 {
504 #if DCHECK_IS_ON
505 {
506 MutexLocker lock(m_threadStateMutex);
507 DCHECK(m_terminated);
508 DCHECK(m_readyToShutdown);
509 }
510 #endif
511 DCHECK(!m_workerGlobalScope);
512
513 // Notify the proxy that the WorkerGlobalScope has been disposed of. This
514 // can free this thread object, hence it must not be touched afterwards.
406 workerReportingProxy().workerThreadTerminated(); 515 workerReportingProxy().workerThreadTerminated();
407 516
408 m_shutdownEvent->signal(); 517 m_shutdownEvent->signal();
409 } 518 }
410 519
411 void WorkerThread::performTaskOnWorkerThread(std::unique_ptr<ExecutionContextTas k> task, bool isInstrumented) 520 void WorkerThread::performTaskOnWorkerThread(std::unique_ptr<ExecutionContextTas k> task, bool isInstrumented)
412 { 521 {
413 DCHECK(isCurrentThread()); 522 DCHECK(isCurrentThread());
414 { 523 {
415 MutexLocker lock(m_threadStateMutex); 524 MutexLocker lock(m_threadStateMutex);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 } 562 }
454 563
455 void WorkerThread::runDebuggerTaskDontWaitOnWorkerThread() 564 void WorkerThread::runDebuggerTaskDontWaitOnWorkerThread()
456 { 565 {
457 DCHECK(isCurrentThread()); 566 DCHECK(isCurrentThread());
458 std::unique_ptr<CrossThreadClosure> task = m_inspectorTaskRunner->takeNextTa sk(InspectorTaskRunner::DontWaitForTask); 567 std::unique_ptr<CrossThreadClosure> task = m_inspectorTaskRunner->takeNextTa sk(InspectorTaskRunner::DontWaitForTask);
459 if (task) 568 if (task)
460 (*task)(); 569 (*task)();
461 } 570 }
462 571
572 WorkerThread::ExitCode WorkerThread::getExitCode()
573 {
574 MutexLocker lock(m_threadStateMutex);
575 return m_exitCode;
576 }
577
463 } // namespace blink 578 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/workers/WorkerThread.h ('k') | third_party/WebKit/Source/core/workers/WorkerThreadTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698