summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-12-05 19:37:49 +0000
committerkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-12-05 19:37:49 +0000
commitfe6b2e20e9f17ed2c2900aa72994e075ffdc7124 (patch)
tree13f2b2f26be57d3cd6f25b0e6483484d9dc22d1e
parentdef63c3466939161f2459f6489815b444bbde8a3 (diff)
* 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--ChangeLog12
-rw-r--r--internal.h1
-rw-r--r--io.c48
-rw-r--r--test/ruby/test_thread.rb20
-rw-r--r--thread.c12
5 files changed, 78 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index c5b43d44d6..51cb62048c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);
diff --git a/io.c b/io.c
index c8a5905630..4cbce26c9c 100644
--- a/io.c
+++ b/io.c
@@ -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){
diff --git a/thread.c b/thread.c
index 8fd4580ab2..4ea4c58f5d 100644
--- a/thread.c
+++ b/thread.c
@@ -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);
+}