aboutsummaryrefslogtreecommitdiff
path: root/vendor/rayon-core/tests/stack_overflow_crash.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
committerValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
commit1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch)
tree7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/rayon-core/tests/stack_overflow_crash.rs
parent5ecd8cf2cba827454317368b68571df0d13d7842 (diff)
downloadfparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz
fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/rayon-core/tests/stack_overflow_crash.rs')
-rw-r--r--vendor/rayon-core/tests/stack_overflow_crash.rs97
1 files changed, 97 insertions, 0 deletions
diff --git a/vendor/rayon-core/tests/stack_overflow_crash.rs b/vendor/rayon-core/tests/stack_overflow_crash.rs
new file mode 100644
index 0000000..7dcde43
--- /dev/null
+++ b/vendor/rayon-core/tests/stack_overflow_crash.rs
@@ -0,0 +1,97 @@
+use rayon_core::ThreadPoolBuilder;
+
+use std::env;
+use std::process::{Command, ExitStatus, Stdio};
+
+#[cfg(target_os = "linux")]
+use std::os::unix::process::ExitStatusExt;
+
+fn force_stack_overflow(depth: u32) {
+ let mut buffer = [0u8; 1024 * 1024];
+ std::hint::black_box(&mut buffer);
+ if depth > 0 {
+ force_stack_overflow(depth - 1);
+ }
+}
+
+#[cfg(unix)]
+fn disable_core() {
+ unsafe {
+ libc::setrlimit(
+ libc::RLIMIT_CORE,
+ &libc::rlimit {
+ rlim_cur: 0,
+ rlim_max: 0,
+ },
+ );
+ }
+}
+
+#[cfg(unix)]
+fn overflow_code() -> Option<i32> {
+ None
+}
+
+#[cfg(windows)]
+fn overflow_code() -> Option<i32> {
+ use std::os::windows::process::ExitStatusExt;
+
+ ExitStatus::from_raw(0xc00000fd /*STATUS_STACK_OVERFLOW*/).code()
+}
+
+#[test]
+#[cfg_attr(not(any(unix, windows)), ignore)]
+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");
+ assert!(!status.success());
+ #[cfg(any(unix, windows))]
+ assert_eq!(status.code(), overflow_code());
+ #[cfg(target_os = "linux")]
+ assert!(matches!(
+ status.signal(),
+ Some(libc::SIGABRT | libc::SIGSEGV)
+ ));
+
+ // 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);
+}
+
+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()
+}
+
+#[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);
+ });
+}