From d247dedade684d8ba04da4af891791e5ab5878ef Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Fri, 25 Sep 2020 11:39:15 +0900 Subject: [PATCH] Ractor.yield should raise if out-port is closed Ractor.yield should raise Ractor::ClosedError if current Ractor's outgoing-port is closed. --- bootstraptest/test_ractor.rb | 21 +++++++++++++++++++++ ractor.c | 8 ++++++++ 2 files changed, 29 insertions(+) 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; } }