From e4ba8d16f32ac5dbca59cd786601af6da34ca43e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 16 Jan 2023 18:05:32 -0800 Subject: [PATCH] Improve rayon-core/tests/stack_overflow_crash.rs - Rewrite it within the regular test harness, so it doesn't crash in arg-parsing on broad `cargo test -- filter` commands. - Use `std::hint::black_box` so the test even works in `--release`. --- rayon-core/Cargo.toml | 1 - rayon-core/tests/stack_overflow_crash.rs | 93 ++++++++++++++---------- 2 files changed, 53 insertions(+), 41 deletions(-) diff --git a/rayon-core/Cargo.toml b/rayon-core/Cargo.toml index 9e45992dd..3b0ed149d 100644 --- a/rayon-core/Cargo.toml +++ b/rayon-core/Cargo.toml @@ -33,7 +33,6 @@ libc = "0.2" [[test]] name = "stack_overflow_crash" path = "tests/stack_overflow_crash.rs" -harness = false # NB: having one [[test]] manually defined means we need to declare them all diff --git a/rayon-core/tests/stack_overflow_crash.rs b/rayon-core/tests/stack_overflow_crash.rs index 61288982c..e87e151a9 100644 --- a/rayon-core/tests/stack_overflow_crash.rs +++ b/rayon-core/tests/stack_overflow_crash.rs @@ -1,13 +1,14 @@ use rayon_core::ThreadPoolBuilder; use std::env; -use std::process::Command; +use std::process::{Command, ExitStatus, Stdio}; #[cfg(target_os = "linux")] use std::os::unix::process::ExitStatusExt; fn force_stack_overflow(depth: u32) { - let _buffer = [0u8; 1024 * 1024]; + let mut buffer = [0u8; 1024 * 1024]; + std::hint::black_box(&mut buffer); if depth > 0 { force_stack_overflow(depth - 1); } @@ -34,49 +35,61 @@ fn overflow_code() -> Option { #[cfg(windows)] fn overflow_code() -> Option { use std::os::windows::process::ExitStatusExt; - use std::process::ExitStatus; ExitStatus::from_raw(0xc00000fd /*STATUS_STACK_OVERFLOW*/).code() } -fn main() { - if env::args().len() == 1 { - // first check that the recursivecall actually causes a stack overflow, and does not get optimized away - { - let status = Command::new(env::current_exe().unwrap()) - .arg("8") - .status() - .unwrap(); +#[test] +fn stack_overflow_crash() { + // First check that the recursive call actually causes a stack overflow, + // and does not get optimized away. + let status = run_ignored("run_with_small_stack"); + #[cfg(any(unix, windows))] + assert_eq!(status.code(), overflow_code()); + #[cfg(target_os = "linux")] + assert!(matches!( + status.signal(), + Some(libc::SIGABRT | libc::SIGSEGV) + )); - #[cfg(any(unix, windows))] - assert_eq!(status.code(), overflow_code()); + // Now run with a larger stack and verify correct operation. + let status = run_ignored("run_with_large_stack"); + assert_eq!(status.code(), Some(0)); + #[cfg(target_os = "linux")] + assert_eq!(status.signal(), None); +} - #[cfg(target_os = "linux")] - assert!( - status.signal() == Some(11 /*SIGABRT*/) || status.signal() == Some(6 /*SIGSEGV*/) - ); - } +fn run_ignored(test: &str) -> ExitStatus { + Command::new(env::current_exe().unwrap()) + .arg("--ignored") + .arg("--exact") + .arg(test) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .status() + .unwrap() +} - // now run with a larger stack and verify correct operation - { - let status = Command::new(env::current_exe().unwrap()) - .arg("48") - .status() - .unwrap(); - assert_eq!(status.code(), Some(0)); - #[cfg(target_os = "linux")] - assert_eq!(status.signal(), None); - } - } else { - let stack_size_in_mb: usize = env::args().nth(1).unwrap().parse().unwrap(); - let pool = ThreadPoolBuilder::new() - .stack_size(stack_size_in_mb * 1024 * 1024) - .build() - .unwrap(); - pool.install(|| { - #[cfg(unix)] - disable_core(); - force_stack_overflow(32); - }); - } +#[test] +#[ignore] +fn run_with_small_stack() { + run_with_stack(8); +} + +#[test] +#[ignore] +fn run_with_large_stack() { + run_with_stack(48); +} + +fn run_with_stack(stack_size_in_mb: usize) { + let pool = ThreadPoolBuilder::new() + .stack_size(stack_size_in_mb * 1024 * 1024) + .build() + .unwrap(); + pool.install(|| { + #[cfg(unix)] + disable_core(); + force_stack_overflow(32); + }); }