Fixed a race condition in MultiLocker, when compiled in DEBUG mode:

The fWriterThread and fWriterStackBase were reset in WriteUnlock()
without holding any lock. While running a DEBUG compile of app_server,
I ran repeatedly into an assertion in the mouse event thread, that
it was not the write lock holder anymore when calling WriteUnlock().
My theory (also discussed with Axel, thanks!) is as this: Some random
thread holds the write-lock. The mouse event thread is allowed to run
when that thread releases the write-lock, but the thread is rescheduled
before it resets the write-lock-holder values (B_DO_NOT_RESCHEDULE only
means rescheduling is not forced, but it may happen anyway). Then the
mouse thread runs, acquires the write-lock, sometime later the original
thread continues to run, and completes WriteUnlock() with resetting the
holder values. When the mouse thread continues to run and eventually
calls WriteUnlock(), the holder values do not match anymore. The theory
is further confirmed by the fact, that fWriterThread was always -1 in the
assert and not some random other thread.

As mentioned, only affected DEBUG builds of app_server, in release builds,
another lock protects the holder values.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38331 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2010-08-24 13:46:48 +00:00
parent e4f3cf203c
commit f242acd5a0
+5 -8
View File
@@ -445,10 +445,8 @@ MultiLocker::WriteLock()
locked = true;
} else {
// new writer acquiring the lock
#if DEBUG
if (IsReadLocked())
debugger("Reader wants to become writer!");
#endif
status_t status;
do {
@@ -501,12 +499,11 @@ MultiLocker::WriteUnlock()
fWriterNest--;
unlocked = true;
} else {
unlocked = release_sem_etc(fLock, LARGE_NUMBER, B_DO_NOT_RESCHEDULE) == B_OK;
if (unlocked) {
// clear the information
fWriterThread = -1;
fWriterStackBase = 0;
}
// clear the information while still holding the lock
fWriterThread = -1;
fWriterStackBase = 0;
unlocked = release_sem_etc(fLock, LARGE_NUMBER,
B_DO_NOT_RESCHEDULE) == B_OK;
}
} else {
char message[256];