about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rt/rust_builtin.cpp6
-rw-r--r--src/rt/rust_globals.h2
-rw-r--r--src/rt/rust_kernel.cpp2
-rw-r--r--src/rt/rust_task.cpp8
4 files changed, 15 insertions, 3 deletions
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 66337d6c8ea..001fcd6198b 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -864,8 +864,12 @@ rust_task_kill_other(rust_task *task) { /* Used for linked failure */
 }
 
 extern "C" void
-rust_task_kill_all(rust_task *task) {
+rust_task_kill_all(rust_task *task) { /* Used for linked failure */
     task->fail_sched_loop();
+    // This must not happen twice.
+    static bool main_taskgroup_failed = false;
+    assert(!main_taskgroup_failed);
+    main_taskgroup_failed = true;
 }
 
 extern "C" rust_cond_lock*
diff --git a/src/rt/rust_globals.h b/src/rt/rust_globals.h
index 54b80ee7908..7056f7f4a27 100644
--- a/src/rt/rust_globals.h
+++ b/src/rt/rust_globals.h
@@ -90,6 +90,8 @@ extern "C" int check_claims;
 // This accounts for logging buffers.
 static size_t const BUF_BYTES = 2048;
 
+#define INIT_TASK_ID 1
+
 // The error status to use when the process fails
 #define PROC_FAIL_CODE 101
 
diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp
index 82fec98e86a..cbe0bb21199 100644
--- a/src/rt/rust_kernel.cpp
+++ b/src/rt/rust_kernel.cpp
@@ -15,7 +15,7 @@
 rust_kernel::rust_kernel(rust_env *env) :
     _region(env, true),
     _log(NULL),
-    max_task_id(1),
+    max_task_id(INIT_TASK_ID-1), // sync_add_and_fetch increments first
     max_port_id(1),
     rval(0),
     max_sched_id(1),
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index a6c9b791fda..db4db51d3cf 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -129,11 +129,17 @@ 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) {
+    } else if (threw_exception && task->id == INIT_TASK_ID) {
         // 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.
+        // (Note that children tasks can not init their TLS if they were
+        // killed too early, so we need to check main's task id too.)
         task->fail_sched_loop();
+        // This must not happen twice.
+        static bool main_task_failed_without_spawning = false;
+        assert(!main_task_failed_without_spawning);
+        main_task_failed_without_spawning = true;
     }
 
     // FIXME (#2676): For performance we should do the annihilator