kernel/fifo: Don't unlock before unblock.
Otherwise there is a race that can occur if the waiting thread is interrupted (or hasn't slept yet) while the writing thread tries to unblock it. Instead, don't call SetNotified again if we unblocked with a status of B_OK. This can only happen when we were notified by another thread successfully. Should help with #19458. Change-Id: Iad46b26374a01539f8765231d259392c231c786a Reviewed-on: https://review.haiku-os.org/c/haiku/+/9085 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
committed by
waddlesplash
parent
240f1a0e91
commit
0958031b24
@@ -107,17 +107,11 @@ public:
|
||||
|
||||
void Notify(status_t status = B_OK)
|
||||
{
|
||||
InterruptsLocker _;
|
||||
SpinLocker spinLocker(fLock);
|
||||
InterruptsSpinLocker spinLocker(fLock);
|
||||
TRACE("ReadRequest %p::Notify(), fNotified %d\n", this, fNotified);
|
||||
|
||||
if (!fNotified) {
|
||||
fNotified = true;
|
||||
|
||||
// Whoever calls Notify() must hold the requests lock,
|
||||
// so we can be sure this Request won't be deleted.
|
||||
spinLocker.Unlock();
|
||||
|
||||
thread_unblock(fThread, status);
|
||||
}
|
||||
}
|
||||
@@ -697,9 +691,11 @@ Inode::WaitForReadRequest(ReadRequest& request)
|
||||
rw_lock_read_unlock(&fChangeLock);
|
||||
status_t status = thread_block();
|
||||
|
||||
// Before going to lock again, we need to make sure no one tries to
|
||||
// unblock us. Otherwise that would screw with mutex_lock().
|
||||
request.SetNotified(true);
|
||||
if (status != B_OK) {
|
||||
// Before going to lock again, we need to make sure no one tries to
|
||||
// unblock us. Otherwise that would screw with mutex_lock().
|
||||
request.SetNotified(true);
|
||||
}
|
||||
|
||||
rw_lock_read_lock(&fChangeLock);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user