Fiber#raise recursively raises on nested resuming_fiber. (#10482)

* Improve consistency of `Fiber.current.raise`.
This commit is contained in:
Samuel Williams 2024-04-17 23:08:47 +12:00 committed by GitHub
parent 945a0334c7
commit 6ade36c06b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 41 additions and 1 deletions

8
cont.c
View File

@ -3227,7 +3227,13 @@ rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
static VALUE static VALUE
fiber_raise(rb_fiber_t *fiber, VALUE exception) fiber_raise(rb_fiber_t *fiber, VALUE exception)
{ {
if (FIBER_SUSPENDED_P(fiber) && !fiber->yielding) { if (fiber == fiber_current()) {
rb_exc_raise(exception);
}
else if (fiber->resuming_fiber) {
return fiber_raise(fiber->resuming_fiber, exception);
}
else if (FIBER_SUSPENDED_P(fiber) && !fiber->yielding) {
return fiber_transfer_kw(fiber, -1, &exception, RB_NO_KEYWORDS); return fiber_transfer_kw(fiber, -1, &exception, RB_NO_KEYWORDS);
} }
else { else {

View File

@ -91,6 +91,40 @@ describe "Fiber#raise" do
fiber_two.resume.should == [:yield_one, :rescued] fiber_two.resume.should == [:yield_one, :rescued]
end end
ruby_version_is "3.4" do
it "raises on the resumed fiber" do
root_fiber = Fiber.current
f1 = Fiber.new { root_fiber.transfer }
f2 = Fiber.new { f1.resume }
f2.transfer
-> do
f2.raise(RuntimeError, "Expected error")
end.should raise_error(RuntimeError, "Expected error")
end
it "raises on itself" do
-> do
Fiber.current.raise(RuntimeError, "Expected error")
end.should raise_error(RuntimeError, "Expected error")
end
it "should raise on parent fiber" do
f2 = nil
f1 = Fiber.new do
# This is equivalent to Kernel#raise:
f2.raise(RuntimeError, "Expected error")
end
f2 = Fiber.new do
f1.resume
end
-> do
f2.resume
end.should raise_error(RuntimeError, "Expected error")
end
end
end end