mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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:
parent
def63c3466
commit
fe6b2e20e9
5 changed files with 78 additions and 15 deletions
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>
|
Thu Dec 6 04:27:10 2012 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
|
||||||
|
|
||||||
* io.c (io_binwrite): check interrupt before io issue.
|
* 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_release(VALUE self);
|
||||||
VALUE rb_thread_shield_destroy(VALUE self);
|
VALUE rb_thread_shield_destroy(VALUE self);
|
||||||
void rb_mutex_allow_trap(VALUE self, int val);
|
void rb_mutex_allow_trap(VALUE self, int val);
|
||||||
|
VALUE rb_uninterruptible(VALUE (*b_proc)(ANYARGS), VALUE data);
|
||||||
|
|
||||||
/* thread_pthread.c, thread_win32.c */
|
/* thread_pthread.c, thread_win32.c */
|
||||||
void Init_native_thread(void);
|
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:
|
* call-seq:
|
||||||
* p(obj) -> obj
|
* p(obj) -> obj
|
||||||
|
@ -6780,22 +6809,11 @@ rb_p(VALUE obj) /* for debug print within C code */
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_f_p(int argc, VALUE *argv, VALUE self)
|
rb_f_p(int argc, VALUE *argv, VALUE self)
|
||||||
{
|
{
|
||||||
int i;
|
struct rb_f_p_arg arg;
|
||||||
VALUE ret = Qnil;
|
arg.argc = argc;
|
||||||
|
arg.argv = argv;
|
||||||
|
|
||||||
for (i=0; i<argc; i++) {
|
return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -637,6 +637,26 @@ class TestThread < Test::Unit::TestCase
|
||||||
INPUT
|
INPUT
|
||||||
end
|
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?
|
def test_async_interrupted?
|
||||||
q = Queue.new
|
q = Queue.new
|
||||||
Thread.async_interrupt_timing(RuntimeError => :defer){
|
Thread.async_interrupt_timing(RuntimeError => :defer){
|
||||||
|
|
12
thread.c
12
thread.c
|
@ -5048,3 +5048,15 @@ rb_reset_coverages(void)
|
||||||
GET_VM()->coverages = Qfalse;
|
GET_VM()->coverages = Qfalse;
|
||||||
rb_remove_event_hook(update_coverage);
|
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);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue