1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

fix Thread's interrupt and Ractor#take issue

Thread's interrupt set Ractor's wakeup_status as interrupted, but
the status remains next Ractor communication API. This patch makes
to ignore the previous interrupt state.
[Bug #17366]

Also this patch solves the Thread#kill and Ractor#take issues.
This commit is contained in:
Koichi Sasada 2020-12-07 16:01:35 +09:00
parent cc36e499f9
commit c2fa024e02
3 changed files with 27 additions and 2 deletions

View file

@ -229,6 +229,26 @@ assert_equal 'ok', %q{
end
}
# Can mix with Thread#interrupt and Ractor#take [Bug #17366]
assert_equal 'err', %q{
Ractor.new{
t = Thread.current
begin
Thread.new{ t.raise "err" }.join
rescue => e
e.message
end
}.take
}
# Killed Ractor's thread yields nil
assert_equal 'nil', %q{
Ractor.new{
t = Thread.current
Thread.new{ t.kill }.join
}.take.inspect #=> nil
}
# Ractor.yield raises Ractor::ClosedError when outgoing port is closed.
assert_equal 'ok', %q{
r = Ractor.new Ractor.current do |main|

View file

@ -627,8 +627,8 @@ ractor_receive(rb_execution_context_t *ec, rb_ractor_t *r)
{
if (ractor_queue_empty_p(r, &r->incoming_queue)) {
VM_ASSERT(r->wait.status == wait_none);
VM_ASSERT(r->wait.wakeup_status == wakeup_none);
r->wait.status = wait_receiving;
r->wait.wakeup_status = wakeup_none;
ractor_sleep(ec, r);
@ -887,8 +887,8 @@ ractor_select(rb_execution_context_t *ec, const VALUE *rs, int alen, VALUE yield
RACTOR_LOCK(cr);
{
VM_ASSERT(cr->wait.status == wait_none);
VM_ASSERT(cr->wait.wakeup_status == wakeup_none);
cr->wait.status = wait_status;
cr->wait.wakeup_status == wakeup_none;
}
RACTOR_UNLOCK(cr);
@ -1331,6 +1331,8 @@ ractor_yield_atexit(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool e
VM_ASSERT(cr->wait.status == wait_none);
cr->wait.status = wait_yielding;
cr->wait.wakeup_status = wakeup_none;
VM_ASSERT(cr->yield_atexit == false);
cr->yield_atexit = true;
}

View file

@ -825,6 +825,9 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start)
errinfo = th->ec->errinfo;
if (state == TAG_FATAL) {
if (th->invoke_type == thread_invoke_type_ractor_proc) {
rb_ractor_atexit(th->ec, Qnil);
}
/* fatal error within this thread, need to stop whole script */
}
else if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {