about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstd/rt/stack.rs15
-rw-r--r--src/test/run-pass/out-of-stack.rs50
2 files changed, 60 insertions, 5 deletions
diff --git a/src/libstd/rt/stack.rs b/src/libstd/rt/stack.rs
index 655c209fec8..963ff000c4a 100644
--- a/src/libstd/rt/stack.rs
+++ b/src/libstd/rt/stack.rs
@@ -36,7 +36,7 @@ pub static RED_ZONE: uint = 20 * 1024;
                   //   irrelevant for documentation purposes.
 #[cfg(not(test))] // in testing, use the original libstd's version
 pub extern "C" fn rust_stack_exhausted() {
-    use option::None;
+    use option::{Option, None, Some};
     use rt::local::Local;
     use rt::task::Task;
     use str::Str;
@@ -85,16 +85,21 @@ pub extern "C" fn rust_stack_exhausted() {
         //  #9854 - unwinding on windows through __morestack has never worked
         //  #2361 - possible implementation of not using landing pads
 
-        let mut task = Local::borrow(None::<Task>);
-        let n = task.get().name.as_ref()
-                    .map(|n| n.as_slice()).unwrap_or("<unnamed>");
+        let task: Option<~Task> = Local::try_take();
+        let name = match task {
+            Some(ref task) => {
+                task.name.as_ref().map(|n| n.as_slice())
+            }
+            None => None
+        };
+        let name = name.unwrap_or("<unknown>");
 
         // See the message below for why this is not emitted to the
         // task's logger. This has the additional conundrum of the
         // logger may not be initialized just yet, meaning that an FFI
         // call would happen to initialized it (calling out to libuv),
         // and the FFI call needs 2MB of stack when we just ran out.
-        println!("task '{}' has overflowed its stack", n);
+        rterrln!("task '{}' has overflowed its stack", name);
 
         intrinsics::abort();
     }
diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs
new file mode 100644
index 00000000000..9344c29d5ca
--- /dev/null
+++ b/src/test/run-pass/out-of-stack.rs
@@ -0,0 +1,50 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-fast
+
+#[feature(asm)];
+
+use std::io::Process;
+use std::os;
+use std::str;
+
+// lifted from the test module
+pub fn black_box<T>(dummy: T) { unsafe { asm!("" : : "r"(&dummy)) } }
+
+fn silent_recurse() {
+    let buf = [0, ..1000];
+    black_box(buf);
+    silent_recurse();
+}
+
+fn loud_recurse() {
+    println!("hello!");
+    loud_recurse();
+}
+
+fn main() {
+    let args = os::args();
+    if args.len() > 1 && args[1].as_slice() == "silent" {
+        silent_recurse();
+    } else if args.len() > 1 && args[1].as_slice() == "loud" {
+        loud_recurse();
+    } else {
+        let silent = Process::output(args[0], [~"silent"]).unwrap();
+        assert!(!silent.status.success());
+        let error = str::from_utf8_lossy(silent.error);
+        assert!(error.as_slice().contains("has overflowed its stack"));
+
+        let loud = Process::output(args[0], [~"loud"]).unwrap();
+        assert!(!loud.status.success());
+        let error = str::from_utf8_lossy(silent.error);
+        assert!(error.as_slice().contains("has overflowed its stack"));
+    }
+}