Project

General

Profile

Actions

Bug #18023

closed

Ractor#make_shareable changes the values of closured shareable objects

Added by slowpilot (Ivan Razuvaev) 4 months ago. Updated 13 days ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
3.0.0, 3.0.1
[ruby-core:104519]

Description

Hi. I encountered strange behaviour or shareable procs when every even closured shareable variable becomes the FalseClass instance.

[usr@srvr ~]$ irb
3.0.1 :001 > v1, v2, v3, v4 = :a, :b, :c, :d
 => [:a, :b, :c, :d] 
3.0.1 :002 > p = Proc.new { p v1, v2, v3, v4 }
 => #<Proc:0x000000000248ed18 (irb):2> 
3.0.1 :003 > p.()
:a
:b
:c
:d
 => [:a, :b, :c, :d] 
3.0.1 :004 > Ractor.make_shareable(p).()
:a
false
:c
false
 => [:a, false, :c, false] 

Updated by slowpilot (Ivan Razuvaev) 4 months ago

slowpilot (Ivan Razuvaev) wrote:

Hi. I encountered strange behaviour or shareable procs when every even closured shareable variable becomes the FalseClass instance.

[usr@srvr ~]$ irb
3.0.1 :001 > v1, v2, v3, v4 = :a, :b, :c, :d
 => [:a, :b, :c, :d] 
3.0.1 :002 > p = Proc.new { p v1, v2, v3, v4 }
 => #<Proc:0x000000000248ed18 (irb):2> 
3.0.1 :003 > p.()
:a
:b
:c
:d
 => [:a, :b, :c, :d] 
3.0.1 :004 > Ractor.make_shareable(p).()
:a
false
:c
false
 => [:a, false, :c, false] 

This is stopping from using dynamically defined methods from ractors. E.g. in Ruby libtorch. So after calling rb_ext_ractor_safe in extension, I am trying to do something like:

cls.define_singleton_method('new', Ractor.make_shareable(Proc.new { ... })

That leads to every second closure assignment to false.

Actions #2

Updated by alanwu (Alan Wu) 22 days ago

  • Status changed from Open to Closed

Applied in changeset git|76228191474c76810043b294a74bbb2f1808b3d9.


Fix Ractor.make_shareable changing locals for Procs

env_copy() uses rb_ary_delete_at() with a loop counting up while
iterating through the list of read only locals. rb_ary_delete_at() can
shift elements in the array to an index lesser than the loop index,
causing locals to be missed and set to Qfalse in the returned
environment.

Iterate through the locals in reverse instead, this way the shifting
never happens for locals that are yet to be visited and we process all
the locals in the array.

[Bug #18023]

Actions #3

Updated by nagachika (Tomoyuki Chikanaga) 20 days ago

  • Backport changed from 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN to 2.6: DONTNEED, 2.7: DONTNEED, 3.0: REQUIRED

Updated by nagachika (Tomoyuki Chikanaga) 13 days ago

  • Backport changed from 2.6: DONTNEED, 2.7: DONTNEED, 3.0: REQUIRED to 2.6: DONTNEED, 2.7: DONTNEED, 3.0: DONE

ruby_3_0 5427b08381fb0d644ec69d5aa94234f90a4fbed1 merged revision(s) 76228191474c76810043b294a74bbb2f1808b3d9.

Actions

Also available in: Atom PDF