From 0cd607bcbdc70d3d7ccefd5faf830cc8e5d68c86 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 10 Aug 2011 12:57:53 -0700 Subject: [PATCH] rt: Shutdown gracefully on failure When the kernel fails, kill all tasks and wait for the schedulers to stop instead of just exiting. I'm sure there are tons of lurking issues here but this is enough to fail without leaking (at least in the absence of cleanups). --- src/rt/rust_kernel.cpp | 8 ++++++++ src/rt/rust_kernel.h | 2 ++ src/rt/rust_scheduler.cpp | 16 +++++++++++++++- src/rt/rust_scheduler.h | 2 ++ src/rt/rust_upcall.cpp | 2 +- 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp index 4197f5dea890..89c068856835 100644 --- a/src/rt/rust_kernel.cpp +++ b/src/rt/rust_kernel.cpp @@ -134,6 +134,14 @@ int rust_kernel::start_task_threads() return rval; } +void +rust_kernel::fail() { + for(size_t i = 0; i < num_threads; ++i) { + rust_scheduler *thread = threads[i]; + thread->kill_all_tasks(); + } +} + rust_task_id rust_kernel::create_task(rust_task *spawner, const char *name) { rust_scheduler *thread = threads[rand(&rctx) % num_threads]; diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h index ff5b100445e3..774f7f4d0a49 100644 --- a/src/rt/rust_kernel.h +++ b/src/rt/rust_kernel.h @@ -52,6 +52,8 @@ public: void *realloc(void *mem, size_t size); void free(void *mem); + void fail(); + int start_task_threads(); #ifdef __WIN32__ diff --git a/src/rt/rust_scheduler.cpp b/src/rt/rust_scheduler.cpp index 30504319b30b..33e607a85e19 100644 --- a/src/rt/rust_scheduler.cpp +++ b/src/rt/rust_scheduler.cpp @@ -71,7 +71,21 @@ rust_scheduler::fail() { name, this); I(this, kernel->rval == 0); kernel->rval = 1; - exit(1); + kernel->fail(); +} + +void +rust_scheduler::kill_all_tasks() { + I(this, !lock.lock_held_by_current_thread()); + scoped_lock with(lock); + + for (size_t i = 0; i < running_tasks.length(); i++) { + running_tasks[i]->kill(); + } + + for (size_t i = 0; i < blocked_tasks.length(); i++) { + blocked_tasks[i]->kill(); + } } size_t diff --git a/src/rt/rust_scheduler.h b/src/rt/rust_scheduler.h index 286691695121..b4a70e51f686 100644 --- a/src/rt/rust_scheduler.h +++ b/src/rt/rust_scheduler.h @@ -81,6 +81,8 @@ struct rust_scheduler : public kernel_owned, void log_state(); + void kill_all_tasks(); + rust_task *create_task(rust_task *spawner, const char *name); virtual void run(); diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 5feffe600c3f..cd8d9b96e2e0 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -195,8 +195,8 @@ upcall_fail(rust_task *task, size_t line) { LOG_UPCALL_ENTRY(task); LOG_ERR(task, upcall, "upcall fail '%s', %s:%" PRIdPTR, expr, file, line); - task->fail(); task->die(); + task->fail(); task->notify_tasks_waiting_to_join(); task->yield(4); }