diff --git a/src/libstd/rt/stack.rs b/src/libstd/rt/stack.rs index 655c209fec874..963ff000c4ad1 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::); - let n = task.get().name.as_ref() - .map(|n| n.as_slice()).unwrap_or(""); + 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(""); // 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 0000000000000..9344c29d5ca2b --- /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 or the MIT license +// , 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(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")); + } +}