diff options
author | Koichi Sasada <[email protected]> | 2020-04-09 04:45:49 +0900 |
---|---|---|
committer | Koichi Sasada <[email protected]> | 2020-04-09 12:51:51 +0900 |
commit | fd0222caedf1be56faa004656bbf145522abbe68 (patch) | |
tree | e20c3cdb107770bd1e65f79b33a4b67c9d415167 | |
parent | d2bb2e066b5a914283dd3ea473fc1762183af013 (diff) |
should check pending interrupts correctly.
rb_uninterruptible() disables any interrupts using handle_interrupt
feature (This function is used by `p`).
After this function, pending interrupts should be checked correctly,
however there is no chance to setup interrupt flag of working
threads, it means that nobody checks pending interrupts.
For example, it ignores terminate signal delivered at the end
of main thread and program can't stop.
This patch set interrupt flag if there are pending interrupts.
-rw-r--r-- | bootstraptest/test_thread.rb | 14 | ||||
-rw-r--r-- | thread.c | 18 |
2 files changed, 31 insertions, 1 deletions
diff --git a/bootstraptest/test_thread.rb b/bootstraptest/test_thread.rb index e7ddadf4a7..38a55ff229 100644 --- a/bootstraptest/test_thread.rb +++ b/bootstraptest/test_thread.rb @@ -484,3 +484,17 @@ assert_equal 'foo', %q{ GC.start f.call.source } +assert_normal_exit %q{ + class C + def inspect + sleep 0.5 + 'C!!' + end + end + Thread.new{ + loop{ + p C.new + } + } + sleep 0.1 +}, timeout: 5 @@ -5564,6 +5564,19 @@ rb_default_coverage(int n) return coverage; } +static VALUE +uninterruptible_exit(VALUE v) +{ + rb_thread_t *cur_th = GET_THREAD(); + rb_ary_pop(cur_th->pending_interrupt_mask_stack); + + cur_th->pending_interrupt_queue_checked = 0; + if (!rb_threadptr_pending_interrupt_empty_p(cur_th)) { + RUBY_VM_SET_INTERRUPT(cur_th->ec); + } + return Qnil; +} + VALUE rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data) { @@ -5574,5 +5587,8 @@ rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data) OBJ_FREEZE_RAW(interrupt_mask); rb_ary_push(cur_th->pending_interrupt_mask_stack, interrupt_mask); - return rb_ensure(b_proc, data, rb_ary_pop, cur_th->pending_interrupt_mask_stack); + VALUE ret = rb_ensure(b_proc, data, uninterruptible_exit, Qnil); + + RUBY_VM_CHECK_INTS(cur_th->ec); + return ret; } |