You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
$ ruby -reventmachine -e 'at_exit { puts "bye" }; EventMachine.setuid_string "unknown"'
terminate called after throwing an instance of 'std::runtime_error'what(): setuid_string failed: No such file or directory
Aborted (core dumped)
$ echo$?
134
I understand that immediate abort is intended, but I believe rb_fatal should be used to wrap all unhandled C++ exceptions, as letting them pass across library boundaries is not considered a good practice.
vladimir@np940x5n:~$ irb3.0.2:001 > require'ffi'=>true3.0.2:002 > moduleRbFFI3.0.2:003 > extendFFI::Library3.0.2:004 > ffi_libFFI::CURRENT_PROCESS3.0.2:005 > end=>[#<FFI::DynamicLibrary:0x000058dfabc49850 @name="[current process]">] 3.0.2:006 > require'fiddle'=>false3.0.2:007 > rb_eException=Fiddle.dlwrapException# Just a hacky way to convert get VALUE representation of Ruby object =>977176564527203.0.2:008 > RbFFI.attach_function :rb_define_class,[:string,:ulong],:ulong=>#<FFI::Function address=0x00007bd66cc67d10> 3.0.2:009 > rb_eFatal=RbFFI.rb_define_class("fatal",rb_eException)=>977176564514403.0.2:010 > rb_eFatal=RbFFI.rb_define_class("fatal",rb_eException)=>977176564514403.0.2:011 > RbFFI.attach_function :rb_raise,[:ulong,:string,:varargs],:void=>#<FFI::VariadicInvoker:0x000058dfacb21bc0@fixed=[#<FFI::Type::Builtin::ULONG size=8 alignment=8>, #<FFI::Type::Builtin::STRING size=8 alignment=8>],@type_map=nil>
3.0.2:012 > RbFFI.rb_raiserb_eFatal,"fatal"
/home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:47:in`invoke': fatal (fatal) from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:47:in `call' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:62:in `rb_raise'from(irb):12:in`<main>' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/exe/irb:9:in `<top(required)>' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/irb:25:in `load'from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/irb:25:in`<main>' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/ruby_executable_hooks:22:in `eval' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/ruby_executable_hooks:22:in `<main>'3.0.2:013 > RbFFI.rb_raiserb_eException,"fatal"
/home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:47:in`invoke': fatal (Exception) from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:47:in `call' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:62:in `rb_raise'from(irb):13:in`<main>' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/exe/irb:9:in `<top(required)>' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/irb:25:in `load'from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/irb:25:in`<main>' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/ruby_executable_hooks:22:in `eval' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/ruby_executable_hooks:22:in `<main>'3.0.2:014 > RbFFI.attach_function :rb_fatal,[:string,:varargs],:void=>#<FFI::VariadicInvoker:0x000058dfab66d170 @fixed=[#<FFI::Type::Builtin::STRING size=8 alignment=8>], @type_map=nil> 3.0.2:015 > RbFFI.rb_fatal"faaaaaaaaaaaaaaaaatal"
/home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:47:in`invoke': faaaaaaaaaaaaaaaaatal (fatal) from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:47:in `call' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:62:in `rb_fatal'from(irb):15:in`<top (required)>' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb/workspace.rb:121:in `eval' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb/workspace.rb:121:in `evaluate'from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb/context.rb:633:in`evaluate_expression' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb/context.rb:601:in `evaluate' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1049:in `block (2 levels) in eval_input'from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1388:in`signal_status' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1041:in `blockineval_input' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1120:in `block in each_top_level_statement'from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1117:in`loop' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1117:in `each_top_level_statement' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1040:in `eval_input'from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1021:in`block in run' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1020:in `catch' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1020:in `run'from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:904:in`start' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/exe/irb:9:in `<top(required)>' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/irb:25:in `load'from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/irb:25:in`<main>' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/ruby_executable_hooks:22:in `eval' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/ruby_executable_hooks:22:in `<main>'vladimir@np940x5n:~$ irb3.0.2:001 > require'ffi'=>true3.0.2:002 > moduleRbFFI3.0.2:003 > extendFFI::Library3.0.2:004 > ffi_libFFI::CURRENT_PROCESS3.0.2:005 > end=>[#<FFI::DynamicLibrary:0x000060ee91216340 @name="[current process]">] 3.0.2:006 > RbFFI.attach_function:rb_fatal,[:string,:varargs],:void=>#<FFI::VariadicInvoker:0x000060ee911b43c0 @fixed=[#<FFI::Type::Builtin::STRING size=8 alignment=8>], @type_map=nil> 3.0.2:007 > at_exit{puts'byebye'}=>#<Proc:0x000060ee9124ed08 (irb):7> 3.0.2:008 > RbFFI.rb_fatal"faaaaaaaaaaaaaaaaatal"byebye
/home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:47:in`invoke': faaaaaaaaaaaaaaaaatal (fatal) from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:47:in `call' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/ffi-1.16.3/lib/ffi/variadic.rb:62:in `rb_fatal'from(irb):8:in`<top (required)>' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb/workspace.rb:121:in `eval' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb/workspace.rb:121:in `evaluate'from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb/context.rb:633:in`evaluate_expression' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb/context.rb:601:in `evaluate' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1049:in `block (2 levels) in eval_input'from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1388:in`signal_status' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1041:in `blockineval_input' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1120:in `block in each_top_level_statement'from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1117:in`loop' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1117:in `each_top_level_statement' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1040:in `eval_input'from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1021:in`block in run' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1020:in `catch' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:1020:in `run'from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/lib/irb.rb:904:in`start' from /home/vladimir/.local/share/rtx/installs/ruby/3.0.2/lib/ruby/gems/3.0.0/gems/irb-1.14.0/exe/irb:9:in `<top(required)>' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/irb:25:in `load'from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/irb:25:in`<main>' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/ruby_executable_hooks:22:in `eval' from /home/vladimir/.local/share/mise/installs/ruby/3.0.2/bin/ruby_executable_hooks:22:in `<main>'vladimir@np940x5n:~$
As you can see, rb_fatal is not the same as just using rb_throw with rb_eFatal, it cannot be rescued, but it's not the same as throwing unhandled C++ exception, although abort() is called in the end, some sort of cleanup is performed (when possible), and at_exit was called.
Activity
uvlad7 commentedon Sep 1, 2024
Here are some examples:
As you can see,
rb_fatalis not the same as just usingrb_throwwithrb_eFatal, it cannot be rescued, but it's not the same as throwing unhandled C++ exception, althoughabort()is called in the end, some sort of cleanup is performed (when possible), andat_exitwas called.