
Issue #21309 has been updated by nevans (Nicholas Evans). Eregon (Benoit Daloze) wrote in #note-6:
osyoyu (Daisuke Aritomo) wrote in #note-5:
I am not sure about this. Sending HTTP request using net/http inside an Ractor should be a valid use case, and `Timeout` is blocking this (it is internally used to implement `open_timeout` `read_timeout` and `write_timeout`.
Ideally Net::HTTP wouldn't use Timeout (which is for interrupting code using too much CPU), interrupting I/O in general should be done without Timeout (because Timeout is too heavy for that). Maybe Net::HTTP could use `IO.select`?
Does `Net::HTTP` use `Timeout` to implement its timeouts? `Timeout::Error` is used as a superclass for the `net-protocol` timeout errors, but doesn't use `Timeout.timeout` directly, I think. I'm pretty sure that `Net::HTTP` uses `Net::BufferedIO` (from `net-protocol`) for timeouts, and that switched from `Timeout.timeout` to `IO.select` in 2008, then to `wait_readable`/`wait_writable` in 2015: * [net-protocol `rbuf_fill`] - using `read_nonblock`, `wait_readable`, and `wait_writable` * [net-protocol `write0`] - using `read_nonblock` and `wait_writable` * [net-protocol `a73e9852`] - 2018 commit adding write timeouts * [net-protocol `23614f41`] - 2015 commit converting read timeouts from `IO.select` to `io/wait` methods * [net-protocol `76c28402`] - 2008 commit converting read timeouts from `Timeout.timeout` to `IO.select` [net-protocol `rbuf_fill`]: https://github.com/ruby/net-protocol/blob/0d0c9f372b7e571c9b446caead6af8f938... [net-protocol `write0`]: https://github.com/ruby/net-protocol/blob/0d0c9f372b7e571c9b446caead6af8f938... [net-protocol `a73e9852`]: https://github.com/ruby/net-protocol/commit/a73e9852b8dfc2384afcb2fe62eb310f... [net-protocol `23614f41`]: https://github.com/ruby/net-protocol/commit/23614f419d98e4db1a748b16815a49bb... [net-protocol `76c28402`]: https://github.com/ruby/net-protocol/commit/76c284021cec9fac23ac562eda78df11... I've been looking at adding comprehensive timeouts to `net-imap` 0.6, and considering whether or not it can be based on `BufferedIO`. More relevant to the original purpose of _this_ ticket: [ko1's Ractor::Port ticket](https://bugs.ruby-lang.org/issues/21262) looks very promising to me, especially if it is bundled with a library of common patterns built on top of it. ---------------------------------------- Feature #21309: Can Thread::Mutex be Ractor shareable? https://bugs.ruby-lang.org/issues/21309#change-113342 * Author: osyoyu (Daisuke Aritomo) * Status: Rejected ---------------------------------------- ## Background Keeping a `Mutex` object in a constant or a class instance variable is a common pattern seen in code with thread safety in mind. However, this kind of code does not play well with Ractors: ```ruby require 'thread' class C MUTEX = Mutex.new def self.foo MUTEX.synchronize { p 1 } end end Ractor.new { C.foo }.take ``` ``` t.rb:11: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues. #<Thread:0x000000011d80f368 run> terminated with exception (report_on_exception is true): t.rb:7:in 'C.foo': can not access non-shareable objects in constant C::MUTEX by non-main ractor. (Ractor::IsolationError) from t.rb:12:in 'block in <main>' <internal:ractor>:711:in 'Ractor#take': thrown by remote Ractor. (Ractor::RemoteError) from t.rb:13:in '<main>' t.rb:7:in 'C.foo': can not access non-shareable objects in constant C::MUTEX by non-main ractor. (Ractor::IsolationError) from t.rb:12:in 'block in <main>' ``` Many libraries follow this pattern. `Mutex` not being Ractor shareable is blocking these libraries from being used from inside Ractors. `Timeout` in stdlib in particular has large impact since it is required from many other gems by default, including `net/http`. https://github.com/ruby/timeout/blob/v0.4.3/lib/timeout.rb#L49-L50 https://github.com/lostisland/faraday/blob/v2.13.1/lib/faraday/middleware.rb... ## Proposal Make built-in concurrency primitives (Thread::Mutex, Thread::ConditionVariable and Thread::Queue) Ractor shareable. While this idea may not be strictly aligned with idea of the Ractor world (exchanging messages for controlling concurrency?), I have the feeling that too many code is blocked from running in Ractors because `Mutex` is not Ractor shareable. Allowing `Mutex`es to be shared would make a large portion of existing Ruby code Ractor-compatible, or at least make migration much easier. I believe that it won't be semantically incorrect, since they are concurrency primitives after all. One thing to consider that the current `Mutex` implementation is based on the GVL (I believe so). Migration to some other implementation e.g. pthread_mutex or CRITICAL_SECTION may be needed to make Mutex work well on Ractors. -- https://bugs.ruby-lang.org/