aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bootstraptest/test_ractor.rb21
-rw-r--r--ractor.c8
2 files changed, 29 insertions, 0 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index c693a9c496..025d886152 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -225,6 +225,27 @@ assert_equal 'ok', %q{
end
}
+# Ractor.yield raises Ractor::ClosedError when outgoing port is closed.
+assert_equal 'ok', %q{
+ r = Ractor.new Ractor.current do |main|
+ Ractor.recv
+ main << true
+ Ractor.yield 1
+ end
+
+ r.close_outgoing
+ r << true
+ Ractor.recv
+
+ begin
+ r.take
+ rescue Ractor::ClosedError
+ 'ok'
+ else
+ 'ng'
+ end
+}
+
# Raise Ractor::ClosedError when try to send into a ractor with closed incoming port
assert_equal 'ok', %q{
r = Ractor.new { Ractor.recv }
diff --git a/ractor.c b/ractor.c
index fbc9192af8..382d3d5199 100644
--- a/ractor.c
+++ b/ractor.c
@@ -832,6 +832,10 @@ ractor_try_yield(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_b
ASSERT_ractor_unlocking(cr);
VM_ASSERT(basket->type != basket_type_none);
+ if (cr->outgoing_port_closed) {
+ rb_raise(rb_eRactorClosedError, "The outgoing-port is already closed");
+ }
+
rb_ractor_t *r;
retry_shift:
@@ -1017,6 +1021,10 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, int alen, VALUE yield
cr->wait.wakeup_status = wakeup_by_retry;
goto skip_sleep;
}
+ else if (cr->outgoing_port_closed) {
+ cr->wait.wakeup_status = wakeup_by_close;
+ goto skip_sleep;
+ }
break;
}
}