[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]