summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2020-04-09 04:45:49 +0900
committerKoichi Sasada <ko1@atdot.net>2020-04-09 12:51:51 +0900
commitfd0222caedf1be56faa004656bbf145522abbe68 (patch)
treee20c3cdb107770bd1e65f79b33a4b67c9d415167
parentd2bb2e066b5a914283dd3ea473fc1762183af013 (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.rb14
-rw-r--r--thread.c18
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
diff --git a/thread.c b/thread.c
index e59b6dbac8..ccfa870f99 100644
--- a/thread.c
+++ b/thread.c
@@ -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;
}