Feature #19627
closedEnsure the VM is alive before accessing objspace in C API
Description
Currently, there is no supported way to check if the Ruby VM has been shut down. There are a couple of workarounds that I know of:
- Setup an exit handler which sets a global variable (like I did in https://github.com/tmm1/stackprof/pull/200).
- In Ruby 2.4 thru 3.2, you could check the hidden
ruby_vm_global_ptr != NULL
.
For my use, in rb-sys there is a feature to automatically report Rust memory allocations via rb_gc_adjust_memory_usage
. However, there is a bug that can cause processes to deadlock and/or segfault if a Rust destructor gets called after the VM quits (which can happen in Rust background threads). Currently, I don’t think there’s a way to safely make this feature work. (https://github.com/oxidize-rb/rb-sys/pull/205)
It would be nice to have an official way to know if the Ruby VM is available, basically just a ruby_current_vm_ptr != null
. Thoughts?
Updated by mdalessio (Mike Dalessio) over 1 year ago
I reported a related issue in https://bugs.ruby-lang.org/issues/19580 which I fixed with https://github.com/ruby/ruby/pull/7663
Maybe you want to explore a similar fix which will short-circuit functions like rb_gc_adjust_memory_usage
instead of forcing callers to figure out if it's safe?
Updated by ianks (Ian Ker-Seymer) over 1 year ago
That’s a good idea. I’ll put a patch up for that.
So far I’ve encountered this issue this issue in rb_gc_adjust_memory_usage
and rb_during_gc
, so I still think having the ability to check for a Ruby VM is important for writing robust code. At the very least, it would provide an escape hatch in case there are undiscovered edge cases lurking.
Updated by ianks (Ian Ker-Seymer) over 1 year ago
For documentations sake, he's a real world reproduction of this issue that happens when calling TLS destructors. In Ruby < 3.3-dev, I'm able to avoid this by checking the hidden ruby_current_vm_ptr
symbol so the code won't segfault after VM shutdown.
-- C level backtrace information -------------------------------------------
/home/runner/.rubies/ruby-head/lib/libruby.so.3.3(rb_print_backtrace+0xd) [0x7f360aab3a3f] /home/runner/work/ruby-dev-builder/ruby-dev-builder/vm_dump.c:785
/home/runner/.rubies/ruby-head/lib/libruby.so.3.3(rb_vm_bugreport) /home/runner/work/ruby-dev-builder/ruby-dev-builder/vm_dump.c:1101
/home/runner/.rubies/ruby-head/lib/libruby.so.3.3(rb_bug_for_fatal_signal+0xf4) [0x7f360a8b8c94] /home/runner/work/ruby-dev-builder/ruby-dev-builder/error.c:814
/home/runner/.rubies/ruby-head/lib/libruby.so.3.3(sigsegv+0x4d) [0x7f360a9feecd] /home/runner/work/ruby-dev-builder/ruby-dev-builder/signal.c:964
/lib/x86_64-linux-gnu/libc.so.6(0x7f360a413520) [0x7f360a413520]
/home/runner/.rubies/ruby-head/lib/libruby.so.3.3(rb_gc_adjust_memory_usage+0xe) [0x7f360a8dedbe] /home/runner/work/ruby-dev-builder/ruby-dev-builder/gc.c:12743
/lib/x86_64-linux-gnu/libc.so.6(__call_tls_dtors+0x3f) [0x7f360a416d9f]
/lib/x86_64-linux-gnu/libc.so.6(0x7f360a4165c9) [0x7f360a4165c9]
/lib/x86_64-linux-gnu/libc.so.6(on_exit+0x20) [0x7f360a416610]
/lib/x86_64-linux-gnu/libc.so.6(0x7f360a3fad97) [0x7f360a3fad97]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80) [0x7f360a3fae40]
[0x55e16aa391d5]
Updated by ianks (Ian Ker-Seymer) over 1 year ago
- Status changed from Open to Closed
Applied in changeset git|2f9f44f077a53b14aa1fbd43111955251750d31f.
Ensure the VM is alive before accessing objspace in C API (Feature #19627)
[Feature #19627]
Updated by byroot (Jean Boussier) over 1 year ago
- Subject changed from Add a way to detect if the Ruby VM is running in C API to Ensure the VM is alive before accessing objspace in C API