ruby-changes:70921
From: Nobuyoshi <ko1@a...>
Date: Wed, 19 Jan 2022 21:54:21 +0900 (JST)
Subject: [ruby-changes:70921] d650b17686 (master): `rb_fiber_terminate` must not return [Bug #18497]
https://git.ruby-lang.org/ruby.git/commit/?id=d650b17686 From d650b17686d49c2ce8e6a87039861154e93d4621 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada <nobu@r...> Date: Wed, 19 Jan 2022 16:01:45 +0900 Subject: `rb_fiber_terminate` must not return [Bug #18497] In a forked process from a fiber, the fiber becomes the only fiber, `fiber_switch` does nothing as there is no other fibers, `rb_fiber_terminate` does not terminate the fiber. In that case, reaches the end of `fiber_entry` finaly, which is declared as "COROUTINE" and should never return. --- cont.c | 3 ++- eval_intern.h | 2 +- test/fiber/test_process.rb | 15 +++++++++++++++ test/ruby/test_fiber.rb | 5 +++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/cont.c b/cont.c index 96654733f8e..f9ebb4483ec 100644 --- a/cont.c +++ b/cont.c @@ -2039,7 +2039,7 @@ rb_fiber_set_scheduler(VALUE klass, VALUE scheduler) https://github.com/ruby/ruby/blob/trunk/cont.c#L2039 return rb_fiber_scheduler_set(scheduler); } -static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt, VALUE err); +NORETURN(static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt, VALUE err)); void rb_fiber_start(rb_fiber_t *fiber) @@ -2408,6 +2408,7 @@ rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt, VALUE error) https://github.com/ruby/ruby/blob/trunk/cont.c#L2408 fiber_switch(next_fiber, -1, &error, RB_NO_KEYWORDS, NULL, false); else fiber_switch(next_fiber, 1, &value, RB_NO_KEYWORDS, NULL, false); + ruby_stop(0); } static VALUE diff --git a/eval_intern.h b/eval_intern.h index 347453f4e8f..0efbcb0441d 100644 --- a/eval_intern.h +++ b/eval_intern.h @@ -287,7 +287,7 @@ VALUE rb_make_exception(int argc, const VALUE *argv); https://github.com/ruby/ruby/blob/trunk/eval_intern.h#L287 NORETURN(void rb_method_name_error(VALUE, VALUE)); -void rb_fiber_start(rb_fiber_t*); +NORETURN(void rb_fiber_start(rb_fiber_t*)); NORETURN(void rb_print_undef(VALUE, ID, rb_method_visibility_t)); NORETURN(void rb_print_undef_str(VALUE, VALUE)); diff --git a/test/fiber/test_process.rb b/test/fiber/test_process.rb index c6583cac9bc..a5990be2044 100644 --- a/test/fiber/test_process.rb +++ b/test/fiber/test_process.rb @@ -33,4 +33,19 @@ class TestFiberProcess < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/fiber/test_process.rb#L33 end end.join end + + def test_fork + omit 'fork not supported' unless Process.respond_to?(:fork) + Thread.new do + scheduler = Scheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + pid = Process.fork {} + Process.wait(pid) + + assert_predicate $?, :success? + end + end.join + end end diff --git a/test/ruby/test_fiber.rb b/test/ruby/test_fiber.rb index 1447a036c3b..5825aaf6cc5 100644 --- a/test/ruby/test_fiber.rb +++ b/test/ruby/test_fiber.rb @@ -407,6 +407,11 @@ class TestFiber < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_fiber.rb#L407 pid, status = Process.waitpid2(pid) assert_not_predicate(status, :signaled?, bug5700) assert_predicate(status, :success?, bug5700) + + pid = Fiber.new {fork}.resume + pid, status = Process.waitpid2(pid) + assert_not_predicate(status, :signaled?) + assert_predicate(status, :success?) end def test_exit_in_fiber -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/