From 936899aa7a7fa042ec4b2cfdf1f1269b215b2070 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 29 Jul 2026 20:54:16 +1200 Subject: [PATCH] Reset blocked operations after fork. --- lib/async/scheduler.rb | 1 + releases.md | 4 ++++ test/process/fork.rb | 23 +++++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/lib/async/scheduler.rb b/lib/async/scheduler.rb index 45f972fa..46610357 100644 --- a/lib/async/scheduler.rb +++ b/lib/async/scheduler.rb @@ -685,6 +685,7 @@ def process_fork @children = nil @selector = nil @timers = nil + @blocked = 0 # Close the scheduler: Fiber.set_scheduler(nil) diff --git a/releases.md b/releases.md index db113ed9..420aae5c 100644 --- a/releases.md +++ b/releases.md @@ -1,5 +1,9 @@ # Releases +## Unreleased + + - Fixed scheduler cleanup after forking while other fibers are blocked. + ## v2.43.0 - Propagate cancellation causes through task trees so child tasks observe the original cancellation cause. diff --git a/test/process/fork.rb b/test/process/fork.rb index 42885389..8b28c0c3 100644 --- a/test/process/fork.rb +++ b/test/process/fork.rb @@ -44,5 +44,28 @@ Process.waitpid(pid) if pid end end + + it "can fork while another fiber is blocked" do + r, w = IO.pipe + queue = Thread::Queue.new + + Async do |task| + blocked_task = task.async do + queue.pop + end + + pid = Process.fork do + # Child process: + w.write("hello") + end + + # Parent process: + w.close + expect(r.read).to be == "hello" + ensure + blocked_task&.stop + Process.waitpid(pid) if pid + end + end end end