[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