Skip to content

Commit 094cb1a

Browse files
Dynamically size sigaltstk in rustc
rustc installs a signal stack that assumes that MINSIGSTKSZ is a constant, unchanging value. Newer hardware undermines that assumption greatly, with register files larger than MINSIGSTKZ. Properly handle this so that it is correct on all supported Linux versions with all CPUs.
1 parent 71f71a5 commit 094cb1a

File tree

1 file changed

+22
-5
lines changed
  • compiler/rustc_driver_impl/src

1 file changed

+22
-5
lines changed

compiler/rustc_driver_impl/src/lib.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -1453,13 +1453,13 @@ mod signal_handler {
14531453
/// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
14541454
/// process, print a stack trace and then exit.
14551455
pub(super) fn install() {
1456+
use std::alloc::{alloc, Layout};
1457+
14561458
unsafe {
1457-
const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024;
1459+
let alt_stack_size: usize = min_sigstack_size() + 64 * 1024;
14581460
let mut alt_stack: libc::stack_t = std::mem::zeroed();
1459-
alt_stack.ss_sp =
1460-
std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap())
1461-
as *mut libc::c_void;
1462-
alt_stack.ss_size = ALT_STACK_SIZE;
1461+
alt_stack.ss_sp = alloc(Layout::from_size_align(alt_stack_size, 1).unwrap()).cast();
1462+
alt_stack.ss_size = alt_stack_size;
14631463
libc::sigaltstack(&alt_stack, std::ptr::null_mut());
14641464

14651465
let mut sa: libc::sigaction = std::mem::zeroed();
@@ -1469,6 +1469,23 @@ mod signal_handler {
14691469
libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut());
14701470
}
14711471
}
1472+
1473+
/// Modern kernels on modern hardware can have dynamic signal stack sizes.
1474+
#[cfg(any(target_os = "linux", target_os = "android"))]
1475+
fn min_sigstack_size() -> usize {
1476+
const AT_MINSIGSTKSZ: core::ffi::c_ulong = 51;
1477+
let dynamic_sigstksz = unsafe { libc::getauxval(AT_MINSIGSTKSZ) };
1478+
// If getauxval couldn't find the entry, it returns 0,
1479+
// so take the higher of the "constant" and auxval.
1480+
// This transparently supports older kernels which don't provide AT_MINSIGSTKSZ
1481+
libc::MINSIGSTKSZ.max(dynamic_sigstksz as _)
1482+
}
1483+
1484+
/// Not all OS support hardware where this is needed.
1485+
#[cfg(not(any(target_os = "linux", target_os = "android")))]
1486+
fn min_sigstack_size() -> usize {
1487+
libc::MINSIGSTKSZ
1488+
}
14721489
}
14731490

14741491
#[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]

0 commit comments

Comments
 (0)