Created
December 4, 2012 13:19
-
-
Save tarui/4203798 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
r=:ok | |
e=Class.new(Exception) | |
th_s = Thread.current | |
begin | |
th = Thread.start{ | |
Thread.async_interrupt_timing(Object => :on_blocking){ | |
begin | |
Thread.current.raise RuntimeError | |
sleep | |
ensure | |
th_s.raise e | |
end | |
} | |
} | |
sleep 1 | |
r=:ng | |
th.raise RuntimeError | |
th.join | |
rescue e | |
end | |
p r |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: vm_core.h | |
=================================================================== | |
--- vm_core.h (revision 38191) | |
+++ vm_core.h (working copy) | |
@@ -889,11 +889,16 @@ int rb_threadptr_async_errinfo_active_p(rb_thread_ | |
void rb_thread_lock_unlock(rb_thread_lock_t *); | |
void rb_thread_lock_destroy(rb_thread_lock_t *); | |
-#define RUBY_VM_CHECK_INTS_BLOCKING(th) do { \ | |
- if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(th))) { \ | |
- rb_threadptr_execute_interrupts(th, 1); \ | |
- } \ | |
-} while (0) | |
+#define RUBY_VM_CHECK_INTS_BLOCKING(th) do { \ | |
+ if (UNLIKELY(!rb_threadptr_async_errinfo_empty_p(th))) { \ | |
+ th->async_errinfo_queue_checked = 0; \ | |
+ RUBY_VM_SET_INTERRUPT(th); \ | |
+ rb_threadptr_execute_interrupts(th, 1); \ | |
+ } \ | |
+ else if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(th))) { \ | |
+ rb_threadptr_execute_interrupts(th, 1); \ | |
+ } \ | |
+ } while (0) | |
#define RUBY_VM_CHECK_INTS(th) do { \ | |
if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(th))) { \ | |
Index: thread.c | |
=================================================================== | |
--- thread.c (revision 38191) | |
+++ thread.c (working copy) | |
@@ -69,6 +69,7 @@ static void sleep_forever(rb_thread_t *th, int nod | |
static double timeofday(void); | |
static int rb_threadptr_dead(rb_thread_t *th); | |
static void rb_check_deadlock(rb_vm_t *vm); | |
+static int rb_threadptr_async_errinfo_empty_p(rb_thread_t *th); | |
#define eKillSignal INT2FIX(0) | |
#define eTerminateSignal INT2FIX(1) | |
@@ -888,7 +889,8 @@ sleep_forever(rb_thread_t *th, int deadlockable,in | |
enum rb_thread_status status = deadlockable ? THREAD_STOPPED_FOREVER : THREAD_STOPPED; | |
th->status = status; | |
- do { | |
+ RUBY_VM_CHECK_INTS_BLOCKING(th); | |
+ while (th->status == status) { | |
if (deadlockable) { | |
th->vm->sleeper++; | |
rb_check_deadlock(th->vm); | |
@@ -898,7 +900,9 @@ sleep_forever(rb_thread_t *th, int deadlockable,in | |
th->vm->sleeper--; | |
} | |
RUBY_VM_CHECK_INTS_BLOCKING(th); | |
- } while (spurious_check && th->status == status); | |
+ if(!spurious_check) | |
+ break; | |
+ } | |
th->status = prev_status; | |
} | |
@@ -932,7 +936,8 @@ sleep_timeval(rb_thread_t *th, struct timeval tv,i | |
} | |
th->status = THREAD_STOPPED; | |
- do { | |
+ RUBY_VM_CHECK_INTS_BLOCKING(th); | |
+ while (th->status == THREAD_STOPPED) { | |
native_sleep(th, &tv); | |
RUBY_VM_CHECK_INTS_BLOCKING(th); | |
getclockofday(&tvn); | |
@@ -946,7 +951,9 @@ sleep_timeval(rb_thread_t *th, struct timeval tv,i | |
--tv.tv_sec; | |
tv.tv_usec += 1000000; | |
} | |
- } while (spurious_check && th->status == THREAD_STOPPED); | |
+ if(!spurious_check) | |
+ break; | |
+ } | |
th->status = prev_status; | |
} | |
Index: test/ruby/test_thread.rb | |
=================================================================== | |
--- test/ruby/test_thread.rb (revision 38191) | |
+++ test/ruby/test_thread.rb (working copy) | |
@@ -563,6 +563,30 @@ class TestThread < Test::Unit::TestCase | |
Thread.async_interrupt_timing([]) {} # array | |
} | |
end | |
+ | |
+ def test_async_interrupt_blocking | |
+ r=:ok | |
+ e=Class.new(Exception) | |
+ th_s = Thread.current | |
+ begin | |
+ th = Thread.start{ | |
+ Thread.async_interrupt_timing(Object => :on_blocking){ | |
+ begin | |
+ Thread.current.raise RuntimeError | |
+ sleep | |
+ ensure | |
+ th_s.raise e | |
+ end | |
+ } | |
+ } | |
+ sleep 1 | |
+ r=:ng | |
+ th.raise RuntimeError | |
+ th.join | |
+ rescue e | |
+ end | |
+ assert_equal(:ok,r) | |
+ end | |
def test_async_interrupted? | |
q = Queue.new |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment