[macruby-changes] [1931] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Thu Jun 25 23:01:50 PDT 2009
Revision: 1931
http://trac.macosforge.org/projects/ruby/changeset/1931
Author: lsansonetti at apple.com
Date: 2009-06-25 23:01:49 -0700 (Thu, 25 Jun 2009)
Log Message:
-----------
fixed the kill of a thread which is waiting for a cond var
Modified Paths:
--------------
MacRuby/branches/experimental/thread.c
MacRuby/branches/experimental/vm.cpp
MacRuby/branches/experimental/vm.h
Modified: MacRuby/branches/experimental/thread.c
===================================================================
--- MacRuby/branches/experimental/thread.c 2009-06-26 04:21:03 UTC (rev 1930)
+++ MacRuby/branches/experimental/thread.c 2009-06-26 06:01:49 UTC (rev 1931)
@@ -250,11 +250,9 @@
rb_thread_kill(VALUE thread, SEL sel)
{
rb_vm_thread_t *t = GetThreadPtr(thread);
- if (t->status == THREAD_KILLED) {
- // Already being killed!
- return thread;
+ if (t->status != THREAD_KILLED) {
+ rb_vm_thread_cancel(t);
}
- rb_vm_thread_cancel(t);
return thread;
}
Modified: MacRuby/branches/experimental/vm.cpp
===================================================================
--- MacRuby/branches/experimental/vm.cpp 2009-06-26 04:21:03 UTC (rev 1930)
+++ MacRuby/branches/experimental/vm.cpp 2009-06-26 06:01:49 UTC (rev 1931)
@@ -4285,6 +4285,9 @@
static inline void
rb_vm_thread_throw_kill(void)
{
+ // Killing a thread is implemented using a non-catchable (from Ruby)
+ // exception, which allows us to call the ensure blocks before dying,
+ // which is unfortunately covered in the Ruby specifications.
rb_vm_rethrow();
}
@@ -4378,24 +4381,41 @@
t->vm = vm;
t->value = Qundef;
t->status = THREAD_ALIVE;
+ t->in_cond_wait = false;
assert(pthread_mutex_init(&t->sleep_mutex, NULL) == 0);
assert(pthread_cond_init(&t->sleep_cond, NULL) == 0);
}
+static inline void
+pre_wait(rb_vm_thread_t *t)
+{
+ t->status = THREAD_SLEEP;
+ assert(pthread_mutex_lock(&t->sleep_mutex) == 0);
+ t->in_cond_wait = true;
+}
+
+static inline void
+post_wait(rb_vm_thread_t *t)
+{
+ t->in_cond_wait = false;
+ assert(pthread_mutex_unlock(&t->sleep_mutex) == 0);
+ if (t->status == THREAD_KILLED) {
+ rb_vm_thread_throw_kill();
+ }
+ t->status = THREAD_ALIVE;
+}
+
extern "C"
void
rb_thread_sleep_forever()
{
rb_vm_thread_t *t = GET_THREAD();
- t->status = THREAD_SLEEP;
- assert(pthread_mutex_lock(&t->sleep_mutex) == 0);
+ pre_wait(t);
const int code = pthread_cond_wait(&t->sleep_cond, &t->sleep_mutex);
assert(code == 0 || code == ETIMEDOUT);
- assert(pthread_mutex_unlock(&t->sleep_mutex) == 0);
-
- t->status = THREAD_ALIVE;
+ post_wait(t);
}
extern "C"
@@ -4414,15 +4434,11 @@
}
rb_vm_thread_t *t = GET_THREAD();
- t->status = THREAD_SLEEP;
-
- assert(pthread_mutex_lock(&t->sleep_mutex) == 0);
+ pre_wait(t);
const int code = pthread_cond_timedwait(&t->sleep_cond, &t->sleep_mutex,
&ts);
assert(code == 0 || code == ETIMEDOUT);
- assert(pthread_mutex_unlock(&t->sleep_mutex) == 0);
-
- t->status = THREAD_ALIVE;
+ post_wait(t);
}
extern "C"
@@ -4446,7 +4462,18 @@
rb_vm_thread_throw_kill();
}
else {
- assert(pthread_cancel(t->thread) == 0);
+ if (t->in_cond_wait) {
+ // We are trying to kill a thread which is currently waiting
+ // for a condition variable (#sleep). Instead of canceling the
+ // thread, we are simply signaling the variable, and the thread
+ // will autodestroy itself, to work around a stack unwinding bug
+ // in the Mac OS X pthread implementation that messes our C++
+ // exception handlers.
+ assert(pthread_cond_signal(&t->sleep_cond) == 0);
+ }
+ else {
+ assert(pthread_cancel(t->thread) == 0);
+ }
}
}
Modified: MacRuby/branches/experimental/vm.h
===================================================================
--- MacRuby/branches/experimental/vm.h 2009-06-26 04:21:03 UTC (rev 1930)
+++ MacRuby/branches/experimental/vm.h 2009-06-26 06:01:49 UTC (rev 1931)
@@ -90,6 +90,7 @@
pthread_mutex_t sleep_mutex;
pthread_cond_t sleep_cond;
rb_vm_thread_status_t status;
+ bool in_cond_wait;
} rb_vm_thread_t;
typedef struct rb_vm_outer {
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090625/dfe95193/attachment.html>
More information about the macruby-changes
mailing list