ruby-changes:63077
From: Koichi <ko1@a...>
Date: Fri, 25 Sep 2020 00:26:01 +0900 (JST)
Subject: [ruby-changes:63077] 7ad3aff48d (master): Ractor#close_outgoping cancel Ractor.yield
https://git.ruby-lang.org/ruby.git/commit/?id=7ad3aff48d From 7ad3aff48dc8309542704b2212b3c3d1df8155d0 Mon Sep 17 00:00:00 2001 From: Koichi Sasada <ko1@a...> Date: Thu, 24 Sep 2020 17:41:10 +0900 Subject: Ractor#close_outgoping cancel Ractor.yield Ractor#close_outgoing should cancel waiting Ractor.yield. However, yield a value by the Ractor's block should not cancel (to recognize terminating Ractor, introduce rb_ractor_t::yield_atexit flag). diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 86325f0..b6f00de 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -257,6 +257,7 @@ assert_equal 'ok', %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_ractor.rb#L257 Ractor.recv end + sleep 0.01 # wait for Ractor.yield in r r.close_outgoing begin r.take diff --git a/ractor.c b/ractor.c index 3c87802..a7e588a 100644 --- a/ractor.c +++ b/ractor.c @@ -1138,6 +1138,7 @@ ractor_close_incoming(rb_execution_context_t *ec, rb_ractor_t *r) https://github.com/ruby/ruby/blob/trunk/ractor.c#L1138 r->incoming_port_closed = true; if (ractor_wakeup(r, wait_recving, wakeup_by_close)) { VM_ASSERT(r->incoming_queue.cnt == 0); + RUBY_DEBUG_LOG("cancel receiving", 0); } } else { @@ -1149,15 +1150,15 @@ ractor_close_incoming(rb_execution_context_t *ec, rb_ractor_t *r) https://github.com/ruby/ruby/blob/trunk/ractor.c#L1150 } static VALUE -ractor_close_outgoing(rb_execution_context_t *ec, rb_ractor_t *cr) +ractor_close_outgoing(rb_execution_context_t *ec, rb_ractor_t *r) { VALUE prev; - RACTOR_LOCK(cr); + RACTOR_LOCK(r); { - if (!cr->outgoing_port_closed) { + if (!r->outgoing_port_closed) { prev = Qfalse; - cr->outgoing_port_closed = true; + r->outgoing_port_closed = true; } else { prev = Qtrue; @@ -1165,13 +1166,21 @@ ractor_close_outgoing(rb_execution_context_t *ec, rb_ractor_t *cr) https://github.com/ruby/ruby/blob/trunk/ractor.c#L1166 // wakeup all taking ractors rb_ractor_t *taking_ractor; - while ((taking_ractor = ractor_waiting_list_shift(cr, &cr->taking_ractors)) != NULL) { + bp(); + while ((taking_ractor = ractor_waiting_list_shift(r, &r->taking_ractors)) != NULL) { + rp(taking_ractor->self); RACTOR_LOCK(taking_ractor); ractor_wakeup(taking_ractor, wait_taking, wakeup_by_close); RACTOR_UNLOCK(taking_ractor); } + + // raising yielding Ractor + if (!r->yield_atexit && + ractor_wakeup(r, wait_yielding, wakeup_by_close)) { + RUBY_DEBUG_LOG("cancel yielding", 0); + } } - RACTOR_UNLOCK(cr); + RACTOR_UNLOCK(r); return prev; } @@ -1362,7 +1371,7 @@ ractor_create(rb_execution_context_t *ec, VALUE self, VALUE loc, VALUE name, VAL https://github.com/ruby/ruby/blob/trunk/ractor.c#L1371 } static void -ractor_atexit_yield(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool exc) +ractor_yield_atexit(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool exc) { ASSERT_ractor_unlocking(cr); @@ -1382,6 +1391,8 @@ ractor_atexit_yield(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool e https://github.com/ruby/ruby/blob/trunk/ractor.c#L1391 VM_ASSERT(cr->wait.status == wait_none); cr->wait.status = wait_yielding; + VM_ASSERT(cr->yield_atexit == false); + cr->yield_atexit = true; } else { retry = true; // another ractor is waiting for the yield. @@ -1413,14 +1424,14 @@ void https://github.com/ruby/ruby/blob/trunk/ractor.c#L1424 rb_ractor_atexit(rb_execution_context_t *ec, VALUE result) { rb_ractor_t *cr = rb_ec_ractor_ptr(ec); - ractor_atexit_yield(ec, cr, result, false); + ractor_yield_atexit(ec, cr, result, false); } void rb_ractor_atexit_exception(rb_execution_context_t *ec) { rb_ractor_t *cr = rb_ec_ractor_ptr(ec); - ractor_atexit_yield(ec, cr, ec->errinfo, true); + ractor_yield_atexit(ec, cr, ec->errinfo, true); } void diff --git a/ractor.h b/ractor.h index 640fc62..10d7ba8 100644 --- a/ractor.h +++ b/ractor.h @@ -47,6 +47,7 @@ struct rb_ractor_struct { https://github.com/ruby/ruby/blob/trunk/ractor.h#L47 bool incoming_port_closed; bool outgoing_port_closed; + bool yield_atexit; struct rb_ractor_waiting_list taking_ractors; -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/