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

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

Issue 1134933003: Revert of Remove the concept of a cleanup task (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/workers/WorkerThread.h ('k') | Source/modules/webdatabase/DatabaseThread.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 #include "wtf/Noncopyable.h" 51 #include "wtf/Noncopyable.h"
52 #include "wtf/WeakPtr.h" 52 #include "wtf/WeakPtr.h"
53 #include "wtf/text/WTFString.h" 53 #include "wtf/text/WTFString.h"
54 54
55 namespace blink { 55 namespace blink {
56 56
57 namespace { 57 namespace {
58 const int64_t kShortIdleHandlerDelayMs = 1000; 58 const int64_t kShortIdleHandlerDelayMs = 1000;
59 const int64_t kLongIdleHandlerDelayMs = 10*1000; 59 const int64_t kLongIdleHandlerDelayMs = 10*1000;
60 60
61 } // namespace 61 class MicrotaskRunner : public WebThread::TaskObserver {
62
63 class WorkerMicrotaskRunner : public WebThread::TaskObserver {
64 public: 62 public:
65 explicit WorkerMicrotaskRunner(WorkerThread* workerThread) 63 explicit MicrotaskRunner(WorkerThread* workerThread)
66 : m_workerThread(workerThread) 64 : m_workerThread(workerThread)
67 { 65 {
68 } 66 }
69 67
70 virtual void willProcessTask() override 68 virtual void willProcessTask() override { }
71 {
72 // No tasks should get executed after we have closed.
73 WorkerGlobalScope* globalScope = m_workerThread->workerGlobalScope();
74 ASSERT_UNUSED(globalScope, !globalScope || !globalScope->isClosing());
75 }
76
77 virtual void didProcessTask() override 69 virtual void didProcessTask() override
78 { 70 {
79 Microtask::performCheckpoint(); 71 Microtask::performCheckpoint();
80 if (WorkerGlobalScope* globalScope = m_workerThread->workerGlobalScope() ) { 72 if (WorkerGlobalScope* globalScope = m_workerThread->workerGlobalScope() ) {
81 if (WorkerScriptController* scriptController = globalScope->script() ) 73 if (WorkerScriptController* scriptController = globalScope->script() )
82 scriptController->rejectedPromises()->processQueue(); 74 scriptController->rejectedPromises()->processQueue();
83 if (globalScope->isClosing()) {
84 m_workerThread->workerReportingProxy().workerGlobalScopeClosed() ;
85 m_workerThread->shutdown();
86 }
87 } 75 }
88 } 76 }
89 77
90 private: 78 private:
91 // Thread owns the microtask runner; reference remains 79 // Thread owns the microtask runner; reference remains
92 // valid for the lifetime of this object. 80 // valid for the lifetime of this object.
93 WorkerThread* m_workerThread; 81 WorkerThread* m_workerThread;
94 }; 82 };
95 83
84 } // namespace
85
96 static Mutex& threadSetMutex() 86 static Mutex& threadSetMutex()
97 { 87 {
98 AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex); 88 AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex);
99 return mutex; 89 return mutex;
100 } 90 }
101 91
102 static HashSet<WorkerThread*>& workerThreads() 92 static HashSet<WorkerThread*>& workerThreads()
103 { 93 {
104 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ()); 94 DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ());
105 return threads; 95 return threads;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO wnPtr<ExecutionContextTask> task, bool isInstrumented) 201 static PassOwnPtr<WorkerThreadTask> create(WorkerThread& workerThread, PassO wnPtr<ExecutionContextTask> task, bool isInstrumented)
212 { 202 {
213 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented) ); 203 return adoptPtr(new WorkerThreadTask(workerThread, task, isInstrumented) );
214 } 204 }
215 205
216 virtual ~WorkerThreadTask() { } 206 virtual ~WorkerThreadTask() { }
217 207
218 virtual void run() override 208 virtual void run() override
219 { 209 {
220 WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope( ); 210 WorkerGlobalScope* workerGlobalScope = m_workerThread.workerGlobalScope( );
221 ASSERT(workerGlobalScope); 211 // Tasks could be put on the message loop after the cleanup task,
212 // ensure none of those are ran.
213 if (!workerGlobalScope)
214 return;
222 215
223 if (m_isInstrumented) 216 if (m_isInstrumented)
224 InspectorInstrumentation::willPerformExecutionContextTask(workerGlob alScope, m_task.get()); 217 InspectorInstrumentation::willPerformExecutionContextTask(workerGlob alScope, m_task.get());
225 m_task->performTask(workerGlobalScope); 218 if ((!workerGlobalScope->isClosing() && !m_workerThread.terminated()) || m_task->isCleanupTask())
219 m_task->performTask(workerGlobalScope);
226 if (m_isInstrumented) 220 if (m_isInstrumented)
227 InspectorInstrumentation::didPerformExecutionContextTask(workerGloba lScope); 221 InspectorInstrumentation::didPerformExecutionContextTask(workerGloba lScope);
228 } 222 }
229 223
230 private: 224 private:
231 WorkerThreadTask(WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask > task, bool isInstrumented) 225 WorkerThreadTask(WorkerThread& workerThread, PassOwnPtr<ExecutionContextTask > task, bool isInstrumented)
232 : m_workerThread(workerThread) 226 : m_workerThread(workerThread)
233 , m_task(task) 227 , m_task(task)
234 , m_isInstrumented(isInstrumented) 228 , m_isInstrumented(isInstrumented)
235 { 229 {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 302
309 void WorkerThread::initialize() 303 void WorkerThread::initialize()
310 { 304 {
311 KURL scriptURL = m_startupData->m_scriptURL; 305 KURL scriptURL = m_startupData->m_scriptURL;
312 String sourceCode = m_startupData->m_sourceCode; 306 String sourceCode = m_startupData->m_sourceCode;
313 WorkerThreadStartMode startMode = m_startupData->m_startMode; 307 WorkerThreadStartMode startMode = m_startupData->m_startMode;
314 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas e(); 308 OwnPtr<Vector<char>> cachedMetaData = m_startupData->m_cachedMetaData.releas e();
315 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions; 309 V8CacheOptions v8CacheOptions = m_startupData->m_v8CacheOptions;
316 310
317 { 311 {
318 MutexLocker lock(m_threadStateMutex); 312 MutexLocker lock(m_threadCreationMutex);
319 313
320 // The worker was terminated before the thread had a chance to run. 314 // The worker was terminated before the thread had a chance to run.
321 if (m_terminated) { 315 if (m_terminated) {
322 // Notify the proxy that the WorkerGlobalScope has been disposed of. 316 // Notify the proxy that the WorkerGlobalScope has been disposed of.
323 // This can free this thread object, hence it must not be touched af terwards. 317 // This can free this thread object, hence it must not be touched af terwards.
324 m_workerReportingProxy.workerThreadTerminated(); 318 m_workerReportingProxy.workerThreadTerminated();
325 return; 319 return;
326 } 320 }
327 321
328 m_microtaskRunner = adoptPtr(new WorkerMicrotaskRunner(this)); 322 m_microtaskRunner = adoptPtr(new MicrotaskRunner(this));
329 backingThread().addTaskObserver(m_microtaskRunner.get()); 323 backingThread().addTaskObserver(m_microtaskRunner.get());
330 backingThread().initialize(); 324 backingThread().attachGC();
331 325
332 m_isolate = initializeIsolate(); 326 m_isolate = initializeIsolate();
333 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release()); 327 m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release());
334 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge t() ? cachedMetaData->size() : 0); 328 m_workerGlobalScope->scriptLoaded(sourceCode.length(), cachedMetaData.ge t() ? cachedMetaData->size() : 0);
335 329
336 PlatformThreadData::current().threadTimers().setSharedTimer(adoptPtr(new WorkerSharedTimer(this))); 330 PlatformThreadData::current().threadTimers().setSharedTimer(adoptPtr(new WorkerSharedTimer(this)));
337 } 331 }
338 332
339 // The corresponding call to stopRunLoop() is in ~WorkerScriptController(). 333 // The corresponding call to stopRunLoop() is in ~WorkerScriptController().
340 didStartRunLoop(); 334 didStartRunLoop();
(...skipping 10 matching lines...) Expand all
351 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip tCachedMetadataHandler(scriptURL, cachedMetaData.get())); 345 OwnPtr<CachedMetadataHandler> handler(workerGlobalScope()->createWorkerScrip tCachedMetadataHandler(scriptURL, cachedMetaData.get()));
352 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul lptr, handler.get(), v8CacheOptions); 346 bool success = script->evaluate(ScriptSourceCode(sourceCode, scriptURL), nul lptr, handler.get(), v8CacheOptions);
353 m_workerGlobalScope->didEvaluateWorkerScript(); 347 m_workerGlobalScope->didEvaluateWorkerScript();
354 m_workerReportingProxy.didEvaluateWorkerScript(success); 348 m_workerReportingProxy.didEvaluateWorkerScript(success);
355 349
356 postInitialize(); 350 postInitialize();
357 351
358 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler, this), kShortIdleHandlerDelayMs); 352 postDelayedTask(FROM_HERE, createSameThreadTask(&WorkerThread::idleHandler, this), kShortIdleHandlerDelayMs);
359 } 353 }
360 354
361 void WorkerThread::shutdown() 355 void WorkerThread::cleanup()
362 { 356 {
363 MutexLocker lock(m_threadStateMutex);
364 ASSERT(isCurrentThread());
365
366 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr);
367 workerGlobalScope()->dispose();
368 willDestroyIsolate();
369
370 // This should be called before we start the shutdown procedure. 357 // This should be called before we start the shutdown procedure.
371 workerReportingProxy().willDestroyWorkerGlobalScope(); 358 workerReportingProxy().willDestroyWorkerGlobalScope();
372 359
373 // The below assignment will destroy the context, which will in turn notify messaging proxy. 360 // The below assignment will destroy the context, which will in turn notify messaging proxy.
374 // We cannot let any objects survive past thread exit, because no other thre ad will run GC or otherwise destroy them. 361 // We cannot let any objects survive past thread exit, because no other thre ad will run GC or otherwise destroy them.
375 // If Oilpan is enabled, we detach of the context/global scope, with the fin al heap cleanup below sweeping it out. 362 // If Oilpan is enabled, we detach of the context/global scope, with the fin al heap cleanup below sweeping it out.
376 #if !ENABLE(OILPAN) 363 #if !ENABLE(OILPAN)
377 ASSERT(m_workerGlobalScope->hasOneRef()); 364 ASSERT(m_workerGlobalScope->hasOneRef());
378 #endif 365 #endif
379 m_workerGlobalScope->notifyContextDestroyed(); 366 m_workerGlobalScope->notifyContextDestroyed();
380 m_workerGlobalScope = nullptr; 367 m_workerGlobalScope = nullptr;
381 368
382 backingThread().removeTaskObserver(m_microtaskRunner.get()); 369 backingThread().detachGC();
383 backingThread().shutdown();
384 destroyIsolate(); 370 destroyIsolate();
385 371
372 backingThread().removeTaskObserver(m_microtaskRunner.get());
386 m_microtaskRunner = nullptr; 373 m_microtaskRunner = nullptr;
387 374
388 // Notify the proxy that the WorkerGlobalScope has been disposed of. 375 // Notify the proxy that the WorkerGlobalScope has been disposed of.
389 // This can free this thread object, hence it must not be touched afterwards . 376 // This can free this thread object, hence it must not be touched afterwards .
390 workerReportingProxy().workerThreadTerminated(); 377 workerReportingProxy().workerThreadTerminated();
391 378
392 m_terminationEvent->signal(); 379 m_terminationEvent->signal();
393 380
394 // Clean up PlatformThreadData before WTF::WTFThreadData goes away! 381 // Clean up PlatformThreadData before WTF::WTFThreadData goes away!
395 PlatformThreadData::current().destroy(); 382 PlatformThreadData::current().destroy();
396 } 383 }
397 384
385 class WorkerThreadShutdownFinishTask : public ExecutionContextTask {
386 public:
387 static PassOwnPtr<WorkerThreadShutdownFinishTask> create()
388 {
389 return adoptPtr(new WorkerThreadShutdownFinishTask());
390 }
391
392 virtual void performTask(ExecutionContext *context)
393 {
394 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
395 workerGlobalScope->dispose();
396
397 WorkerThread* workerThread = workerGlobalScope->thread();
398 workerThread->willDestroyIsolate();
399 workerThread->backingThread().postTask(FROM_HERE, new Task(WTF::bind(&Wo rkerThread::cleanup, workerThread)));
400 }
401
402 virtual bool isCleanupTask() const { return true; }
403 };
404
405 class WorkerThreadShutdownStartTask : public ExecutionContextTask {
406 public:
407 static PassOwnPtr<WorkerThreadShutdownStartTask> create()
408 {
409 return adoptPtr(new WorkerThreadShutdownStartTask());
410 }
411
412 virtual void performTask(ExecutionContext *context)
413 {
414 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
415 workerGlobalScope->stopActiveDOMObjects();
416 PlatformThreadData::current().threadTimers().setSharedTimer(nullptr);
417
418 // Event listeners would keep DOMWrapperWorld objects alive for too long . Also, they have references to JS objects,
419 // which become dangling once Heap is destroyed.
420 workerGlobalScope->removeAllEventListeners();
421
422 // Stick a shutdown command at the end of the queue, so that we deal
423 // with all the cleanup tasks the databases post first.
424 workerGlobalScope->postTask(FROM_HERE, WorkerThreadShutdownFinishTask::c reate());
425 }
426
427 virtual bool isCleanupTask() const { return true; }
428 };
398 429
399 void WorkerThread::stop() 430 void WorkerThread::stop()
400 { 431 {
401 // Prevent the deadlock between GC and an attempt to stop a thread. 432 // Prevent the deadlock between GC and an attempt to stop a thread.
402 SafePointScope safePointScope(ThreadState::HeapPointersOnStack); 433 SafePointScope safePointScope(ThreadState::HeapPointersOnStack);
403 stopInternal(); 434 stopInternal();
404 } 435 }
405 436
406 void WorkerThread::stopInShutdownSequence() 437 void WorkerThread::stopInShutdownSequence()
407 { 438 {
408 stopInternal(); 439 stopInternal();
409 } 440 }
410 441
411 void WorkerThread::terminateAndWait() 442 void WorkerThread::terminateAndWait()
412 { 443 {
413 stop(); 444 stop();
414 m_terminationEvent->wait(); 445 m_terminationEvent->wait();
415 } 446 }
416 447
417 bool WorkerThread::terminated() 448 bool WorkerThread::terminated()
418 { 449 {
419 MutexLocker lock(m_threadStateMutex); 450 MutexLocker lock(m_threadCreationMutex);
420 return m_terminated; 451 return m_terminated;
421 } 452 }
422 453
423 void WorkerThread::stopInternal() 454 void WorkerThread::stopInternal()
424 { 455 {
425 // Protect against this method, initialize() or termination via the global s cope racing each other. 456 // Protect against this method and initialize() racing each other.
426 MutexLocker lock(m_threadStateMutex); 457 MutexLocker lock(m_threadCreationMutex);
427 458
428 // If stop has already been called, just return. 459 // If stop has already been called, just return.
429 if (m_terminated) 460 if (m_terminated)
430 return; 461 return;
431 m_terminated = true; 462 m_terminated = true;
432 463
433 // Signal the thread to notify that the thread's stopping. 464 // Signal the thread to notify that the thread's stopping.
434 if (m_shutdownEvent) 465 if (m_shutdownEvent)
435 m_shutdownEvent->signal(); 466 m_shutdownEvent->signal();
436 467
437 if (!m_workerGlobalScope) 468 if (!m_workerGlobalScope)
438 return; 469 return;
439 470
440 // Ensure that tasks are being handled by thread event loop. If script execu tion weren't forbidden, a while(1) loop in JS could keep the thread alive foreve r. 471 // Ensure that tasks are being handled by thread event loop. If script execu tion weren't forbidden, a while(1) loop in JS could keep the thread alive foreve r.
441 terminateV8Execution(); 472 terminateV8Execution();
442 473
443 InspectorInstrumentation::didKillAllExecutionContextTasks(m_workerGlobalScop e.get()); 474 InspectorInstrumentation::didKillAllExecutionContextTasks(m_workerGlobalScop e.get());
444 m_debuggerMessageQueue.kill(); 475 m_debuggerMessageQueue.kill();
445 backingThread().postTask(FROM_HERE, new Task(threadSafeBind(&WorkerThread::s hutdown, AllowCrossThreadAccess(this)))); 476 postTask(FROM_HERE, WorkerThreadShutdownStartTask::create());
446 } 477 }
447 478
448 void WorkerThread::didStartRunLoop() 479 void WorkerThread::didStartRunLoop()
449 { 480 {
450 ASSERT(isCurrentThread()); 481 ASSERT(isCurrentThread());
451 Platform::current()->didStartWorkerRunLoop(); 482 Platform::current()->didStartWorkerRunLoop();
452 } 483 }
453 484
454 void WorkerThread::didStopRunLoop() 485 void WorkerThread::didStopRunLoop()
455 { 486 {
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get()); 606 InspectorInstrumentation::didLeaveNestedRunLoop(m_workerGlobalScope.get());
576 } 607 }
577 608
578 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke rInspectorController) 609 void WorkerThread::setWorkerInspectorController(WorkerInspectorController* worke rInspectorController)
579 { 610 {
580 MutexLocker locker(m_workerInspectorControllerMutex); 611 MutexLocker locker(m_workerInspectorControllerMutex);
581 m_workerInspectorController = workerInspectorController; 612 m_workerInspectorController = workerInspectorController;
582 } 613 }
583 614
584 } // namespace blink 615 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/workers/WorkerThread.h ('k') | Source/modules/webdatabase/DatabaseThread.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698