Skip to content

Commit

Permalink
Fix race-condition in TaskMutex debug code.
Browse files Browse the repository at this point in the history
m_owner could change between the two conditions checked in the assertion in lock(), causing a false assertion failure. Using atomic operations to avoid that.
  • Loading branch information
s-ludwig committed Jan 8, 2024
1 parent def5e7b commit 0b72fb0
Showing 1 changed file with 13 additions and 5 deletions.
18 changes: 13 additions & 5 deletions source/vibe/core/sync.d
Original file line number Diff line number Diff line change
Expand Up @@ -1934,7 +1934,7 @@ private struct TaskMutexImpl(bool INTERRUPTIBLE) {
shared(bool) m_locked = false;
shared(uint) m_waiters = 0;
shared(ManualEvent) m_signal;
debug Task m_owner;
debug shared Task m_owner;
}

shared:
Expand All @@ -1947,7 +1947,10 @@ private struct TaskMutexImpl(bool INTERRUPTIBLE) {
@trusted bool tryLock()
nothrow {
if (cas(&m_locked, false, true)) {
debug m_owner = Task.getThis();
debug {
auto swapped = cas(&m_owner, Task.init, Task.getThis());
assert(swapped);
}
debug(VibeMutexLog) logTrace("mutex %s lock %s", cast(void*)&this, atomicLoad(m_waiters));
return true;
}
Expand All @@ -1957,7 +1960,11 @@ private struct TaskMutexImpl(bool INTERRUPTIBLE) {
@trusted bool lock(Duration timeout = Duration.max)
{
if (tryLock()) return true;
debug assert(m_owner == Task() || m_owner != Task.getThis(), "Recursive mutex lock.");
debug {
auto thist = Task.getThis();
auto owner = atomicLoad(m_owner);
assert(owner == Task.init || owner != thist, "Recursive mutex lock.");
}
atomicOp!"+="(m_waiters, 1);
debug(VibeMutexLog) logTrace("mutex %s wait %s", cast(void*)&this, atomicLoad(m_waiters));
scope(exit) atomicOp!"-="(m_waiters, 1);
Expand All @@ -1979,8 +1986,9 @@ private struct TaskMutexImpl(bool INTERRUPTIBLE) {
{
assert(m_locked);
debug {
assert(m_owner == Task.getThis());
m_owner = Task();
auto thist = Task.getThis();
auto swapped = cas(&m_owner, thist, Task());
assert(swapped);
}
atomicStore!(MemoryOrder.rel)(m_locked, false);
debug(VibeMutexLog) logTrace("mutex %s unlock %s", cast(void*)&this, atomicLoad(m_waiters));
Expand Down

0 comments on commit 0b72fb0

Please sign in to comment.