Skip to content

Print stack overflow messages for Linux and OS X #16388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 24, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/libgreen/simple.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
10 changes: 0 additions & 10 deletions src/libnative/io/c_unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,16 +252,6 @@ mod signal {
pub status: libc::c_int,
}

#[cfg(any(target_os = "macos", target_os = "ios"))]
#[repr(C)]
pub struct sigaction {
pub sa_handler: extern fn(libc::c_int),
sa_tramp: *mut libc::c_void,
pub sa_mask: sigset_t,
pub sa_flags: libc::c_int,
}

#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
#[repr(C)]
pub struct sigaction {
pub sa_handler: extern fn(libc::c_int),
Expand Down
3 changes: 2 additions & 1 deletion src/libnative/lib.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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>;
Copy link
Member

Choose a reason for hiding this comment

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

This function seems a little redundant with stack_bounds because I would expect the guard page to always be at the very base of the stack, so it seems like this would always be equivalent to lo?

Copy link
Member

Choose a reason for hiding this comment

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

Hm, or maybe the stack_bounds function should be clarified in its documentation instead. It looks like (at least for libgreen), stack_bounds returns the usable stack of a task, (notably excluding the red zone).

So I think this is ok, but could this be returning the base address of the guard page instead of the top address of the guard page?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

stack_bounds is an approximation so it isn't usable to get the guard page. It also doesn't indicate if such a page exists at all. It's also separate functionality from the guard page logic.

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
Original file line number Diff line number Diff line change
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
Loading