From fcb91379ba8fdaa00551df2e20f025c0a11e91e9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:11:14 +0000 Subject: [PATCH 1/4] Pipe2 is always available on Linux Pipe2 was introduced in Linux 2.6.27 while our minimum is 3.2. And Glibc 2.9 while we need 2.17. --- src/unix.rs | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/unix.rs b/src/unix.rs index 2b310c2..80ae8c3 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -72,30 +72,19 @@ impl Client { unsafe fn mk() -> io::Result { let mut pipes = [0; 2]; - // Attempt atomically-create-with-cloexec if we can on Linux, - // detected by using the `syscall` function in `libc` to try to work - // with as many kernels/glibc implementations as possible. + // Atomically-create-with-cloexec on Linux. #[cfg(target_os = "linux")] + if libc::syscall(libc::SYS_pipe2, pipes.as_mut_ptr(), libc::O_CLOEXEC) == -1 { + return Err(io::Error::last_os_error()); + } + + #[cfg(not(target_os = "linux"))] { - static PIPE2_AVAILABLE: AtomicBool = AtomicBool::new(true); - if PIPE2_AVAILABLE.load(Ordering::SeqCst) { - match libc::syscall(libc::SYS_pipe2, pipes.as_mut_ptr(), libc::O_CLOEXEC) { - -1 => { - let err = io::Error::last_os_error(); - if err.raw_os_error() == Some(libc::ENOSYS) { - PIPE2_AVAILABLE.store(false, Ordering::SeqCst); - } else { - return Err(err); - } - } - _ => return Ok(Client::from_fds(pipes[0], pipes[1])), - } - } + cvt(libc::pipe(pipes.as_mut_ptr()))?; + drop(set_cloexec(pipes[0], true)); + drop(set_cloexec(pipes[1], true)); } - cvt(libc::pipe(pipes.as_mut_ptr()))?; - drop(set_cloexec(pipes[0], true)); - drop(set_cloexec(pipes[1], true)); Ok(Client::from_fds(pipes[0], pipes[1])) } From 588c01d1c5a6e9db66e3d480aa45a9a9502b8dce Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:12:30 +0000 Subject: [PATCH 2/4] Use pipe2 libc wrapper rather than a raw syscall Miri doesn't support the raw syscall variant. --- src/unix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix.rs b/src/unix.rs index 80ae8c3..4194bb6 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -74,7 +74,7 @@ impl Client { // Atomically-create-with-cloexec on Linux. #[cfg(target_os = "linux")] - if libc::syscall(libc::SYS_pipe2, pipes.as_mut_ptr(), libc::O_CLOEXEC) == -1 { + if libc::pipe2(pipes.as_mut_ptr(), libc::O_CLOEXEC) == -1 { return Err(io::Error::last_os_error()); } From c5f6152ead55509195e762e06f95f2012937b9b7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:17:11 +0000 Subject: [PATCH 3/4] Fix a warning --- src/unix.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/unix.rs b/src/unix.rs index 4194bb6..53d3546 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -552,12 +552,7 @@ mod test { use crate::{test::run_named_fifo_try_acquire_tests, Client}; - use std::{ - fs::File, - io::{self, Write}, - os::unix::io::AsRawFd, - sync::Arc, - }; + use std::{fs::File, io::Write, os::unix::io::AsRawFd, sync::Arc}; fn from_imp_client(imp: ClientImp) -> Client { Client { @@ -611,7 +606,7 @@ mod test { #[cfg(not(target_os = "linux"))] assert_eq!( new_client_from_pipe().0.try_acquire().unwrap_err().kind(), - io::ErrorKind::Unsupported + std::io::ErrorKind::Unsupported ); #[cfg(target_os = "linux")] From 5f0b099b69846f6b86b0845e13a66c773d761b4f Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:23:36 +0000 Subject: [PATCH 4/4] Disable helper thread cleanup signals in miri Miri doesn't support signals and the cleanup is best-effort anyway. --- src/unix.rs | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/unix.rs b/src/unix.rs index 53d3546..2758e31 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -8,10 +8,9 @@ use std::mem::MaybeUninit; use std::os::unix::prelude::*; use std::path::Path; use std::process::Command; -use std::ptr; use std::sync::{ atomic::{AtomicBool, Ordering}, - Arc, Once, + Arc, }; use std::thread::{self, Builder, JoinHandle}; use std::time::Duration; @@ -379,19 +378,24 @@ pub(crate) fn spawn_helper( state: Arc, mut f: Box) + Send>, ) -> io::Result { - static USR1_INIT: Once = Once::new(); - let mut err = None; - USR1_INIT.call_once(|| unsafe { - let mut new: libc::sigaction = mem::zeroed(); - new.sa_sigaction = sigusr1_handler as usize; - new.sa_flags = libc::SA_SIGINFO as _; - if libc::sigaction(libc::SIGUSR1, &new, ptr::null_mut()) != 0 { - err = Some(io::Error::last_os_error()); - } - }); + #[cfg(not(miri))] + { + use std::sync::Once; + + static USR1_INIT: Once = Once::new(); + let mut err = None; + USR1_INIT.call_once(|| unsafe { + let mut new: libc::sigaction = mem::zeroed(); + new.sa_sigaction = sigusr1_handler as usize; + new.sa_flags = libc::SA_SIGINFO as _; + if libc::sigaction(libc::SIGUSR1, &new, std::ptr::null_mut()) != 0 { + err = Some(io::Error::last_os_error()); + } + }); - if let Some(e) = err.take() { - return Err(e); + if let Some(e) = err.take() { + return Err(e); + } } let state2 = state.clone(); @@ -436,6 +440,7 @@ impl Helper { if state.consumer_done { break; } + #[cfg(not(miri))] unsafe { // Ignore the return value here of `pthread_kill`, // apparently on OSX if you kill a dead thread it will @@ -538,6 +543,7 @@ fn cvt(t: c_int) -> io::Result { } } +#[cfg(not(miri))] extern "C" fn sigusr1_handler( _signum: c_int, _info: *mut libc::siginfo_t,