diff options
author | kosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-12-05 19:37:49 +0000 |
---|---|---|
committer | kosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-12-05 19:37:49 +0000 |
commit | fe6b2e20e9f17ed2c2900aa72994e075ffdc7124 (patch) | |
tree | 13f2b2f26be57d3cd6f25b0e6483484d9dc22d1e | |
parent | def63c3466939161f2459f6489815b444bbde8a3 (diff) | |
download | ruby-fe6b2e20e9f17ed2c2900aa72994e075ffdc7124.tar.gz |
* thread.c (rb_uninterruptible): helper function for providing
temporary async_interrupt_timing(Object => :defer)
* io.c (rb_f_p): use rb_uninterruptible.
* io.c (rb_f_p_internal): helper function for rb_f_p().
* io.c (struct rb_f_p_arg): new struct for rb_f_p_internal.
* test/ruby/test_thread.rb (test_async_interrupt_and_p): test for
the above.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38225 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | internal.h | 1 | ||||
-rw-r--r-- | io.c | 48 | ||||
-rw-r--r-- | test/ruby/test_thread.rb | 20 | ||||
-rw-r--r-- | thread.c | 12 |
5 files changed, 78 insertions, 15 deletions
@@ -1,3 +1,15 @@ +Thu Dec 6 04:34:19 2012 KOSAKI Motohiro <kosaki.motohiro@gmail.com> + + * thread.c (rb_uninterruptible): helper function for providing + temporary async_interrupt_timing(Object => :defer) + + * io.c (rb_f_p): use rb_uninterruptible. + * io.c (rb_f_p_internal): helper function for rb_f_p(). + * io.c (struct rb_f_p_arg): new struct for rb_f_p_internal. + + * test/ruby/test_thread.rb (test_async_interrupt_and_p): test for + the above. + Thu Dec 6 04:27:10 2012 KOSAKI Motohiro <kosaki.motohiro@gmail.com> * io.c (io_binwrite): check interrupt before io issue. diff --git a/internal.h b/internal.h index 86181f913a..8165545813 100644 --- a/internal.h +++ b/internal.h @@ -279,6 +279,7 @@ VALUE rb_thread_shield_wait(VALUE self); VALUE rb_thread_shield_release(VALUE self); VALUE rb_thread_shield_destroy(VALUE self); void rb_mutex_allow_trap(VALUE self, int val); +VALUE rb_uninterruptible(VALUE (*b_proc)(ANYARGS), VALUE data); /* thread_pthread.c, thread_win32.c */ void Init_native_thread(void); @@ -6759,6 +6759,35 @@ rb_p(VALUE obj) /* for debug print within C code */ } } +struct rb_f_p_arg { + int argc; + VALUE *argv; +}; + +static VALUE +rb_f_p_internal(VALUE arg) +{ + struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg; + int argc = arg1->argc; + VALUE *argv = arg1->argv; + int i; + VALUE ret = Qnil; + + for (i=0; i<argc; i++) { + rb_p(argv[i]); + } + if (argc == 1) { + ret = argv[0]; + } + else if (argc > 1) { + ret = rb_ary_new4(argc, argv); + } + if (RB_TYPE_P(rb_stdout, T_FILE)) { + rb_io_flush(rb_stdout); + } + return ret; +} + /* * call-seq: * p(obj) -> obj @@ -6780,22 +6809,11 @@ rb_p(VALUE obj) /* for debug print within C code */ static VALUE rb_f_p(int argc, VALUE *argv, VALUE self) { - int i; - VALUE ret = Qnil; + struct rb_f_p_arg arg; + arg.argc = argc; + arg.argv = argv; - for (i=0; i<argc; i++) { - rb_p(argv[i]); - } - if (argc == 1) { - ret = argv[0]; - } - else if (argc > 1) { - ret = rb_ary_new4(argc, argv); - } - if (RB_TYPE_P(rb_stdout, T_FILE)) { - rb_io_flush(rb_stdout); - } - return ret; + return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg); } /* diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb index b82cae4cb7..ae007e5a6d 100644 --- a/test/ruby/test_thread.rb +++ b/test/ruby/test_thread.rb @@ -637,6 +637,26 @@ class TestThread < Test::Unit::TestCase INPUT end + def test_async_interrupt_and_p + assert_in_out_err([], <<-INPUT, %w(:ok :ok), []) + th_waiting = true + + t = Thread.new { + Thread.async_interrupt_timing(RuntimeError => :on_blocking) { + nil while th_waiting + # p shouldn't provide interruptible point + p :ok + p :ok + } + } + + sleep 0.1 + t.raise RuntimeError + th_waiting = false + t.join rescue nil + INPUT + end + def test_async_interrupted? q = Queue.new Thread.async_interrupt_timing(RuntimeError => :defer){ @@ -5048,3 +5048,15 @@ rb_reset_coverages(void) GET_VM()->coverages = Qfalse; rb_remove_event_hook(update_coverage); } + +VALUE +rb_uninterruptible(VALUE (*b_proc)(ANYARGS), VALUE data) +{ + VALUE interrupt_mask = rb_hash_new(); + rb_thread_t *cur_th = GET_THREAD(); + + rb_hash_aset(interrupt_mask, rb_cObject, ID2SYM(rb_intern("defer"))); + rb_ary_push(cur_th->async_errinfo_mask_stack, interrupt_mask); + + return rb_ensure(b_proc, data, rb_ary_pop, cur_th->async_errinfo_mask_stack); +} |