Bug #19387
closedObjectSpace.each_objects only returns shareable objects after starting a Ractor
Added by luke-gru (Luke Gruber) over 3 years ago. Updated 13 days ago.
Description
Updated by luke-gru (Luke Gruber) over 3 years ago
Actions
#1
[ruby-core:112092]
- Subject changed from Issue with ObjectSpace.each_objects not returning IO objects after starting a ractor to Issue with ObjectSpace.each_objects not returning objects after starting a ractor
The problem is actually for any objects, not just IO.
PR here: https://github.com/ruby/ruby/pull/7191
Edit: I took down the PR because I realized it doesn't properly fix the issue. The only way to get this working, and also to get ObjectSpace._id2ref working, is to keep the RACTOR_BELONGING_ID in all builds, and use that info when letting ractors access the objects.
I'll create another PR with that in mind. But I'm wondering why was this only in debug builds? Does it have to do with speed?
Updated by hsbt (Hiroshi SHIBATA) over 3 years ago
Actions
#2
[ruby-core:112252]
- Status changed from Open to Assigned
- Assignee set to ko1 (Koichi Sasada)
Updated by Anonymous about 3 years ago
Actions
#3
- Status changed from Assigned to Closed
Applied in changeset git|c08fdc68383ee368c18e15e298502e6ee0089e18.
Allow waitpid(-1) to be woken if a waitpid(pid) call is pending
If two threads are running, with one calling waitpid(-1), and another
calling waitpid($some_pid), and then $some_other_pid exits, we would
expect the waitpid(-1) call to retrieve that exit status; however, it
cannot actually do so until $some_pid also exits.
This patch fixes the issue by unconditionally checking for pending
process group waits on SIGCHLD, and then allowing pending pid-only waits
to "steal" the notification.
[Fixes #19387]
Updated by ko1 (Koichi Sasada) about 3 years ago
Actions
#4
[ruby-core:114638]
- Status changed from Closed to Assigned
c08fdc68383ee368c18e15e298502e6ee0089e18 is not related to this ticket.
Updated by Anonymous about 3 years ago
Actions
#5
- Status changed from Assigned to Closed
Applied in changeset git|0b7a4fbaa9c56d2c67d00d86c69f9e5c71803267.
Allow waitpid(-1) to be woken if a waitpid(pid) call is pending
If two threads are running, with one calling waitpid(-1), and another
calling waitpid($some_pid), and then $some_other_pid exits, we would
expect the waitpid(-1) call to retrieve that exit status; however, it
cannot actually do so until $some_pid also exits.
This patch fixes the issue by unconditionally checking for pending
process group waits on SIGCHLD, and then allowing pending pid-only waits
to "steal" the notification.
[Fixes #19387]
Updated by luke-gru (Luke Gruber) over 2 years ago
Actions
#6
[ruby-core:116017]
- ruby -v set to 3.3.0
I believe this was closed prematurely due to an unrelated git commit that wrongly tagged it. Please reopen :)
Updated by jeremyevans0 (Jeremy Evans) over 2 years ago
Actions
#7
- Status changed from Closed to Open
Updated by Anonymous over 2 years ago
Actions
#8
- Status changed from Open to Closed
Applied in changeset git|76a8c963c7ad975b7bbfc1c4979bf7a2de15af27.
Add a test for what happens with concurent calls to waitpid
Ruby 3.1 and 3.2 have a bug in their implementation, for which I'm
backporting a fix. However, the current development branch doesn't have
the issue (because the MJIT -> RJIT change refactored how waitpid worked
substantially). I do however want to commit the test which verifies
that waitpid works properly on master.
[Fixes #19387]
Updated by luke-gru (Luke Gruber) over 2 years ago
Actions
#9
[ruby-core:116168]
It happened again :( I notified the committer of the mistake. Please reopen, thanks!
Updated by jeremyevans0 (Jeremy Evans) over 2 years ago
Actions
#10
- Status changed from Closed to Open
Updated by hsbt (Hiroshi SHIBATA) over 2 years ago
Actions
#11
- Status changed from Open to Assigned
Updated by wanabe (_ wanabe) over 1 year ago
Actions
#12
- Has duplicate Bug #21149: Strange behavior of ObjectSpace.each_object after Ractor.new added
Updated by Eregon (Benoit Daloze) over 1 year ago
Actions
#13
[ruby-core:121311]
One idea to solve this would be to implement ObjectSpace.each_object like TruffleRuby does it (at least when there are multiple Ractors):
basically it's just the transitive ObjectSpace.reachable_objects_from(roots).
I.e. it uses the same mechanism as GC traversal/marking to find every object reachable from some roots objects (like Object class, the stack frames, etc).
Context: the latest breakage due to this bug: https://github.com/ruby/prism/pull/3491
And I know of many before, it's a very common issue that Ractor.new can't be used in make test-all.
Updated by tenderlovemaking (Aaron Patterson) over 1 year ago
Actions
#14
[ruby-core:121442]
- Assignee changed from ko1 (Koichi Sasada) to ractor
Updated by osyoyu (Daisuke Aritomo) over 1 year ago
Actions
#15
[ruby-core:121929]
I also ran into this, so I opened an pull request document this behavior.
https://github.com/ruby/ruby/pull/13278
Updated by Eregon (Benoit Daloze) over 1 year ago
Actions
#16
- Related to Feature #17270: ObjectSpace.each_object should be restricted on multi-Ractors added
Updated by jhawthorn (John Hawthorn) over 1 year ago
Actions
#17
- Has duplicate Bug #21401: ObjectSpace can't count Fibers after using a Ractor added
Updated by jhawthorn (John Hawthorn) over 1 year ago
Actions
#18
- Subject changed from Issue with ObjectSpace.each_objects not returning objects after starting a ractor to ObjectSpace.each_objects only returns shareable objects after starting a Ractor
Updated by ko1 (Koichi Sasada) 13 days ago
Actions
#19
[ruby-core:126602]
- Status changed from Assigned to Closed
Re-checked on master 4d185cce78: this no longer reproduces.
With per-Ractor GC (GH-18194) each Ractor has its own objspace, and
ObjectSpace.each_object walks the calling Ractor's objspace directly, so it keeps
working while other Ractors are alive:
port = Ractor::Port.new
r = Ractor.new(port) { |p| p << :up; Ractor.receive }
port.receive
p ObjectSpace.each_object(IO).count
ruby 4.0.2 : 0
master : 3
Isolation is still respected. Letting a sub-Ractor build one unshareable and one
shareable String and scanning for them from the main Ractor:
4.0.2 master
own unshareable objects no yes
another Ractor's unshareable objects no no
another Ractor's shareable objects yes yes
(the last row needs the object to have actually been made shareable; a merely frozen
String that nobody has shared yet does not carry the flag and is not enumerated.)
So the reported symptom -- each_object yields nothing once a Ractor has been started
-- is gone, and Ractor.new can be used in make test-all again.
One follow-up: the documentation added in GH-13278 ("Due to a current Ractor
implementation issue, this method does not yield Ractor-unshareable objects when the
process is in multi-Ractor mode", which links to this ticket) is now wrong. I will send
a separate PR for it.