Skip to content

Commit ee302c6

Browse files
committed
ConditionVariable#wait needs to check both for Thread#{wakeup,run} and after a safepoint
1 parent 83602d5 commit ee302c6

File tree

1 file changed

+15
-0
lines changed

1 file changed

+15
-0
lines changed

src/main/java/org/truffleruby/core/mutex/ConditionVariableNodes.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ private void waitInternal(DynamicObject conditionVariable, ReentrantLock mutexLo
9191
endNanoTime = 0;
9292
}
9393

94+
// Clear the wakeUp flag, following Ruby semantics:
95+
// it should only be considered if we are inside Mutex#sleep when Thread#{run,wakeup} is called.
96+
Layouts.THREAD.getWakeUp(thread).set(false);
97+
9498
// condLock must be locked before unlocking mutexLock, to avoid losing potential signals
9599
getContext().getThreadManager().runUntilResult(this, () -> {
96100
condLock.lockInterruptibly();
@@ -167,6 +171,17 @@ private void awaitSignal(DynamicObject self, DynamicObject thread, long duration
167171
} finally {
168172
condLock.lock();
169173
}
174+
175+
// Thread#{wakeup,run} might have woken us. In that a case, no signal is consumed.
176+
if (Layouts.THREAD.getWakeUp(thread).getAndSet(false)) {
177+
return;
178+
}
179+
180+
// Check if a signal are available now, since another thread might have used
181+
// ConditionVariable#signal while we released condLock to check for safepoints.
182+
if (consumeSignal(self)) {
183+
return;
184+
}
170185
}
171186
}
172187
}

0 commit comments

Comments
 (0)