Diff
Modified: MacRuby/branches/experimental/thread.c (1945 => 1946)
--- MacRuby/branches/experimental/thread.c 2009-06-27 06:38:55 UTC (rev 1945)
+++ MacRuby/branches/experimental/thread.c 2009-06-27 06:39:27 UTC (rev 1946)
@@ -131,31 +131,35 @@
rb_scan_args(argc, argv, "01", &timeout);
rb_vm_thread_t *t = GetThreadPtr(self);
- if (t->status == THREAD_DEAD) {
- return self;
- }
-
- if (timeout == Qnil) {
- // No timeout given: block until the thread finishes.
- pthread_assert(pthread_join(t->thread, NULL));
- }
- else {
- // Timeout given: sleep then check if the thread is dead.
- // TODO do multiple sleeps instead of only one.
- struct timeval tv = rb_time_interval(timeout);
- struct timespec ts;
- ts.tv_sec = tv.tv_sec;
- ts.tv_nsec = tv.tv_usec * 1000;
- while (ts.tv_nsec >= 1000000000) {
- ts.tv_sec += 1;
- ts.tv_nsec -= 1000000000;
+ if (t->status != THREAD_DEAD) {
+ if (timeout == Qnil) {
+ // No timeout given: block until the thread finishes.
+ pthread_assert(pthread_join(t->thread, NULL));
}
- nanosleep(&ts, NULL);
- if (t->status != THREAD_DEAD) {
- return Qnil;
+ else {
+ // Timeout given: sleep then check if the thread is dead.
+ // TODO do multiple sleeps instead of only one.
+ struct timeval tv = rb_time_interval(timeout);
+ struct timespec ts;
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+ while (ts.tv_nsec >= 1000000000) {
+ ts.tv_sec += 1;
+ ts.tv_nsec -= 1000000000;
+ }
+ nanosleep(&ts, NULL);
+ if (t->status != THREAD_DEAD) {
+ return Qnil;
+ }
}
}
+ // If the thread was terminated because of an exception, we need to
+ // propagate it.
+ if (t->exception != Qnil) {
+ rb_exc_raise(t->exception);
+ }
+
return self;
}
@@ -570,8 +574,7 @@
{
rb_vm_thread_t *t = GetThreadPtr(thread);
if (t->status == THREAD_DEAD) {
- // TODO should return Qnil in case the thread got an exception.
- return Qfalse;
+ return t->exception == Qnil ? Qfalse : Qnil;
}
return rb_str_new2(rb_thread_status_cstr(thread));
}
Modified: MacRuby/branches/experimental/vm.cpp (1945 => 1946)
--- MacRuby/branches/experimental/vm.cpp 2009-06-27 06:38:55 UTC (rev 1945)
+++ MacRuby/branches/experimental/vm.cpp 2009-06-27 06:39:27 UTC (rev 1946)
@@ -4420,9 +4420,11 @@
GC_WB(&t->value, val);
}
catch (...) {
- // TODO handle thread-level exceptions.
- //printf("exception raised inside thread %p\n", pthread_self());
- t->value = Qfalse;
+ VALUE exc = rb_vm_current_exception();
+ if (exc != Qnil) {
+ GC_WB(&t->exception, exc);
+ }
+ t->value = Qnil;
}
pthread_cleanup_pop(0);
@@ -4495,6 +4497,7 @@
t->vm = vm;
t->value = Qundef;
t->locals = Qnil;
+ t->exception = Qnil;
t->status = THREAD_ALIVE;
t->in_cond_wait = false;
Modified: MacRuby/branches/experimental/vm.h (1945 => 1946)
--- MacRuby/branches/experimental/vm.h 2009-06-27 06:38:55 UTC (rev 1945)
+++ MacRuby/branches/experimental/vm.h 2009-06-27 06:39:27 UTC (rev 1946)
@@ -103,6 +103,7 @@
rb_vm_thread_status_t status;
bool in_cond_wait;
VALUE locals; // a Hash object or Qnil
+ VALUE exception; // killed-by-exception or Qnil
} rb_vm_thread_t;
typedef struct rb_vm_outer {