Skip to content

Commit d650b17

Browse files
committed
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.
1 parent 5c7af72 commit d650b17

4 files changed

Lines changed: 23 additions & 2 deletions

File tree

cont.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2039,7 +2039,7 @@ rb_fiber_set_scheduler(VALUE klass, VALUE scheduler)
20392039
return rb_fiber_scheduler_set(scheduler);
20402040
}
20412041

2042-
static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt, VALUE err);
2042+
NORETURN(static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt, VALUE err));
20432043

20442044
void
20452045
rb_fiber_start(rb_fiber_t *fiber)
@@ -2408,6 +2408,7 @@ rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt, VALUE error)
24082408
fiber_switch(next_fiber, -1, &error, RB_NO_KEYWORDS, NULL, false);
24092409
else
24102410
fiber_switch(next_fiber, 1, &value, RB_NO_KEYWORDS, NULL, false);
2411+
ruby_stop(0);
24112412
}
24122413

24132414
static VALUE

eval_intern.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ VALUE rb_make_exception(int argc, const VALUE *argv);
287287

288288
NORETURN(void rb_method_name_error(VALUE, VALUE));
289289

290-
void rb_fiber_start(rb_fiber_t*);
290+
NORETURN(void rb_fiber_start(rb_fiber_t*));
291291

292292
NORETURN(void rb_print_undef(VALUE, ID, rb_method_visibility_t));
293293
NORETURN(void rb_print_undef_str(VALUE, VALUE));

test/fiber/test_process.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,19 @@ def test_system
3333
end
3434
end.join
3535
end
36+
37+
def test_fork
38+
omit 'fork not supported' unless Process.respond_to?(:fork)
39+
Thread.new do
40+
scheduler = Scheduler.new
41+
Fiber.set_scheduler scheduler
42+
43+
Fiber.schedule do
44+
pid = Process.fork {}
45+
Process.wait(pid)
46+
47+
assert_predicate $?, :success?
48+
end
49+
end.join
50+
end
3651
end

test/ruby/test_fiber.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@ def test_fork_from_fiber
407407
pid, status = Process.waitpid2(pid)
408408
assert_not_predicate(status, :signaled?, bug5700)
409409
assert_predicate(status, :success?, bug5700)
410+
411+
pid = Fiber.new {fork}.resume
412+
pid, status = Process.waitpid2(pid)
413+
assert_not_predicate(status, :signaled?)
414+
assert_predicate(status, :success?)
410415
end
411416

412417
def test_exit_in_fiber

0 commit comments

Comments
 (0)