[ruby-core:115349] [Ruby master Feature#20002] Print C-level backtrace on uncaught Ruby exceptions

Issue #20002 has been reported by osyoyu (Daisuke Aritomo). ---------------------------------------- Feature #20002: Print C-level backtrace on uncaught Ruby exceptions https://bugs.ruby-lang.org/issues/20002 * Author: osyoyu (Daisuke Aritomo) * Status: Open * Priority: Normal ---------------------------------------- When a uncaught Ruby exception occurs, the Ruby-level backtrace is printed. While this information is valuable for debugging Ruby code, this isn't necessarily the case when developing C extensions, since this message has no information about C code. In this example, the printed message only tells us that something is wrong inside `will_raise`. There are not much ways to debug further; the programmer must guess which Ruby API call is causing the exception. A C-level backtrace which includes the `VALUE x = NUM2INT(rb_str_new_cstr("1"));` line would be very helpful here. ``` % ruby main.rb main.rb:9:in `will_raise': no implicit conversion of String into Integer (TypeError) will_raise ^^^^^^^^^^ from main.rb:9:in `bar' from main.rb:4:in `foo' from main.rb:12:in `<main> ``` ```ruby require_relative "./ext" def foo bar end def bar will_raise end foo ``` ```c #include <ruby/ruby.h> VALUE will_raise(VALUE self) { // Do many things // There is no information leading to this line in the printed message VALUE x = NUM2INT(rb_str_new_cstr("1")); // no implicit conversion of String into Integer (TypeError) return Qtrue; } void Init_ext(void) { rb_define_method(rb_mKernel, "will_raise", will_raise, 0); } ``` I'm imagining something similar to the segfault report. In this case, it is clear that some code caused a SIGSEGV in `ext.c:12` (which is `int *p = NULL; *p = 1;`). ``` -- C level backtrace information ------------------------------------------- /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_print_backtrace+0x14) [0x55dd24893174] /home/osyoyu/ruby/build/../vm_dump.c:812 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_vm_bugreport) /home/osyoyu/ruby/build/../vm_dump.c:1140 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_bug_for_fatal_signal+0x14c) [0x55dd24a064cc] /home/osyoyu/ruby/build/../error.c:1065 /home/osyoyu/.rbenv/versions/master/bin/ruby(sigsegv+0x51) [0x55dd24801c01] /home/osyoyu/ruby/build/../signal.c:920 /usr/lib/libc.so.6(0x7f6926558710) [0x7f6926558710] /home/osyoyu/ruby-bug/ext.so(will_segv+0x14) [0x7f69264fc244] /home/osyoyu/ruby-bug/ext.c:12 /home/osyoyu/ruby-bug/ext.so(will_segv) (null):0 /home/osyoyu/.rbenv/versions/master/bin/ruby(vm_call_cfunc_with_frame_+0xf4) [0x55dd24885d64] ../vm_insnhelper.c:3477 /home/osyoyu/.rbenv/versions/master/bin/ruby(vm_sendish+0xdd) [0x55dd2486aee1] ../vm_insnhelper.c:5555 /home/osyoyu/.rbenv/versions/master/bin/ruby(vm_exec_core) ../insns.def:835 ruby(vm_exec_loop+0x0) [0x55dd24867c52] /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_vm_exec) /home/osyoyu/ruby/build/../vm.c:2420 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_ec_exec_node+0x2b) [0x55dd246e9fab] /home/osyoyu/ruby/build/../eval.c:287 /home/osyoyu/.rbenv/versions/master/bin/ruby(ruby_run_node) /home/osyoyu/ruby/build/../eval.c:328 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_main+0x1c) [0x55dd246e7a85] /home/osyoyu/ruby/build/../main.c:39 /home/osyoyu/.rbenv/versions/master/bin/ruby(main) /home/osyoyu/ruby/build/../main.c:58 /usr/lib/libc.so.6(0x7f6926541cd0) [0x7f6926541cd0] /usr/lib/libc.so.6(__libc_start_main+0x8a) [0x7f6926541d8a] [0x55dd246e7935] ``` As most Ruby users might not be interested in C-level information, this behavior could be made optional through startup options or environment variables. -- https://bugs.ruby-lang.org/

Issue #20002 has been updated by byroot (Jean Boussier). Maybe you already know, but when debugging a C extension you can trigger a crash report with `rb_bug("message")`. ---------------------------------------- Feature #20002: Print C-level backtrace on uncaught Ruby exceptions https://bugs.ruby-lang.org/issues/20002#change-105276 * Author: osyoyu (Daisuke Aritomo) * Status: Open * Priority: Normal ---------------------------------------- When a uncaught Ruby exception occurs, the Ruby-level backtrace is printed. While this information is valuable for debugging Ruby code, this isn't necessarily the case when developing C extensions, since this message has no information about C code. In this example, the printed message only tells us that something is wrong inside `will_raise`. There are not much ways to debug further; the programmer must guess which Ruby API call is causing the exception. A C-level backtrace which includes the `VALUE x = NUM2INT(rb_str_new_cstr("1"));` line would be very helpful here. ``` % ruby main.rb main.rb:9:in `will_raise': no implicit conversion of String into Integer (TypeError) will_raise ^^^^^^^^^^ from main.rb:9:in `bar' from main.rb:4:in `foo' from main.rb:12:in `<main> ``` ```ruby require_relative "./ext" def foo bar end def bar will_raise end foo ``` ```c #include <ruby/ruby.h> VALUE will_raise(VALUE self) { // Do many things // There is no information leading to this line in the printed message VALUE x = NUM2INT(rb_str_new_cstr("1")); // no implicit conversion of String into Integer (TypeError) return Qtrue; } void Init_ext(void) { rb_define_method(rb_mKernel, "will_raise", will_raise, 0); } ``` I'm imagining something similar to the segfault report. In this case, it is clear that some code caused a SIGSEGV in `ext.c:12` (which is `int *p = NULL; *p = 1;`). ``` -- C level backtrace information ------------------------------------------- /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_print_backtrace+0x14) [0x55dd24893174] /home/osyoyu/ruby/build/../vm_dump.c:812 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_vm_bugreport) /home/osyoyu/ruby/build/../vm_dump.c:1140 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_bug_for_fatal_signal+0x14c) [0x55dd24a064cc] /home/osyoyu/ruby/build/../error.c:1065 /home/osyoyu/.rbenv/versions/master/bin/ruby(sigsegv+0x51) [0x55dd24801c01] /home/osyoyu/ruby/build/../signal.c:920 /usr/lib/libc.so.6(0x7f6926558710) [0x7f6926558710] /home/osyoyu/ruby-bug/ext.so(will_segv+0x14) [0x7f69264fc244] /home/osyoyu/ruby-bug/ext.c:12 /home/osyoyu/ruby-bug/ext.so(will_segv) (null):0 /home/osyoyu/.rbenv/versions/master/bin/ruby(vm_call_cfunc_with_frame_+0xf4) [0x55dd24885d64] ../vm_insnhelper.c:3477 /home/osyoyu/.rbenv/versions/master/bin/ruby(vm_sendish+0xdd) [0x55dd2486aee1] ../vm_insnhelper.c:5555 /home/osyoyu/.rbenv/versions/master/bin/ruby(vm_exec_core) ../insns.def:835 ruby(vm_exec_loop+0x0) [0x55dd24867c52] /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_vm_exec) /home/osyoyu/ruby/build/../vm.c:2420 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_ec_exec_node+0x2b) [0x55dd246e9fab] /home/osyoyu/ruby/build/../eval.c:287 /home/osyoyu/.rbenv/versions/master/bin/ruby(ruby_run_node) /home/osyoyu/ruby/build/../eval.c:328 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_main+0x1c) [0x55dd246e7a85] /home/osyoyu/ruby/build/../main.c:39 /home/osyoyu/.rbenv/versions/master/bin/ruby(main) /home/osyoyu/ruby/build/../main.c:58 /usr/lib/libc.so.6(0x7f6926541cd0) [0x7f6926541cd0] /usr/lib/libc.so.6(__libc_start_main+0x8a) [0x7f6926541d8a] [0x55dd246e7935] ``` As most Ruby users might not be interested in C-level information, this behavior could be made optional through startup options or environment variables. -- https://bugs.ruby-lang.org/

Issue #20002 has been updated by osyoyu (Daisuke Aritomo). byroot (Jean Boussier) wrote in #note-1:
Maybe you already know, but when debugging a C extension you can trigger a crash report with `rb_bug("message")`.
Yes, but the problem is that it is difficult to know where the exception is raised (which would be a good place to insert a `rb_bug()` call). (I'm finding `rb_bug()` to be an assert-ish function to be called in unlikely situations, but I might be missing a point here) ---------------------------------------- Feature #20002: Print C-level backtrace on uncaught Ruby exceptions https://bugs.ruby-lang.org/issues/20002#change-105277 * Author: osyoyu (Daisuke Aritomo) * Status: Open * Priority: Normal ---------------------------------------- When a uncaught Ruby exception occurs, the Ruby-level backtrace is printed. While this information is valuable for debugging Ruby code, this isn't necessarily the case when developing C extensions, since this message has no information about C code. In this example, the printed message only tells us that something is wrong inside `will_raise`. There are not much ways to debug further; the programmer must guess which Ruby API call is causing the exception. A C-level backtrace which includes the `VALUE x = NUM2INT(rb_str_new_cstr("1"));` line would be very helpful here. ``` % ruby main.rb main.rb:9:in `will_raise': no implicit conversion of String into Integer (TypeError) will_raise ^^^^^^^^^^ from main.rb:9:in `bar' from main.rb:4:in `foo' from main.rb:12:in `<main> ``` ```ruby require_relative "./ext" def foo bar end def bar will_raise end foo ``` ```c #include <ruby/ruby.h> VALUE will_raise(VALUE self) { // Do many things // There is no information leading to this line in the printed message VALUE x = NUM2INT(rb_str_new_cstr("1")); // no implicit conversion of String into Integer (TypeError) return Qtrue; } void Init_ext(void) { rb_define_method(rb_mKernel, "will_raise", will_raise, 0); } ``` I'm imagining something similar to the segfault report. In this case, it is clear that some code caused a SIGSEGV in `ext.c:12` (which is `int *p = NULL; *p = 1;`). ``` -- C level backtrace information ------------------------------------------- /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_print_backtrace+0x14) [0x55dd24893174] /home/osyoyu/ruby/build/../vm_dump.c:812 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_vm_bugreport) /home/osyoyu/ruby/build/../vm_dump.c:1140 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_bug_for_fatal_signal+0x14c) [0x55dd24a064cc] /home/osyoyu/ruby/build/../error.c:1065 /home/osyoyu/.rbenv/versions/master/bin/ruby(sigsegv+0x51) [0x55dd24801c01] /home/osyoyu/ruby/build/../signal.c:920 /usr/lib/libc.so.6(0x7f6926558710) [0x7f6926558710] /home/osyoyu/ruby-bug/ext.so(will_segv+0x14) [0x7f69264fc244] /home/osyoyu/ruby-bug/ext.c:12 /home/osyoyu/ruby-bug/ext.so(will_segv) (null):0 /home/osyoyu/.rbenv/versions/master/bin/ruby(vm_call_cfunc_with_frame_+0xf4) [0x55dd24885d64] ../vm_insnhelper.c:3477 /home/osyoyu/.rbenv/versions/master/bin/ruby(vm_sendish+0xdd) [0x55dd2486aee1] ../vm_insnhelper.c:5555 /home/osyoyu/.rbenv/versions/master/bin/ruby(vm_exec_core) ../insns.def:835 ruby(vm_exec_loop+0x0) [0x55dd24867c52] /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_vm_exec) /home/osyoyu/ruby/build/../vm.c:2420 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_ec_exec_node+0x2b) [0x55dd246e9fab] /home/osyoyu/ruby/build/../eval.c:287 /home/osyoyu/.rbenv/versions/master/bin/ruby(ruby_run_node) /home/osyoyu/ruby/build/../eval.c:328 /home/osyoyu/.rbenv/versions/master/bin/ruby(rb_main+0x1c) [0x55dd246e7a85] /home/osyoyu/ruby/build/../main.c:39 /home/osyoyu/.rbenv/versions/master/bin/ruby(main) /home/osyoyu/ruby/build/../main.c:58 /usr/lib/libc.so.6(0x7f6926541cd0) [0x7f6926541cd0] /usr/lib/libc.so.6(__libc_start_main+0x8a) [0x7f6926541d8a] [0x55dd246e7935] ``` As most Ruby users might not be interested in C-level information, this behavior could be made optional through startup options or environment variables. -- https://bugs.ruby-lang.org/
participants (2)
-
byroot (Jean Boussier)
-
osyoyu (Daisuke Aritomo)