Project

General

Profile

Bug #20155

Updated by paddor (Patrik Wenger) 12 months ago

While trying to manually block/unblock fibers from an extension using the Fiber Scheduler, 
 I noticed that using the return value of `rb_fiber_scheduler_current()` crashes Ruby. 

 I've created a minimal extension gem called "fiber_blocker". Its test suite shows the behavior. See https://github.com/paddor/fiber_blocker, especially the lines containing `FIXME`. 

 Passing `Fiber.scheduler` to the extension functions works. But letting it get the current scheduler itself does not seem to work. 

 Is `rb_fiber_scheduler_current()`(within a non-blocking Fiber) `rb_fiber_scheduler_current()` not the equivalent to `Fiber.scheduler`? 
 Even just printing the its return value with `#p` will crash Ruby. 


 Ruby either crashes like this: 
 ``` 
 # Running: 

 T1 BEGIN 
 T2 BEGIN 
 T1 END 
 ..T1 BEGIN 
 ext: blocking fiber 
 passed scheduler = #<Scheduler:0x00007fc5f22d39e8 @readable={}, @writable={}, @waiting={}, @closed=false, @lock=#<Thread::Mutex:0x00007fc5f22ec8d0>, @blocking={}, @ready=[], @urgent=[#<IO:fd 5>, #<IO:fd 6>]> 
 T2 BEGIN 
 ext: unblocking fiber 
 T1 END 
 .E 

 Finished in 1.007014s, 3.9721 runs/s, 2.9791 assertions/s. 

   1) Error: 
 TestFiberBlocker#test_fiber_blocker_current_fiber: 
 fatal: machine stack overflow in critical region 
     No backtrace 
 ``` 

 Or with a segfault: 
 ``` 
 # Running: 

 FiberBlocker.test works. 
 .T1 BEGIN 
 T2 BEGIN 
 T1 END 
 .T1 BEGIN 
 ext: blocking fiber 
 /home/user/dev/oss/async_ruby_test/rbnng/fiber_blocker/test/test_fiber_blocker.rb:40: [BUG] Segmentation fault at 0x00000000390d8f98 
 ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux] 

 -- Control frame information ----------------------------------------------- 
 c:0003 p:---- s:0012 e:000011 CFUNC    :block_fiber 
 c:0002 p:0014 s:0006 e:000005 BLOCK    /home/user/dev/oss/async_ruby_test/rbnng/fiber_blocker/test/test_fiber_blocker.rb:40 [FINISH] 
 c:0001 p:---- s:0003 e:000002 DUMMY    [FINISH] 

 -- Ruby level backtrace information ---------------------------------------- 
 /home/user/dev/oss/async_ruby_test/rbnng/fiber_blocker/test/test_fiber_blocker.rb:40:in `block in test_fiber_blocking_in_ext' 
 /home/user/dev/oss/async_ruby_test/rbnng/fiber_blocker/test/test_fiber_blocker.rb:40:in `block_fiber' 

 -- Threading information --------------------------------------------------- 
 Total ractor count: 1 
 Ruby thread count for this ractor: 4 

 -- Machine register context ------------------------------------------------ 
  RIP: 0x00007f1554f17ad8 RBP: 0x00000000390d8f90 RSP: 0x00007f153a79e280 
  RAX: 0x00007f1554addba8 RBX: 0x00007f153a79eab0 RCX: 0x0000000000000000 
  RDX: 0x00007f1554ade600 RDI: 0x00007f15551e8788 RSI: 0x0000000000000ae1 
   R8: 0x000000000000002b    R9: 0x00007f153a79f038 R10: 0x00007f1554c0b9b0 
  R11: 0x00007f153a79e490 R12: 0x0000000000000ae1 R13: 0x0000000000000000 
  R14: 0x0000000000000000 R15: 0x000055ab732d7df0 EFL: 0x0000000000010206 

 -- C level backtrace information ------------------------------------------- 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_print_backtrace+0x14) [0x7f1554f24961] /home/user/src/ruby-3.3.0/vm_dump.c:820 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_vm_bugreport) /home/user/src/ruby-3.3.0/vm_dump.c:1151 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_bug_for_fatal_signal+0x104) [0x7f1554d1c214] /home/user/src/ruby-3.3.0/error.c:1065 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(sigsegv+0x4f) [0x7f1554e700df] /home/user/src/ruby-3.3.0/signal.c:926 
 /lib/x86_64-linux-gnu/libc.so.6(0x7f1554842520) [0x7f1554842520] 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(RBASIC_CLASS+0x0) [0x7f1554f17ad8] ./include/ruby/internal/globals.h:178 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(gccct_method_search) /home/user/src/ruby-3.3.0/vm_eval.c:475 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_funcallv_scope) /home/user/src/ruby-3.3.0/vm_eval.c:1063 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_funcallv) /home/user/src/ruby-3.3.0/vm_eval.c:1084 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_inspect+0x19) [0x7f1554dc1569] /home/user/src/ruby-3.3.0/object.c:697 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(ruby__sfvextra+0x11a) [0x7f1554e7223a] /home/user/src/ruby-3.3.0/sprintf.c:1119 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(BSD_vfprintf+0xa69) [0x7f1554e73059] /home/user/src/ruby-3.3.0/vsnprintf.c:830 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(RBASIC_SET_CLASS_RAW+0x0) [0x7f1554e75b56] /home/user/src/ruby-3.3.0/sprintf.c:1168 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(ruby_vsprintf0) /home/user/src/ruby-3.3.0/sprintf.c:1169 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_enc_vsprintf+0x5d) [0x7f1554e75ecd] /home/user/src/ruby-3.3.0/sprintf.c:1195 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_sprintf+0x9d) [0x7f1554e7607d] /home/user/src/ruby-3.3.0/sprintf.c:1225 
 /home/user/dev/oss/async_ruby_test/rbnng/fiber_blocker/lib/fiber_blocker/fiber_blocker.so(block_fiber+0x4a) [0x7f1554ad430a] ../../../../ext/fiber_blocker/fiber_blocker.c:29 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_cfp_consistent_p+0x0) [0x7f1554ef64b4] /home/user/src/ruby-3.3.0/vm_insnhelper.c:3490 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_call_cfunc_with_frame_) /home/user/src/ruby-3.3.0/vm_insnhelper.c:3492 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_call_cfunc_with_frame) /home/user/src/ruby-3.3.0/vm_insnhelper.c:3518 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_call_cfunc_other) /home/user/src/ruby-3.3.0/vm_insnhelper.c:3544 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_sendish+0x9e) [0x7f1554f06f87] /home/user/src/ruby-3.3.0/vm_insnhelper.c:5581 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(vm_exec_core) /home/user/src/ruby-3.3.0/insns.def:834 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_vm_exec+0x19a) [0x7f1554f0d1fa] /home/user/src/ruby-3.3.0/vm.c:2486 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_vm_invoke_proc+0x5f) [0x7f1554f12e0f] /home/user/src/ruby-3.3.0/vm.c:1728 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_fiber_start+0x1ba) [0x7f1554cf098a] /home/user/src/ruby-3.3.0/cont.c:2536 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(fiber_entry+0x20) [0x7f1554cf0d00] /home/user/src/ruby-3.3.0/cont.c:847 
 /home/user/.rubies/ruby-3.3.0/lib/libruby.so.3.3(rb_threadptr_root_fiber_setup) (null):0 
 ``` 

 This happens with the Async scheduler as well as with Ruby’s test scheduler. My minimal extension uses Ruby’s. 

 I hope I'm not missing something obvious. My C isn't very good.

Back