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:
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user