summary refs log tree commit diff
path: root/src/rt
diff options
context:
space:
mode:
authorBen Blum <bblum@andrew.cmu.edu>2012-07-12 02:42:56 -0400
committerBen Blum <bblum@andrew.cmu.edu>2012-07-12 18:08:36 -0400
commit200a2ded3245eb0a1ca7b265ce83adba16d75b97 (patch)
tree9874f527ab85ef32d2d9dc813685a1add5a03a51 /src/rt
parent343e9de8ef4ee9727f027c896ce99f09611b9603 (diff)
downloadrust-200a2ded3245eb0a1ca7b265ce83adba16d75b97.tar.gz
rust-200a2ded3245eb0a1ca7b265ce83adba16d75b97.zip
Fix linked failure with root taskgroup to kill the runtime too.
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/rust_builtin.cpp5
-rw-r--r--src/rt/rust_sched_loop.cpp4
-rw-r--r--src/rt/rust_task.cpp12
-rw-r--r--src/rt/rust_task.h4
-rw-r--r--src/rt/rustrt.def.in1
5 files changed, 23 insertions, 3 deletions
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 55f1f8bf17e..f648ed8d78c 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -863,6 +863,11 @@ rust_task_kill_other(rust_task *task) { /* Used for linked failure */
     task->kill();
 }
 
+extern "C" void
+rust_task_kill_all(rust_task *task) {
+    task->fail_sched_loop();
+}
+
 extern "C" rust_cond_lock*
 rust_create_cond_lock() {
     return new rust_cond_lock();
diff --git a/src/rt/rust_sched_loop.cpp b/src/rt/rust_sched_loop.cpp
index 4aed9a5e061..54ebccfe8c3 100644
--- a/src/rt/rust_sched_loop.cpp
+++ b/src/rt/rust_sched_loop.cpp
@@ -260,8 +260,8 @@ rust_task *
 rust_sched_loop::create_task(rust_task *spawner, const char *name) {
     rust_task *task =
         new (this->kernel, "rust_task")
-        rust_task (this, task_state_newborn,
-                   spawner, name, kernel->env->min_stack_size);
+        rust_task(this, task_state_newborn,
+                  spawner, name, kernel->env->min_stack_size);
     DLOG(this, task, "created task: " PTR ", spawner: %s, name: %s",
                         task, spawner ? spawner->name : "null", name);
 
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index 3d88c05b3ff..a6c9b791fda 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -129,6 +129,11 @@ cleanup_task(cleanup_args *args) {
         // assert(task->task_local_data != NULL);
         task->task_local_data_cleanup(task->task_local_data);
         task->task_local_data = NULL;
+    } else if (threw_exception) {
+        // Edge case: If main never spawns any tasks, but fails anyway, TLS
+        // won't be around to take down the kernel (task.rs:kill_taskgroup,
+        // rust_task_kill_all). Do it here instead.
+        task->fail_sched_loop();
     }
 
     // FIXME (#2676): For performance we should do the annihilator
@@ -282,6 +287,7 @@ rust_task::kill() {
     LOG(this, task, "preparing to unwind task: 0x%" PRIxPTR, this);
 }
 
+// TODO(bblum): Move this to rust_builtin.cpp (cleanup)
 extern "C" CDECL
 bool rust_task_is_unwinding(rust_task *rt) {
     return rt->unwinding;
@@ -315,10 +321,14 @@ rust_task::begin_failure(char const *expr, char const *file, size_t line) {
 #else
     die();
     // FIXME (#908): Need unwinding on windows. This will end up aborting
-    sched_loop->fail();
+    fail_sched_loop();
 #endif
 }
 
+void rust_task::fail_sched_loop() {
+    sched_loop->fail();
+}
+
 void
 rust_task::unsupervise()
 {
diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h
index 1d87a0ed56c..d562d151894 100644
--- a/src/rt/rust_task.h
+++ b/src/rt/rust_task.h
@@ -275,6 +275,10 @@ public:
     void fail();
     void fail(char const *expr, char const *file, size_t line);
 
+    // Propagate failure to the entire rust runtime.
+    // TODO(bblum): maybe this can be done at rust-level?
+    void fail_sched_loop();
+
     // Disconnect from our supervisor.
     void unsupervise();
 
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 300d6bc79e8..a8256bba300 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -178,6 +178,7 @@ rust_port_task
 rust_task_inhibit_kill
 rust_task_allow_kill
 rust_task_kill_other
+rust_task_kill_all
 rust_create_cond_lock
 rust_destroy_cond_lock
 rust_lock_cond_lock