From: Suraj Kurapati Date: 2009-09-21T13:34:31+09:00 Subject: [ruby-core:25689] [Bug #2127] Fiber#resume - segfault inside C extension Issue #2127 has been updated by Suraj Kurapati. I found an answer to my question: The trick is to always work with the Fiber inside the environment (a running thread?) provided by rb_protect(). If you try to do anything to the Fiber (other than #inspect) outside of rb_protect(), a segfault occurs (see the NOTE comment in the example below). Below is an updated example that shows the answer to my question. Cheers. ############################################################### # cat main.c ############################################################### #include #include VALUE my_fiber_body(VALUE arg) { printf("Fiber: Entering fiber body\n"); int i; for (i = 0; i < 5; i++) { printf("Fiber: going to yield=%d\n", i); VALUE count = INT2FIX(i); rb_fiber_yield(1, &count); } printf("Fiber: Exiting fiber body\n"); return Qtrue; } VALUE create_my_fiber(VALUE arg) { VALUE fib = rb_fiber_new(my_fiber_body, arg), dump; printf("create_my_fiber: Created my fiber="); fflush(stdout); dump = rb_inspect(fib); rb_io_puts(1, &dump, rb_stdout); return fib; } VALUE resume_my_fiber(VALUE fib) { VALUE dump; printf("resume_my_fiber: Going to resume fiber="); fflush(stdout); dump = rb_inspect(fib); rb_io_puts(1, &dump, rb_stdout); if (RTEST(rb_fiber_alive_p(fib))) { VALUE result = rb_fiber_resume(fib, 0, 0); printf("resume_my_fiber: Fiber yielded value="); fflush(stdout); dump = rb_inspect(result); rb_io_puts(1, &dump, rb_stdout); return result; } else { printf("resume_my_fiber: Fiber is dead! cannot resume\n"); return Qfalse; } } RUBY_GLOBAL_SETUP int main(int argc, char** argv) { ruby_sysinit(&argc, &argv); { RUBY_INIT_STACK; ruby_init(); VALUE fib = rb_protect(create_my_fiber, Qnil, 0); printf("Main: Outside rb_protect()\n"); /* NOTE: I resume the fiber here (outside of rb_protect()) then a segfault occurs. Is this because the rb_protect() function provides a running thread? */ printf("Main: Going to resume fiber many times...\n"); VALUE count; do { count = rb_protect(resume_my_fiber, fib, 0); } while (RTEST(count)); printf("Main: Goodbye!\n"); } return ruby_cleanup(0); } ############################################################### # ./main.so ############################################################### create_my_fiber: Created my fiber=# Main: Outside rb_protect() Main: Going to resume fiber many times... resume_my_fiber: Going to resume fiber=# Fiber: Entering fiber body Fiber: going to yield=0 resume_my_fiber: Fiber yielded value=0 resume_my_fiber: Going to resume fiber=# Fiber: going to yield=1 resume_my_fiber: Fiber yielded value=1 resume_my_fiber: Going to resume fiber=# Fiber: going to yield=2 resume_my_fiber: Fiber yielded value=2 resume_my_fiber: Going to resume fiber=# Fiber: going to yield=3 resume_my_fiber: Fiber yielded value=3 resume_my_fiber: Going to resume fiber=# Fiber: going to yield=4 resume_my_fiber: Fiber yielded value=4 resume_my_fiber: Going to resume fiber=# Fiber: Exiting fiber body resume_my_fiber: Fiber yielded value=true resume_my_fiber: Going to resume fiber=# resume_my_fiber: Fiber is dead! cannot resume Main: Goodbye! ---------------------------------------- http://redmine.ruby-lang.org/issues/show/2127 ---------------------------------------- http://redmine.ruby-lang.org