Project

General

Profile

Actions

Feature #19627

closed

Ensure the VM is alive before accessing objspace in C API

Added by ianks (Ian Ker-Seymer) over 1 year ago. Updated over 1 year ago.

Status:
Closed
Assignee:
-
Target version:
-
[ruby-core:113386]

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:

  1. Setup an exit handler which sets a global variable (like I did in https://github.com/tmm1/stackprof/pull/200).
  2. 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]
Actions #4

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]

Actions #5

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
Actions

Also available in: Atom PDF

Like1
Like0Like0Like0Like0Like0