Skip to content

Commit 46de56a

Browse files
authored
Rollup merge of rust-lang#113528 - workingjubilee:use-at-minsigstksz-in-rustc-signal-handler, r=WaffleLapkin
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 glibc's traditional static MINSIGSTKZ. Properly handle this so that it is correct on all supported Linux versions with all CPUs.
2 parents 1abf5d3 + 094cb1a commit 46de56a

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)