Skip to content
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

improve error handling #116

Merged
merged 16 commits into from
Feb 21, 2025
80 changes: 50 additions & 30 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,7 @@
-1, // Some implementations assert fd = -1 if MAP_ANON is specified
0
);
if new_stack == libc::MAP_FAILED {
let error = std::io::Error::last_os_error();
panic!("allocating stack failed with: {}", error)
}
assert_ne!(new_stack, libc::MAP_FAILED, "mmap failed to allocate stack: {}", std::io::Error::last_os_error());
let guard = StackRestoreGuard {
new_stack,
stack_bytes,
Expand All @@ -191,11 +188,7 @@
} else {
-1
};
if result == -1 {
let error = std::io::Error::last_os_error();
drop(guard);
panic!("setting stack permissions failed with: {}", error)
}
assert_ne!(result, -1, "mprotect/mmap failed: {}", std::io::Error::last_os_error());
guard
}
}
Expand All @@ -222,7 +215,7 @@
fn _grow(stack_size: usize, callback: &mut dyn FnMut()) {
// Calculate a number of pages we want to allocate for the new stack.
// For maximum portability we want to produce a stack that is aligned to a page and has
// a size thats a multiple of page size. Furthermore we want to allocate two extras pages
// a size that's a multiple of page size. Furthermore we want to allocate two extras pages
// for the stack guard. To achieve that we do our calculations in number of pages and
// convert to bytes last.
let page_size = page_size();
Expand Down Expand Up @@ -294,7 +287,7 @@
// Make sure the libstacker.a (implemented in C) is linked.
// See https://github.com/rust-lang/rust/issues/65610
#[link(name="stacker")]
extern {

Check warning on line 290 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Test Cargo.toml on windows-latest with nightly and

extern declarations without an explicit ABI are deprecated

Check warning on line 290 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Test Cargo.toml on windows-latest with nightly and --release

extern declarations without an explicit ABI are deprecated

Check warning on line 290 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Test Cargo.toml on windows-latest with nightly and -Zminimal-versions

extern declarations without an explicit ABI are deprecated

Check warning on line 290 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Test Cargo.toml on x86_64-pc-windows-gnu with nightly

extern declarations without an explicit ABI are deprecated

Check warning on line 290 in src/lib.rs

View workflow job for this annotation

GitHub Actions / Test Cargo.toml on i686-pc-windows-gnu with nightly

extern declarations without an explicit ABI are deprecated
fn __stacker_get_current_fiber() -> *mut c_void;
}

Expand Down Expand Up @@ -411,31 +404,58 @@
);
Some(mi.assume_init().AllocationBase as usize + get_thread_stack_guarantee() + 0x1000)
}
} else if #[cfg(any(target_os = "linux", target_os="solaris", target_os = "netbsd"))] {
unsafe fn guess_os_stack_limit() -> Option<usize> {
let mut attr = std::mem::MaybeUninit::<libc::pthread_attr_t>::uninit();
assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0);
assert_eq!(libc::pthread_getattr_np(libc::pthread_self(),
attr.as_mut_ptr()), 0);
let mut stackaddr = std::ptr::null_mut();
let mut stacksize = 0;
assert_eq!(libc::pthread_attr_getstack(
attr.as_ptr(), &mut stackaddr, &mut stacksize
), 0);
assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0);
Some(stackaddr as usize)
} else if #[cfg(any(
target_os = "linux",
target_os = "solaris",
target_os = "netbsd",
target_os = "freebsd",
target_os = "dragonfly",
target_os = "illumos"
))] {
unsafe fn destroy_pthread_attr(attr: *mut libc::pthread_attr_t) {
let ret = libc::pthread_attr_destroy(attr);
if ret != 0 {
panic!("pthread_attr_destroy failed with error code {}: {}", ret, std::io::Error::last_os_error());
}
}

unsafe fn handle_pthread_err(attr: *mut libc::pthread_attr_t, ret: libc::c_int) -> Option<()> {
if ret != 0 {
destroy_pthread_attr(attr);
return None;
}
Some(())
}
} else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "illumos"))] {

unsafe fn guess_os_stack_limit() -> Option<usize> {
// Initialize pthread attributes structure
let mut attr = std::mem::MaybeUninit::<libc::pthread_attr_t>::uninit();
assert_eq!(libc::pthread_attr_init(attr.as_mut_ptr()), 0);
assert_eq!(libc::pthread_attr_get_np(libc::pthread_self(), attr.as_mut_ptr()), 0);
if libc::pthread_attr_init(attr.as_mut_ptr()) != 0 {
return None;
}

let pthread_ctx = attr.as_mut_ptr();

// Linux and BSD use different functions to get attributes of created thread
cfg_if! {
if #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "illumos"))] {
let get_attr = libc::pthread_attr_get_np;
} else {
let get_attr = libc::pthread_getattr_np;
}
};

// Get current thread's attributes
let res = get_attr(libc::pthread_self(), pthread_ctx);
handle_pthread_err(pthread_ctx, res)?;

// Get the stack address and size from attributes
let mut stackaddr = std::ptr::null_mut();
let mut stacksize = 0;
assert_eq!(libc::pthread_attr_getstack(
attr.as_ptr(), &mut stackaddr, &mut stacksize
), 0);
assert_eq!(libc::pthread_attr_destroy(attr.as_mut_ptr()), 0);
let res = libc::pthread_attr_getstack(pthread_ctx, &mut stackaddr, &mut stacksize);
handle_pthread_err(pthread_ctx, res)?;

destroy_pthread_attr(pthread_ctx);
Some(stackaddr as usize)
}
} else if #[cfg(target_os = "openbsd")] {
Expand Down
Loading