Skip to content

Commit

Permalink
Avoid race conditions in Scheduler#unblock.
Browse files Browse the repository at this point in the history
See <ruby/ruby#7460> for more details.
  • Loading branch information
ioquatix committed Mar 7, 2023
1 parent 5bf37d1 commit 20d40aa
Showing 1 changed file with 10 additions and 4 deletions.
14 changes: 10 additions & 4 deletions lib/async/scheduler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,12 @@ def close
# We depend on GVL for consistency:
# @guard.synchronize do

@selector&.close
# We want `@selector = nil` to be a visible side effect from this point forward, specifically in `#interrupt` and `#unblock`. If the selector is closed, then we don't want to push any fibers to it.
selector = @selector
@selector = nil

selector&.close

# end

consume
Expand All @@ -69,9 +72,10 @@ def to_s
end

# Interrupt the event loop and cause it to exit.
# @asynchronous May be called from any thread.
def interrupt
@interrupted = true
@selector.wakeup
@selector&.wakeup
end

# Transfer from the calling fiber to the event loop.
Expand Down Expand Up @@ -127,8 +131,10 @@ def unblock(blocker, fiber)
# $stderr.puts "unblock(#{blocker}, #{fiber})"

# This operation is protected by the GVL:
@selector.push(fiber)
@selector.wakeup
if selector = @selector
selector.push(fiber)
selector.wakeup
end
end

# @asynchronous May be non-blocking..
Expand Down

0 comments on commit 20d40aa

Please sign in to comment.