From: "luke-gru (Luke Gruber) via ruby-core" <ruby-core@...>
Date: 2025-04-01T20:16:57+00:00
Subject: [ruby-core:121502] [Ruby Bug#21208] `Ractor#send(move: true)` allow moving objects that are on the stack, and used by C code.

Issue #21208 has been updated by luke-gru (Luke Gruber).


Hmm... this is tricky, good find! This probably won't occur often, I'm having a hard time coming up with a situation where it would happen with some benign looking code.

It's fun thinking about solutions to these kinds of things, so as thought experiment if we could somehow disallow `r.send(move: true)` inside blocks called from ruby methods that are implemented in C and that call `rb_yield` and modify `self` with the results of the block, then the issue would go away, right? I don't think `(move: true)` will be used as often as copying the object or just using a shareable object (though I could be wrong) so it's not a deal breaker for ractors in general, but it's a shame. 

There could be a way around this I think, if we disallow calling this method with `move: true` in certain scenarios, maybe prohibiting its use from blocks yielded from C (very limiting), or differentiating between mutable and immutable yields, etc. Not that it wouldn't be tricky, but it's not impossible. If a block would be unknown mutability (such as from a C extension), it would be prohibited, etc. I'll have to think more about this, but for now I think letting it exist as a bug and seeing if it rears its head is probably the best "solution".

----------------------------------------
Bug #21208: `Ractor#send(move: true)` allow moving objects that are on the stack, and used by C code.
https://bugs.ruby-lang.org/issues/21208#change-112523

* Author: byroot (Jean Boussier)
* Status: Open
* Assignee: ractor
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN
----------------------------------------
The following script causes a crash:

```ruby
rac = Ractor.new do
  Ractor.receive
end

hash = Hash[*50.times]

hash.merge!(12 => 0, 14 => 0) do |key, old_val, new_val|
  if key == 12
    rac.send(hash, move: true)
  end
  new_val
end

p rac.take
```

Contrary to previous crashes related to `send(move: true)`, I'm afraid this one is with the design of the feature itself, not just the implementation.

If we allow objects to be moved, any C code that calls `rb_yield()` may cause memory corruption if one of the objects it uses is moved.

I personally can't see any realistic solution to this.



-- 
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/