Skip to content

Commit 80f123e

Browse files
committed
Fix handling of spurious wake-ups.
1 parent f106543 commit 80f123e

File tree

3 files changed

+38
-2
lines changed

3 files changed

+38
-2
lines changed

lib/async/promise.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ def wait
8686

8787
begin
8888
# Wait for resolution if not already resolved:
89-
@condition.wait(@mutex) unless @resolved
89+
until @resolved
90+
@condition.wait(@mutex)
91+
end
9092

9193
# Return value or raise exception based on resolution type:
9294
if @resolved == :completed

releases.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Releases
22

3+
## Unreleased
4+
5+
- Fix incorrect handling of spurious wakeups in `Async::Promise#wait`, which could lead to premature (incorrect) resolution of the promise.
6+
37
## v2.35.0
48

59
- `Process.fork` is now properly handled by the Async fiber scheduler, ensuring that the scheduler state is correctly reset in the child process after a fork. This prevents issues where the child process inherits the scheduler state from the parent, which could lead to unexpected behavior.

test/async/promise.rb

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@
9191
end
9292

9393
with "#wait" do
94-
9594
it "blocks until resolved" do
9695
result = nil
9796

@@ -703,3 +702,34 @@
703702
end
704703
end
705704
end
705+
706+
describe Async::Promise do
707+
include Sus::Fixtures::Async::ReactorContext
708+
709+
let(:promise) {subject.new}
710+
711+
describe "#wait" do
712+
it "handles spurious wake-ups gracefully" do
713+
promise = Async::Promise.new
714+
result = nil
715+
716+
thread = Thread.new do
717+
result = promise.wait
718+
rescue => error
719+
# Pass.
720+
end
721+
722+
Thread.pass until thread.stop?
723+
724+
10.times do
725+
thread.wakeup # Trigger spurious wake-up.
726+
Thread.pass
727+
end
728+
729+
promise.resolve(:success)
730+
thread.join
731+
732+
expect(result).to be == :success
733+
end
734+
end
735+
end

0 commit comments

Comments
 (0)