Skip to content

Commit

Permalink
Print stack overflow messages for Windows, Linux and OS X
Browse files Browse the repository at this point in the history
Fixes #17562
  • Loading branch information
Zoxc committed Oct 24, 2014
1 parent 50e86c2 commit 70cef94
Show file tree
Hide file tree
Showing 14 changed files with 774 additions and 33 deletions.
1 change: 1 addition & 0 deletions src/libgreen/simple.rs
Expand Up @@ -81,6 +81,7 @@ impl Runtime for SimpleTask {
}
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
fn stack_bounds(&self) -> (uint, uint) { fail!() }
fn stack_guard(&self) -> Option<uint> { fail!() }
fn can_block(&self) -> bool { true }
fn wrap(self: Box<SimpleTask>) -> Box<Any+'static> { fail!() }
}
Expand Down
5 changes: 5 additions & 0 deletions src/libgreen/stack.rs
Expand Up @@ -82,6 +82,11 @@ impl Stack {
}
}

/// Point to the last writable byte of the stack
pub fn guard(&self) -> *const uint {
(self.start() as uint + page_size()) as *const uint
}

/// Point to the low end of the allocated stack
pub fn start(&self) -> *const uint {
self.buf.as_ref().map(|m| m.data() as *const uint)
Expand Down
7 changes: 7 additions & 0 deletions src/libgreen/task.rs
Expand Up @@ -486,6 +486,13 @@ impl Runtime for GreenTask {
c.current_stack_segment.end() as uint)
}

fn stack_guard(&self) -> Option<uint> {
let c = self.coroutine.as_ref()
.expect("GreenTask.stack_guard called without a coroutine");

Some(c.current_stack_segment.guard() as uint)
}

fn can_block(&self) -> bool { false }

fn wrap(self: Box<GreenTask>) -> Box<Any+'static> {
Expand Down
3 changes: 2 additions & 1 deletion src/libnative/lib.rs
Expand Up @@ -132,7 +132,8 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
rt::init(argc, argv);
let mut exit_code = None;
let mut main = Some(main);
let mut task = task::new((my_stack_bottom, my_stack_top));
let mut task = task::new((my_stack_bottom, my_stack_top),
rt::thread::main_guard_page());
task.name = Some(str::Slice("<main>"));
drop(task.run(|| {
unsafe {
Expand Down
15 changes: 14 additions & 1 deletion src/libnative/task.rs
Expand Up @@ -29,10 +29,11 @@ use io;
use std::task::{TaskBuilder, Spawner};

/// Creates a new Task which is ready to execute as a 1:1 task.
pub fn new(stack_bounds: (uint, uint)) -> Box<Task> {
pub fn new(stack_bounds: (uint, uint), stack_guard: uint) -> Box<Task> {
let mut task = box Task::new();
let mut ops = ops();
ops.stack_bounds = stack_bounds;
ops.stack_guard = stack_guard;
task.put_runtime(ops);
return task;
}
Expand All @@ -44,6 +45,7 @@ fn ops() -> Box<Ops> {
io: io::IoFactory::new(),
// these *should* get overwritten
stack_bounds: (0, 0),
stack_guard: 0
}
}

Expand Down Expand Up @@ -82,6 +84,7 @@ impl Spawner for NativeSpawner {
my_stack);
}
let mut ops = ops;
ops.stack_guard = rt::thread::current_guard_page();
ops.stack_bounds = (my_stack - stack + 1024, my_stack);

let mut f = Some(f);
Expand Down Expand Up @@ -115,6 +118,8 @@ struct Ops {
// native tasks necessarily know their precise bounds, hence this is
// optional.
stack_bounds: (uint, uint),

stack_guard: uint
}

impl rt::Runtime for Ops {
Expand All @@ -138,6 +143,14 @@ impl rt::Runtime for Ops {

fn stack_bounds(&self) -> (uint, uint) { self.stack_bounds }

fn stack_guard(&self) -> Option<uint> {
if self.stack_guard != 0 {
Some(self.stack_guard)
} else {
None
}
}

fn can_block(&self) -> bool { true }

// This function gets a little interesting. There are a few safety and
Expand Down
5 changes: 5 additions & 0 deletions src/librustrt/lib.rs
Expand Up @@ -51,6 +51,7 @@ mod local_ptr;
mod thread_local_storage;
mod util;
mod libunwind;
mod stack_overflow;

pub mod args;
pub mod bookkeeping;
Expand Down Expand Up @@ -92,6 +93,8 @@ pub trait Runtime {
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>>;
/// The (low, high) edges of the current stack.
fn stack_bounds(&self) -> (uint, uint); // (lo, hi)
/// The last writable byte of the stack next to the guard page
fn stack_guard(&self) -> Option<uint>;
fn can_block(&self) -> bool;

// FIXME: This is a serious code smell and this should not exist at all.
Expand All @@ -113,6 +116,7 @@ pub fn init(argc: int, argv: *const *const u8) {
args::init(argc, argv);
local_ptr::init();
at_exit_imp::init();
thread::init();
}

// FIXME(#14344) this shouldn't be necessary
Expand Down Expand Up @@ -151,6 +155,7 @@ pub unsafe fn cleanup() {
bookkeeping::wait_for_other_tasks();
at_exit_imp::run();
args::cleanup();
thread::cleanup();
local_ptr::cleanup();
}

Expand Down
20 changes: 1 addition & 19 deletions src/librustrt/stack.rs
Expand Up @@ -55,10 +55,6 @@ pub const RED_ZONE: uint = 20 * 1024;
#[cfg(not(test))] // in testing, use the original libstd's version
#[lang = "stack_exhausted"]
extern fn stack_exhausted() {
use core::prelude::*;
use alloc::boxed::Box;
use local::Local;
use task::Task;
use core::intrinsics;

unsafe {
Expand Down Expand Up @@ -104,21 +100,7 @@ extern fn stack_exhausted() {
// #9854 - unwinding on windows through __morestack has never worked
// #2361 - possible implementation of not using landing pads

let task: Option<Box<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.
rterrln!("task '{}' has overflowed its stack", name);
::stack_overflow::report();

intrinsics::abort();
}
Expand Down

5 comments on commit 70cef94

@bors
Copy link
Contributor

@bors bors commented on 70cef94 Oct 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from alexcrichton
at Zoxc@70cef94

@bors
Copy link
Contributor

@bors bors commented on 70cef94 Oct 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging Zoxc/rust/stmesg = 70cef94 into auto

@bors
Copy link
Contributor

@bors bors commented on 70cef94 Oct 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zoxc/rust/stmesg = 70cef94 merged ok, testing candidate = a10917a

@bors
Copy link
Contributor

@bors bors commented on 70cef94 Oct 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on 70cef94 Oct 24, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = a10917a

Please sign in to comment.