* 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
This commit is contained in:
kosaki 2012-12-05 19:37:49 +00:00
Родитель def63c3466
Коммит fe6b2e20e9
5 изменённых файлов: 78 добавлений и 15 удалений

Просмотреть файл

@ -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.

Просмотреть файл

@ -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);

48
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);
}
/*

Просмотреть файл

@ -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);
}