[ruby-core:115845] [Ruby master Bug#20078] StringIO cannot be moved between Ractors

Issue #20078 has been reported by forthoney (Seong-Heon Jung). ---------------------------------------- Bug #20078: StringIO cannot be moved between Ractors https://bugs.ruby-lang.org/issues/20078 * Author: forthoney (Seong-Heon Jung) * Status: Open * Priority: Normal * ruby -v: 3.2 * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- The following code will raise an unusual Ractor error. ``` ruby require 'stringio' r = Ractor.new { loop { Ractor.receive } } Ractor.shareable?(StringIO.new) #=> false r.send(StringIO.new) # passing it via copy works r.send(StringIO.new, move: true) # <internal:ractor>:587:in `send': can not move StringIO object. (Ractor::Error) ``` I'm not 100% sure but I believe that this probably not the intended behavior considering * The error raised is a generic `Ractor::Error` rather than something specific like Ractor::MovedError or Ractor::IsolationError * It can be copied * [No documentation](https://docs.ruby-lang.org/en/master/ractor_md.html) exists for this error * I have yet to seen this happen on any other class instance * Typo (can not -> cannot) -- https://bugs.ruby-lang.org/

Issue #20078 has been updated by matz (Yukihiro Matsumoto). StringIO is a mutable object, so it is fundamentally not movable. I agree that some cosmetic errors you have pointed should be fixed. Matz. ---------------------------------------- Bug #20078: StringIO cannot be moved between Ractors https://bugs.ruby-lang.org/issues/20078#change-105802 * Author: forthoney (Seong-Heon Jung) * Status: Open * Priority: Normal * ruby -v: 3.2 * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- The following code will raise an unusual Ractor error. ``` ruby require 'stringio' r = Ractor.new { loop { Ractor.receive } } Ractor.shareable?(StringIO.new) #=> false r.send(StringIO.new) # passing it via copy works r.send(StringIO.new, move: true) # <internal:ractor>:587:in `send': can not move StringIO object. (Ractor::Error) ``` I'm not 100% sure but I believe that this probably not the intended behavior considering * The error raised is a generic `Ractor::Error` rather than something specific like Ractor::MovedError or Ractor::IsolationError * It can be copied * [No documentation](https://docs.ruby-lang.org/en/master/ractor_md.html) exists for this error * I have yet to seen this happen on any other class instance * Typo (can not -> cannot) -- https://bugs.ruby-lang.org/

Issue #20078 has been updated by forthoney (Seong-Heon Jung). Thank you for the quick response! If my understanding is correct, then there are 4 categories of Ruby objects: 1. Shareable objects (Ractors, immutable objects, etc) 2. Unshareable but sendable with copy and move 3. Unshareable but sendable with only copy (StringIO) 4. Unshareable and unsendable objects (Thread) The documentation makes a fairly clear distinction between shareable and unshareable, but the line between the three different types of unshareable objects is a bit unclear. What are the criteria for the different degrees of "sendability"? ---------------------------------------- Bug #20078: StringIO cannot be moved between Ractors https://bugs.ruby-lang.org/issues/20078#change-105817 * Author: forthoney (Seong-Heon Jung) * Status: Open * Priority: Normal * ruby -v: 3.2 * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- The following code will raise an unusual Ractor error. ``` ruby require 'stringio' r = Ractor.new { loop { Ractor.receive } } Ractor.shareable?(StringIO.new) #=> false r.send(StringIO.new) # passing it via copy works r.send(StringIO.new, move: true) # <internal:ractor>:587:in `send': can not move StringIO object. (Ractor::Error) ``` I'm not 100% sure but I believe that this probably not the intended behavior considering * The error raised is a generic `Ractor::Error` rather than something specific like Ractor::MovedError or Ractor::IsolationError * It can be copied * [No documentation](https://docs.ruby-lang.org/en/master/ractor_md.html) exists for this error * I have yet to seen this happen on any other class instance * Typo (can not -> cannot) -- https://bugs.ruby-lang.org/

Issue #20078 has been updated by luke-gru (Luke Gruber). I think this is due to not currently being able to move any T_DATA objects. StringIO is defined in a C extension and is a T_DATA object internally. See https://github.com/ruby/ruby/blob/master/ractor.c#L3417C1-L3417C13. The problem with T_DATA objects like StringIO is you would have to move their references too (like the actual String that it holds) but it's currently not possible to know that this reference exists because there's no callback function for extensions called strio_moved(), which would move the references. That's why you have to pass strio_mark callbacks when defining a new data type for T_DATA objects, to mark the references manually. Note that you can't just add a new callback function and make it optional, all C extensions with T_DATA objects would have to be changed to add this callback to make moving T_DATA objects work properly. It's not really feasible unless something changes with how T_DATA objects are defined or how their references are kept. The documentation should mention this, without going into too much detail. Something like: Currently, most types that are implemented in C extensions cannot be moved. ---------------------------------------- Bug #20078: StringIO cannot be moved between Ractors https://bugs.ruby-lang.org/issues/20078#change-105830 * Author: forthoney (Seong-Heon Jung) * Status: Open * Priority: Normal * ruby -v: 3.2 * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- The following code will raise an unusual Ractor error. ``` ruby require 'stringio' r = Ractor.new { loop { Ractor.receive } } Ractor.shareable?(StringIO.new) #=> false r.send(StringIO.new) # passing it via copy works r.send(StringIO.new, move: true) # <internal:ractor>:587:in `send': can not move StringIO object. (Ractor::Error) ``` I'm not 100% sure but I believe that this probably not the intended behavior considering * The error raised is a generic `Ractor::Error` rather than something specific like Ractor::MovedError or Ractor::IsolationError * It can be copied * [No documentation](https://docs.ruby-lang.org/en/master/ractor_md.html) exists for this error * I have yet to seen this happen on any other class instance * Typo (can not -> cannot) -- https://bugs.ruby-lang.org/

Issue #20078 has been updated by forthoney (Seong-Heon Jung). luke-gru (Luke Gruber) wrote in #note-3:
I think this is due to not currently being able to move any T_DATA objects between ractors. StringIO is defined in a C extension and is a T_DATA object internally. See https://github.com/ruby/ruby/blob/master/ractor.c#L3417C1-L3417C13. This isn't a fundamental limitation (I don't think?), it's just it hasn't been implemented yet. But certain errors could happen, for example if the C extension allows you to move an object to another Ractor, but then uses this same object internally in the original Ractor, maybe it could cause errors.
The documentation should mention this, without going into too much detail. Something like: Currently, most types that are implemented in C extensions cannot be moved.
I agree. The documentation does mention T_DATA, but does not really mention the implications of being unable to move T_DATA, which is that "most types that are implemented in C extensions cannot be moved". Additionally, I am wondering if it makes sense to make a `Ractor.movable?` module function similar to `Ractor.shareable?` This would greatly save developer time since they can check if a object is movable in IRB rather than having to dig through the source code. ---------------------------------------- Bug #20078: StringIO cannot be moved between Ractors https://bugs.ruby-lang.org/issues/20078#change-105831 * Author: forthoney (Seong-Heon Jung) * Status: Open * Priority: Normal * ruby -v: 3.2 * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- The following code will raise an unusual Ractor error. ``` ruby require 'stringio' r = Ractor.new { loop { Ractor.receive } } Ractor.shareable?(StringIO.new) #=> false r.send(StringIO.new) # passing it via copy works r.send(StringIO.new, move: true) # <internal:ractor>:587:in `send': can not move StringIO object. (Ractor::Error) ``` I'm not 100% sure but I believe that this probably not the intended behavior considering * The error raised is a generic `Ractor::Error` rather than something specific like Ractor::MovedError or Ractor::IsolationError * It can be copied * [No documentation](https://docs.ruby-lang.org/en/master/ractor_md.html) exists for this error * I have yet to seen this happen on any other class instance * Typo (can not -> cannot) -- https://bugs.ruby-lang.org/

Issue #20078 has been updated by luke-gru (Luke Gruber). I created a PR that updates the Ractor docs: https://github.com/ruby/ruby/pull/9395. It doesn't go into much detail about the situation but clarifies it a bit. Adding a `movable?` method would have have to be a separate ticket @forthoney. I think it's an okay idea, but I'm a bit concerned because then should we add a `copyable?` method too? We could just have a `sendable?` method that takes the `move` keyword, which could deal with both copying and moving cases. I think unit or integration tests would catch most cases of sending the wrong objects across Ractors, but I see a use for it. ---------------------------------------- Bug #20078: StringIO cannot be moved between Ractors https://bugs.ruby-lang.org/issues/20078#change-105940 * Author: forthoney (Seong-Heon Jung) * Status: Open * Priority: Normal * ruby -v: 3.2 * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- The following code will raise an unusual Ractor error. ``` ruby require 'stringio' r = Ractor.new { loop { Ractor.receive } } Ractor.shareable?(StringIO.new) #=> false r.send(StringIO.new) # passing it via copy works r.send(StringIO.new, move: true) # <internal:ractor>:587:in `send': can not move StringIO object. (Ractor::Error) ``` I'm not 100% sure but I believe that this probably not the intended behavior considering * The error raised is a generic `Ractor::Error` rather than something specific like Ractor::MovedError or Ractor::IsolationError * It can be copied * [No documentation](https://docs.ruby-lang.org/en/master/ractor_md.html) exists for this error * I have yet to seen this happen on any other class instance * Typo (can not -> cannot) -- https://bugs.ruby-lang.org/

Issue #20078 has been updated by luke-gru (Luke Gruber). I think this ticket can be closed as I've updated the docs to reflect the current situation and it's been merged. ---------------------------------------- Bug #20078: StringIO cannot be moved between Ractors https://bugs.ruby-lang.org/issues/20078#change-106189 * Author: forthoney (Seong-Heon Jung) * Status: Open * Priority: Normal * ruby -v: 3.2 * Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- The following code will raise an unusual Ractor error. ``` ruby require 'stringio' r = Ractor.new { loop { Ractor.receive } } Ractor.shareable?(StringIO.new) #=> false r.send(StringIO.new) # passing it via copy works r.send(StringIO.new, move: true) # <internal:ractor>:587:in `send': can not move StringIO object. (Ractor::Error) ``` I'm not 100% sure but I believe that this probably not the intended behavior considering * The error raised is a generic `Ractor::Error` rather than something specific like Ractor::MovedError or Ractor::IsolationError * It can be copied * [No documentation](https://docs.ruby-lang.org/en/master/ractor_md.html) exists for this error * I have yet to seen this happen on any other class instance * Typo (can not -> cannot) -- https://bugs.ruby-lang.org/
participants (3)
-
forthoney (Seong-Heon Jung)
-
luke-gru (Luke Gruber)
-
matz (Yukihiro Matsumoto)