about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <andersrb@gmail.com>2010-12-29 00:33:52 -0500
committerGraydon Hoare <graydon@mozilla.com>2011-01-03 10:59:00 -0800
commit73fd87baf50da704b04837fe059ed4fcad0f4660 (patch)
treec3761f1e64cb4254cf75f1dbda58fd59c600cba7
parent2ec4325fe9fe5808d7abab544e3a9ce896093f51 (diff)
downloadrust-73fd87baf50da704b04837fe059ed4fcad0f4660.tar.gz
rust-73fd87baf50da704b04837fe059ed4fcad0f4660.zip
Don't attempt to wake tasks that aren't blocked.
It's possible for a supervised task to kill and wake its supervising
task then immediately try to wake it again if the supervising task
has joined the supervised. This is the easiest way to prevent that.
-rw-r--r--src/rt/rust_task.cpp2
-rw-r--r--src/test/run-pass/task-killjoin.rs36
2 files changed, 37 insertions, 1 deletions
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index 680043cc35b..1522fcccb1c 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -420,7 +420,7 @@ rust_task::notify_tasks_waiting_to_join() {
             delete waiting_task;
         } else {
             rust_task *task = waiting_task->referent();
-            if (task->dead() == false) {
+            if (task->blocked() == true) {
                 task->wakeup(this);
             }
         }
diff --git a/src/test/run-pass/task-killjoin.rs b/src/test/run-pass/task-killjoin.rs
new file mode 100644
index 00000000000..558c1687106
--- /dev/null
+++ b/src/test/run-pass/task-killjoin.rs
@@ -0,0 +1,36 @@
+// Create a task that is supervised by another task,
+// join the supervised task from the supervising task,
+// then fail the supervised task. The supervised task
+// will kill the supervising task, waking it up. The
+// supervising task no longer needs to be wakened when
+// the supervised task exits.
+
+fn supervised() {
+    // Yield to make sure the supervisor joins before we
+    // fail. This is currently not needed because the supervisor
+    // runs first, but I can imagine that changing.
+    yield;
+    fail;
+}
+
+fn supervisor() {
+    let task t = spawn "supervised" supervised();
+    join t;
+}
+
+fn main() {
+    // Start the test in another domain so that
+    // the process doesn't return a failure status as a result
+    // of the main task being killed.
+    let task dom2 = spawn thread "supervisor" supervisor();
+    join dom2;
+}
+
+// Local Variables:
+// mode: rust;
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End: