Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "stacker"
version = "0.1.3"
version = "0.2.0"
authors = ["Alex Crichton <[email protected]>"]
build = "build.rs"
license = "MIT/Apache-2.0"
Expand Down
6 changes: 1 addition & 5 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ fn main() {
cfg.define("APPLE", None);
} else if target.contains("windows") {
cfg.define("WINDOWS", None);
} else {
panic!("\n\nusing currently unsupported target triple with \
stacker: {}\n\n", target);
}

if target.starts_with("x86_64") {
Expand All @@ -26,8 +23,7 @@ fn main() {
cfg.file(if msvc {"src/arch/i686.asm"} else {"src/arch/i686.S"});
cfg.define("X86", None);
} else {
panic!("\n\nusing currently unsupported target triple with \
stacker: {}\n\n", target);
cfg.file("fallback.rs");
}

cfg.include("src/arch").compile("libstacker.a");
Expand Down
13 changes: 13 additions & 0 deletions src/arch/fallback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[no_mangle]
extern fn __stacker_stack_pointer() -> usize {
0
}

#[no_mangle]
unsafe extern fn __stacker_switch_stacks(
_new_stack: usize,
fnptr: unsafe fn(&mut &mut FnMut()),
dataptr: &mut &mut FnMut(),
) {
fnptr(dataptr)
}
19 changes: 13 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
//! // guaranteed to have at least 32K of stack
//! });
//! ```
//!
//! # Platform support
//!
//! Only Windows, MacOS and Linux are supported. Other platforms don't do anything
//! and will overflow your stack.

#![allow(improper_ctypes)]

Expand Down Expand Up @@ -60,9 +65,7 @@ fn set_stack_limit(l: usize) {
///
/// The closure `f` is guaranteed to run on a stack with at least `red_zone`
/// bytes, and it will be run on the current stack if there's space available.
pub fn maybe_grow<R, F: FnOnce() -> R>(red_zone: usize,
stack_size: usize,
f: F) -> R {
pub fn maybe_grow<R, F: FnOnce() -> R>(red_zone: usize, stack_size: usize, f: F) -> R {
if remaining_stack() >= red_zone {
f()
} else {
Expand All @@ -86,10 +89,14 @@ fn grow_the_stack<R, F: FnOnce() -> R>(stack_size: usize, f: F) -> R {
let mut ret = None;
unsafe {
_grow_the_stack(stack_size, &mut || {
ret = Some(f.take().unwrap()());
let f: F = f.take().unwrap();
ret = Some(std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)));
});
}
ret.unwrap()
match ret.unwrap() {
Ok(ret) => ret,
Err(payload) => std::panic::resume_unwind(payload),
}
}

unsafe fn _grow_the_stack(stack_size: usize, mut f: &mut FnMut()) {
Expand Down Expand Up @@ -177,7 +184,7 @@ cfg_if! {
}
} else {
unsafe fn guess_os_stack_limit() -> usize {
panic!("cannot guess the stack limit on this platform");
0
}
}
}
27 changes: 27 additions & 0 deletions tests/panic_handling.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
extern crate stacker;

const RED_ZONE: usize = 100*1024; // 100k
const STACK_PER_RECURSION: usize = 1 * 1024 * 1024; // 1MB

pub fn ensure_sufficient_stack<R, F: FnOnce() -> R + std::panic::UnwindSafe>(
f: F
) -> R {
stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f)
}

#[inline(never)]
fn recurse(n: usize) {
let x = [42u8; 50000];
if n == 0 {
panic!("an inconvenient time");
} else {
ensure_sufficient_stack(|| recurse(n - 1));
}
drop(x);
}

#[test]
#[should_panic]
fn foo() {
recurse(10000);
}