[#122369] [Ruby Bug#21392] Data classes do not allow overriding #inspect — "austin (Austin Ziegler) via ruby-core" <ruby-core@...>

Issue #21392 has been reported by austin (Austin Ziegler).

8 messages 2025/06/01

[#122411] [Ruby Bug#21396] Set#initialize should call Set#add on items passed in — "tenderlovemaking (Aaron Patterson) via ruby-core" <ruby-core@...>

Issue #21396 has been reported by tenderlovemaking (Aaron Patterson).

12 messages 2025/06/04

[#122506] [Ruby Feature#21435] Kernel#optional as a conditional #then — "Alexander.Senko (Alexander Senko) via ruby-core" <ruby-core@...>

SXNzdWUgIzIxNDM1IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IEFsZXhhbmRlci5TZW5rbyAoQWxleGFu

11 messages 2025/06/10

[#122557] [Ruby Bug#21445] [BUG] push_mark_stack() called for broken object raised since cd9f447be247478d2eb3da985295735cce20cb23 — "yahonda (Yasuo Honda) via ruby-core" <ruby-core@...>

Issue #21445 has been reported by yahonda (Yasuo Honda).

10 messages 2025/06/19

[#122615] [Ruby Misc#21458] Test 'make install'? — "MSP-Greg (Greg L) via ruby-core" <ruby-core@...>

Issue #21458 has been reported by MSP-Greg (Greg L).

11 messages 2025/06/28

[ruby-core:122607] [Ruby Feature#21039] Ractor.make_shareable breaks block semantics (seeing updated captured variables) of existing blocks

From: "Eregon (Benoit Daloze) via ruby-core" <ruby-core@...>
Date: 2025-06-26 21:07:59 UTC
List: ruby-core #122607
Issue #21039 has been updated by Eregon (Benoit Daloze).


I think a good solution here would be:
* raise on `Ractor.make_shareable(proc)`
* raise on `Ractor.make_shareable(proc, copy: true)`
* allow `Ractor.make_shareable { ... }` but only with a block literal. That way, the fact that block behaves differently by copying its environment is very clear. The method could check that the block doesn't do assignments in the environment as well to avoid surprises. It could also set the `self` in the block to `nil`, and/or take a keyword argument to set the receiver, or use the block's original self and error if it cannot be made shareable.

----------------------------------------
Feature #21039: Ractor.make_shareable breaks block semantics (seeing updated captured variables) of existing blocks
https://bugs.ruby-lang.org/issues/21039#change-113845

* Author: Eregon (Benoit Daloze)
* Status: Assigned
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
```ruby
def make_counter
  count = 0
  nil.instance_exec do
    [-> { count }, -> { count += 1 }]
  end
end

get, increment = make_counter

reader = Thread.new {
  sleep 0.01
  loop do
    p get.call
    sleep 0.1
  end
}

writer = Thread.new {
  loop do
    increment.call
    sleep 0.1
  end
}

ractor_thread = Thread.new {
  sleep 1
  Ractor.make_shareable(get)
}

sleep 2
```

This prints:
```
1
2
3
4
5
6
7
8
9
10
10
10
10
10
10
10
10
10
10
10
```
But it should print 1..20, and indeed it does when commenting out the `Ractor.make_shareable(get)`.

This shows a given block/Proc instance is concurrently broken by `Ractor.make_shareable`, IOW Ractor is breaking fundamental Ruby semantics of blocks and their captured/outer variables or "environment".

It's expected that `Ractor.make_shareable` can `freeze` objects and that may cause some FrozenError, but here it's not a FrozenError, it's wrong/stale values being read.

I think what should happen instead is that `Ractor.make_shareable` should create a new Proc and mutate that.
However, if the Proc is inside some other object and not just directly the argument, that wouldn't work (like `Ractor.make_shareable([get])`).

So I think one fix would to be to only accept Procs for `Ractor.make_shareable(obj, copy: true)`.
FWIW that currently doesn't allow Procs, it gives `<internal:ractor>:828:in 'Ractor.make_shareable': allocator undefined for Proc (TypeError)`.
It makes sense to use `copy` here since `make_shareable` effectively takes a copy/snapshot of the Proc's environment.

I think the only other way, and I think it would be a far better way would be to not support making Procs shareable with `Ractor.make_shareable`.
Instead it could be some new method like `isolated { ... }` or `Proc.isolated { ... }` or `Proc.snapshot_outer_variables { ... }` or so, only accepting a literal block (to avoid mutating/breaking an existing block), and that would snapshot outer variables (or require no outer variables like Ractor.new's block, or maybe even do `Ractor.make_shareable(copy: true)` on outer variables) and possibly also set `self` since that's anyway needed.
That would make such blocks with different semantics explicit, which would fix the problem of breaking the intention of who wrote that block and whoever read that code, expecting normal Ruby block semantics, which includes seeing updated outer variables.
Related: #21033 https://bugs.ruby-lang.org/issues/18243#note-5

Extracted from https://bugs.ruby-lang.org/issues/21033#note-14



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


In This Thread