about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-01-12 22:17:21 -0800
committerBrian Anderson <banderson@mozilla.com>2012-01-12 22:24:27 -0800
commit0616cba62be78082f10f6673d45ba4d94da423dc (patch)
tree0cd1d0cf9434a751b293b8292da1c153065da491 /src
parentdcac427795285a46232722a38e8a5f88ae4dc891 (diff)
downloadrust-0616cba62be78082f10f6673d45ba4d94da423dc.tar.gz
rust-0616cba62be78082f10f6673d45ba4d94da423dc.zip
libcore: Add sys::set_exit_status
Sets the process exit code
Diffstat (limited to 'src')
-rw-r--r--src/libcore/sys.rs13
-rw-r--r--src/rt/rust_builtin.cpp6
-rw-r--r--src/rt/rust_internal.h2
-rw-r--r--src/rt/rust_kernel.cpp12
-rw-r--r--src/rt/rust_kernel.h4
-rw-r--r--src/rt/rust_scheduler.cpp2
-rw-r--r--src/rt/rustrt.def.in1
-rw-r--r--src/test/run-fail/rt-set-exit-status-fail.rs10
-rw-r--r--src/test/run-fail/rt-set-exit-status-fail2.rs15
-rw-r--r--src/test/run-fail/rt-set-exit-status.rs8
10 files changed, 68 insertions, 5 deletions
diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs
index 21032e72122..96e5947daf0 100644
--- a/src/libcore/sys.rs
+++ b/src/libcore/sys.rs
@@ -20,6 +20,7 @@ native mod rustrt {
     fn do_gc();
     fn unsupervise();
     fn shape_log_str<T>(t: *sys::type_desc, data: T) -> str;
+    fn rust_set_exit_status(code: int);
 }
 
 #[abi = "rust-intrinsic"]
@@ -92,6 +93,18 @@ fn log_str<T>(t: T) -> str {
     rustrt::shape_log_str(get_type_desc::<T>(), t)
 }
 
+#[doc(
+    brief = "Sets the process exit code",
+    desc = "Sets the exit code returned by the process if all supervised \
+            tasks terminate successfully (without failing). If the current \
+            root task fails and is supervised by the scheduler then any \
+            user-specified exit status is ignored and the process exits \
+            with the default failure status."
+)]
+fn set_exit_status(code: int) {
+    rustrt::rust_set_exit_status(code);
+}
+
 // Local Variables:
 // mode: rust;
 // fill-column: 78;
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 264e6fdb325..7bd1c76c187 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -561,6 +561,12 @@ port_recv(uintptr_t *dptr, rust_port *port,
     return;
 }
 
+extern "C" CDECL void
+rust_set_exit_status(intptr_t code) {
+    rust_task *task = rust_scheduler::get_task();
+    task->kernel->set_exit_status((int)code);
+}
+
 //
 // Local Variables:
 // mode: C++
diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h
index b83d74f6bfe..aa62c22fc8f 100644
--- a/src/rt/rust_internal.h
+++ b/src/rt/rust_internal.h
@@ -92,7 +92,7 @@ static size_t const TIME_SLICE_IN_MS = 10;
 static size_t const BUF_BYTES = 2048;
 
 // The error status to use when the process fails
-#define PROC_FAIL_CODE 101;
+#define PROC_FAIL_CODE 101
 
 // Every reference counted object should use this macro and initialize
 // ref_count.
diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp
index 3078f6b78c4..a7e4ee2e450 100644
--- a/src/rt/rust_kernel.cpp
+++ b/src/rt/rust_kernel.cpp
@@ -11,8 +11,8 @@ rust_kernel::rust_kernel(rust_srv *srv, size_t num_threads) :
     _log(srv, NULL),
     srv(srv),
     max_id(0),
-    num_threads(num_threads),
     rval(0),
+    num_threads(num_threads),
     live_tasks(0),
     env(srv->env)
 {
@@ -140,6 +140,7 @@ rust_kernel::fail() {
     // FIXME: On windows we're getting "Application has requested the
     // Runtime to terminate it in an unusual way" when trying to shutdown
     // cleanly.
+    set_exit_status(PROC_FAIL_CODE);
 #if defined(__WIN32__)
     exit(rval);
 #endif
@@ -210,6 +211,15 @@ rust_kernel::win32_require(LPCTSTR fn, BOOL ok) {
 }
 #endif
 
+void
+rust_kernel::set_exit_status(int code) {
+    scoped_lock with(_kernel_lock);
+    // If we've already failed then that's the code we're going to use
+    if (rval != PROC_FAIL_CODE) {
+        rval = code;
+    }
+}
+
 //
 // Local Variables:
 // mode: C++
diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h
index 8d59dabdcb9..f60987acae5 100644
--- a/src/rt/rust_kernel.h
+++ b/src/rt/rust_kernel.h
@@ -34,9 +34,10 @@ private:
     rust_task_id max_id;
     hash_map<rust_task_id, rust_task *> task_table;
 
+    int rval;
+
 public:
     const size_t num_threads;
-    int rval;
 
     volatile int live_tasks;
     struct rust_env *env;
@@ -68,6 +69,7 @@ public:
     rust_task_id create_task(rust_task *spawner, const char *name);
     rust_task *get_task_by_id(rust_task_id id);
     void release_task_id(rust_task_id tid);
+    void set_exit_status(int code);
 };
 
 #endif /* RUST_KERNEL_H */
diff --git a/src/rt/rust_scheduler.cpp b/src/rt/rust_scheduler.cpp
index 1df70306975..0b4e35910ac 100644
--- a/src/rt/rust_scheduler.cpp
+++ b/src/rt/rust_scheduler.cpp
@@ -82,8 +82,6 @@ void
 rust_scheduler::fail() {
     log(NULL, log_err, "domain %s @0x%" PRIxPTR " root task failed",
         name, this);
-    I(this, kernel->rval == 0);
-    kernel->rval = PROC_FAIL_CODE;
     kernel->fail();
 }
 
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 7e57625fac1..e058ad739df 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -41,6 +41,7 @@ rust_port_size
 rust_process_wait
 rust_ptr_eq
 rust_run_program
+rust_set_exit_status
 rust_start
 rust_getcwd
 rust_task_is_unwinding
diff --git a/src/test/run-fail/rt-set-exit-status-fail.rs b/src/test/run-fail/rt-set-exit-status-fail.rs
new file mode 100644
index 00000000000..fd32ff04600
--- /dev/null
+++ b/src/test/run-fail/rt-set-exit-status-fail.rs
@@ -0,0 +1,10 @@
+// error-pattern:whatever
+
+fn main() {
+    log(error, "whatever");
+    // Setting the exit status only works when the scheduler terminates
+    // normally. In this case we're going to fail, so instead of of
+    // returning 50 the process will return the typical rt failure code.
+    sys::set_exit_status(50);
+    fail;
+}
\ No newline at end of file
diff --git a/src/test/run-fail/rt-set-exit-status-fail2.rs b/src/test/run-fail/rt-set-exit-status-fail2.rs
new file mode 100644
index 00000000000..5d973d2a9e3
--- /dev/null
+++ b/src/test/run-fail/rt-set-exit-status-fail2.rs
@@ -0,0 +1,15 @@
+// error-pattern:whatever
+
+fn main() {
+    log(error, "whatever");
+    task::spawn {||
+        resource r(_i: ()) {
+            // Setting the exit status after the runtime has already
+            // failed has no effect and the process exits with the
+            // runtime's exit code
+            sys::set_exit_status(50);
+        }
+        let i = r(());
+    };
+    fail;
+}
\ No newline at end of file
diff --git a/src/test/run-fail/rt-set-exit-status.rs b/src/test/run-fail/rt-set-exit-status.rs
new file mode 100644
index 00000000000..e9e8f239434
--- /dev/null
+++ b/src/test/run-fail/rt-set-exit-status.rs
@@ -0,0 +1,8 @@
+// error-pattern:whatever
+
+fn main() {
+    log(error, "whatever");
+    // 101 is the code the runtime uses on task failure and the value
+    // compiletest expects run-fail tests to return.
+    sys::set_exit_status(101);
+}
\ No newline at end of file