diff options
author | haraken@chromium.org <haraken@chromium.org@bbb929c8-8fbe-4397-9dbb-9b2b20218538> | 2014-06-23 13:20:34 +0000 |
---|---|---|
committer | haraken@chromium.org <haraken@chromium.org@bbb929c8-8fbe-4397-9dbb-9b2b20218538> | 2014-06-23 13:20:34 +0000 |
commit | b87d8d19de1e2c90c92eaeb4a7642ac021f24d46 (patch) | |
tree | 3b4069cab9fb59dc251a1a176388bccb0c9579a8 | |
parent | 0aafc788020037a39cf3e9d86522fc6091dd2515 (diff) | |
download | chromium-b87d8d19de1e2c90c92eaeb4a7642ac021f24d46.tar.gz chromium-b87d8d19de1e2c90c92eaeb4a7642ac021f24d46.tar.bz2 chromium-b87d8d19de1e2c90c92eaeb4a7642ac021f24d46.zip |
Bridge::destroy should wait for the completion of Peer::destroy
Bridge::initialize waits for the completion of Peer::initialize in order to avoid threading issues. Similarly, we should make Bridge::destroy wait for the completion of Peer::destroy to avoid threading issues. Specifically, the following threading issue can happen in oilpan builds:
(1) The worker thread calls Bridge::destroy.
(2) The worker thread finishes and calls a final GC to clean up the thread heap before Peer::destroy is triggered.
Then the final GC hits the empty ASSERT (which checks if the thread heap of the worker thread is empty) because the main thread still holds a reference to the SyncHelper, which is allocated on the thread heap of the worker thread. In order to make sure that the worker thread runs the final GC after the main thread clears the references to all objects allocated in the thread heap of the worker thread, we need to make the Bridge::destroy wait for the main thread to complete the Peer::destroy.
This issue doesn't happen in non-oilpan builds, so this CL adds the synchronization to oilpan builds only. (In any event, we cannot add the synchronization to non-oilpan builds, because Peer::destroy destructs the SyncHelper object and thus there is no way for the main thread to tell the worker thread that the main thread completes the Peer::destroy.)
Review URL: https://codereview.chromium.org/339663004
git-svn-id: svn://svn.chromium.org/blink/trunk@176751 bbb929c8-8fbe-4397-9dbb-9b2b20218538
-rw-r--r-- | Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp | 9 |
1 files changed, 9 insertions, 0 deletions
diff --git a/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp b/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp index c172874c00fa..7f82ad89ac2a 100644 --- a/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp +++ b/Source/modules/websockets/WorkerThreadableWebSocketChannel.cpp @@ -254,6 +254,7 @@ void WorkerThreadableWebSocketChannel::Peer::destroy() #if ENABLE(OILPAN) m_keepAlive = nullptr; + m_syncHelper->signalWorkerThread(); #else delete this; #endif @@ -567,7 +568,15 @@ bool WorkerThreadableWebSocketChannel::Bridge::waitForMethodCompletion(PassOwnPt void WorkerThreadableWebSocketChannel::Bridge::terminatePeer() { ASSERT(!hasTerminatedPeer()); +#if ENABLE(OILPAN) + // The worker thread has to wait for the main thread to complete Peer::destroy, + // because the worker thread has to make sure that the main thread does not have any + // references to on-heap objects allocated in the thread heap of the worker thread + // before the worker thread shuts down. + waitForMethodCompletion(CallClosureTask::create(bind(&Peer::destroy, m_peer))); +#else m_loaderProxy.postTaskToLoader(CallClosureTask::create(bind(&Peer::destroy, m_peer))); +#endif // Peer::destroy() deletes m_peer and then m_syncHelper will be released. // We must not touch m_syncHelper any more. |