From 25f1a9f1e88bf7cf9fff8d9c3847603ec0dc7c03 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Mon, 28 Feb 2011 10:14:01 -0700 Subject: [PATCH] fix Thread::exit/Thread::dispose race condition There was a race between these two functions such that one thread A would run dispose on thread B just before thread B finishes exit, with the result that Thread::lock and/or Thread::systemThread would be disposed twice, resulting in a crash. --- src/machine.cpp | 23 ++++++++++++++--------- src/machine.h | 1 + 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/machine.cpp b/src/machine.cpp index c174f4aafd..a561006ca7 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -2413,20 +2413,23 @@ Thread::exit() } else { threadPeer(this, javaThread) = 0; + System::Monitor* myLock = lock; + System::Thread* mySystemThread = systemThread; + { ACQUIRE_RAW(this, m->stateLock); while (flags & SystemFlag) { m->stateLock->wait(systemThread, 0); } + + atomicOr(&flags, Thread::DisposeFlag); enter(this, Thread::ZombieState); } - lock->dispose(); - lock = 0; + myLock->dispose(); - systemThread->dispose(); - systemThread = 0; + mySystemThread->dispose(); } } } @@ -2434,12 +2437,14 @@ Thread::exit() void Thread::dispose() { - if (lock) { - lock->dispose(); - } + if ((flags & Thread::DisposeFlag) == 0) { + if (lock) { + lock->dispose(); + } - if (systemThread) { - systemThread->dispose(); + if (systemThread) { + systemThread->dispose(); + } } m->heap->free(defaultHeap, ThreadHeapSizeInBytes); diff --git a/src/machine.h b/src/machine.h index c342b9f695..6c3633000f 100644 --- a/src/machine.h +++ b/src/machine.h @@ -1369,6 +1369,7 @@ class Thread { static const unsigned StressFlag = 1 << 4; static const unsigned ActiveFlag = 1 << 5; static const unsigned SystemFlag = 1 << 6; + static const unsigned DisposeFlag = 1 << 7; class Protector { public: