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

Unified Diff: Source/platform/heap/HeapTest.cpp

Issue 415083002: [oilpan]: fix deadlock when leaving a safepoint and sweeping. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: review feedback Created 6 years, 5 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 | « Source/modules/webdatabase/DatabaseBackendBase.cpp ('k') | Source/platform/heap/ThreadState.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/platform/heap/HeapTest.cpp
diff --git a/Source/platform/heap/HeapTest.cpp b/Source/platform/heap/HeapTest.cpp
index 679b55c023f9887efc5ce9f13edcb9ce89a3664e..14a6157d677d257afbd853bfbed37b96a38d7964 100644
--- a/Source/platform/heap/HeapTest.cpp
+++ b/Source/platform/heap/HeapTest.cpp
@@ -4877,4 +4877,107 @@ TEST(HeapTest, GarbageCollectionDuringMixinConstruction)
a->verify();
}
+static RecursiveMutex& recursiveMutex()
+{
+ AtomicallyInitializedStatic(RecursiveMutex&, recursiveMutex = *new RecursiveMutex);
+ return recursiveMutex;
+}
+
+class DestructorLockingObject : public GarbageCollectedFinalized<DestructorLockingObject> {
+public:
+ static DestructorLockingObject* create()
+ {
+ return new DestructorLockingObject();
+ }
+
+ virtual ~DestructorLockingObject()
+ {
+ SafePointAwareMutexLocker lock(recursiveMutex());
+ ++s_destructorCalls;
+ }
+
+ static int s_destructorCalls;
+ void trace(Visitor* visitor) { }
+
+private:
+ DestructorLockingObject() { }
+};
+
+int DestructorLockingObject::s_destructorCalls = 0;
+
+class RecursiveLockingTester {
+public:
+ static void test()
+ {
+ DestructorLockingObject::s_destructorCalls = 0;
+
+ MutexLocker locker(mainThreadMutex());
+ createThread(&workerThreadMain, 0, "Worker Thread");
+
+ // Park the main thread until the worker thread has initialized.
+ parkMainThread();
+
+ {
+ SafePointAwareMutexLocker recursiveLocker(recursiveMutex());
+
+ // Let the worker try to acquire the above mutex. It won't get it
+ // until the main thread has done its GC.
+ wakeWorkerThread();
+
+ Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
+
+ // The worker thread should not have swept yet since it is waiting
+ // to get the global mutex.
+ EXPECT_EQ(0, DestructorLockingObject::s_destructorCalls);
+ }
+ // At this point the main thread releases the global lock and the worker
+ // can acquire it and do its sweep of its heaps. Just wait for the worker
+ // to complete its sweep and check the result.
+ parkMainThread();
+ EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls);
+ }
+
+private:
+ static void workerThreadMain(void* data)
+ {
+ MutexLocker locker(workerThreadMutex());
+ ThreadState::attach();
+
+ DestructorLockingObject* dlo = DestructorLockingObject::create();
+ ASSERT_UNUSED(dlo, dlo);
+
+ // Wake up the main thread which is waiting for the worker to do its
+ // allocation.
+ wakeMainThread();
+
+ // Wait for the main thread to get the global lock to ensure it has
+ // it before the worker tries to acquire it. We want the worker to
+ // block in the SafePointAwareMutexLocker until the main thread
+ // has done a GC. The GC will not mark the "dlo" object since the worker
+ // is entering the safepoint with NoHeapPointersOnStack. When the worker
+ // subsequently gets the global lock and leaves the safepoint it will
+ // sweep its heap and finalize "dlo". The destructor of "dlo" will try
+ // to acquire the same global lock that the thread just got and deadlock
+ // unless the global lock is recursive.
+ parkWorkerThread();
+ SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), ThreadState::NoHeapPointersOnStack);
+
+ // We won't get here unless the lock is recursive since the sweep done
+ // in the constructor of SafePointAwareMutexLocker after
+ // getting the lock will not complete given the "dlo" destructor is
+ // waiting to get the same lock.
+ // Tell the main thread the worker has done its sweep.
+ wakeMainThread();
+
+ ThreadState::detach();
+ }
+
+ static volatile IntWrapper* s_workerObjectPointer;
+};
+
+TEST(HeapTest, RecursiveMutex)
+{
+ RecursiveLockingTester::test();
+}
+
} // WebCore namespace
« no previous file with comments | « Source/modules/webdatabase/DatabaseBackendBase.cpp ('k') | Source/platform/heap/ThreadState.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698