Issue #22211 has been reported by rkh (Konstantin Haase). ---------------------------------------- Bug #22211: Fiber::Scheduler stalls on Ractor::Port.receive https://bugs.ruby-lang.org/issues/22211 * Author: rkh (Konstantin Haase) * Status: Open * ruby -v: ruby 4.1.0dev (2026-07-24T12:18:38Z master 180b664bd9) +PRISM [arm64-darwin25] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Quickly upfront: This might be a duplicate of #20276, and let me know if the official solution is still to launch a thread for each port so it can block (or add some more complex thread orchestration). Anyway, I think `Ractor::Port#receive` should call `Fiber::Scheduler#block`/`Fiber::Scheduler#unblock` if a scheduler is set (or some other hook), the way that `Thread::Queue` does. Instead, it completely blocks the scheduler. Example to reproduce: ``` ruby Warning[:experimental] = false class Scheduler def initialize @fiber = Fiber.current @blocked = Set.new @ready = Queue.new end def scheduler_close @ready.pop.transfer while @blocked.any? end def block(blocker, timeout = nil) raise NotImplementedError, "block: timeout not supported" if timeout @blocked << Fiber.current @fiber.transfer ensure @blocked.delete(Fiber.current) end def unblock(blocker, fiber) = @ready << fiber def io_write(io, buffer, offset, length) = Thread.new { buffer.write(io, offset, length) }.value def fiber(&) = Fiber.new(blocking: false, &).tap(&:transfer) def respond_to_missing?(...) = true def method_missing(method, ...) = raise NotImplementedError, "#{method}: not implemented" end Fiber.set_scheduler(Scheduler.new) # This would work: # # queue = Queue.new # Fiber.schedule { puts queue.pop } # queue.push "Hello from Queue!" port = Ractor::Port.new Fiber.schedule { puts port.receive } port.send("Hello from Ractor::Port!") # never gets here ``` -- https://bugs.ruby-lang.org/