зеркало из https://github.com/github/ruby.git
* 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:
Родитель
def63c3466
Коммит
fe6b2e20e9
12
ChangeLog
12
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.
|
||||
|
|
|
@ -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
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){
|
||||
|
|
12
thread.c
12
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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче