summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2024-05-29 15:47:26 -0700
committerTakashi Kokubun <[email protected]>2024-05-29 15:47:26 -0700
commit5c06e930748ef6bdb4ac4751ba16b7b604da3db0 (patch)
treefbc72c6bf0e5ad28feb51262e0f565569a83091f
parentb44c02ad5a1c5c8c1c62b83eec96cf3a8a2107bc (diff)
merge revision(s) 6ade36c06b7cef948099b8f5f483763498705d12: [Backport #20414]
`Fiber#raise` recursively raises on nested resuming_fiber. (#10482) * Improve consistency of `Fiber.current.raise`.
-rw-r--r--cont.c8
-rw-r--r--spec/ruby/core/fiber/raise_spec.rb34
-rw-r--r--version.h2
3 files changed, 42 insertions, 2 deletions
diff --git a/cont.c b/cont.c
index cafcb66091..55040d3d38 100644
--- a/cont.c
+++ b/cont.c
@@ -3223,7 +3223,13 @@ rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
static VALUE
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);
}
else {
diff --git a/spec/ruby/core/fiber/raise_spec.rb b/spec/ruby/core/fiber/raise_spec.rb
index eb4b39c8be..b3e021e636 100644
--- a/spec/ruby/core/fiber/raise_spec.rb
+++ b/spec/ruby/core/fiber/raise_spec.rb
@@ -91,6 +91,40 @@ describe "Fiber#raise" do
fiber_two.resume.should == [:yield_one, :rescued]
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
diff --git a/version.h b/version.h
index 6cc6423ca6..e6138749cd 100644
--- a/version.h
+++ b/version.h
@@ -11,7 +11,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 1
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 70
+#define RUBY_PATCHLEVEL 71
#include "ruby/version.h"
#include "ruby/internal/abi.h"