From: "rkh (Konstantin Haase) via ruby-core" Date: 2026-08-19T14:10:06+00:00 Subject: [ruby-core:126442] [Ruby Bug#22211] Fiber::Scheduler stalls on Ractor::Port.receive Issue #22211 has been updated by rkh (Konstantin Haase). luke-gru (Luke Gruber) wrote in #note-2: > The tricky part in integrating the fiber scheduler with `Ractor::Port` `send/receive` is what to do when you want to wakeup (unblock) a fiber on another Ractor. Would it be possible to add something like `ractor_receive`/`ractor_select`/`ractor_value` to the `Fiber::Scheduler` interface instead, with the wakeup being the scheduler's responsibility? Similar to how dealing with IO has explicit callbacks. That way, having a thread that can be woken up would be the scheduler's responsibility, with a naive implementation being something like this: ```ruby def ractor_select(*args) = Thread.new { Ractor.select(*args) }.value def ractor_receive(port) = Thread.new { port.receive }.value def ractor_value(ractor) = Thread.new { ractor.value }.value ``` That way, the scheduler could implement a single background thread itself running `Ractor.select(...)` (again, similar to IO). ---------------------------------------- Bug #22211: Fiber::Scheduler stalls on Ractor::Port.receive https://bugs.ruby-lang.org/issues/22211#change-118592 * Author: rkh (Konstantin Haase) * Status: Open * Assignee: ractor * 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/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/