From c1fba4663b4d61f4c8f59554293b082274416d0d Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Wed, 7 Aug 2024 12:19:54 +0200 Subject: [PATCH] Replace nanosleep with stdlib wrapper (which is still broken) As of rust 1.78, the Unix stdlib implementation is affected by the same issue: pub fn sleep(dur: Duration) { let mut secs = dur.as_secs(); let mut nsecs = dur.subsec_nanos() as _; // If we're awoken with a signal then the return value will be -1 and // nanosleep will fill in `ts` with the remaining time. unsafe { while secs > 0 || nsecs > 0 { let mut ts = libc::timespec { tv_sec: cmp::min(libc::time_t::MAX as u64, secs) as libc::time_t, tv_nsec: nsecs, }; secs -= ts.tv_sec as u64; let ts_ptr = core::ptr::addr_of_mut!(ts); if libc::nanosleep(ts_ptr, ts_ptr) == -1 { assert_eq!(os::errno(), libc::EINTR); secs += ts.tv_sec as u64; nsecs = ts.tv_nsec; } else { nsecs = 0; } } } } Note that there is a small behavior change here -- sleep() will continue after signals; I'm not sure if we want that but it seems harmless? Part of #10634 --- src/fork_exec/postfork.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/fork_exec/postfork.rs b/src/fork_exec/postfork.rs index 664b79227..14bcb4c7a 100644 --- a/src/fork_exec/postfork.rs +++ b/src/fork_exec/postfork.rs @@ -9,12 +9,13 @@ use crate::{common::exit_without_destructors, wutil::fstat}; use libc::{c_char, pid_t, O_RDONLY}; use std::ffi::CStr; use std::os::unix::fs::MetadataExt; +use std::time::Duration; /// The number of times to try to call fork() before giving up. const FORK_LAPS: usize = 5; /// The number of nanoseconds to sleep between attempts to call fork(). -const FORK_SLEEP_TIME: libc::c_long = 1000000; +const FORK_SLEEP_TIME: Duration = Duration::from_nanos(1000000); /// Clear FD_CLOEXEC on a file descriptor. fn clear_cloexec(fd: i32) -> i32 { @@ -211,13 +212,9 @@ pub fn execute_fork() -> pid_t { if err != libc::EAGAIN { break; } - let pollint = libc::timespec { - tv_sec: 0, - tv_nsec: FORK_SLEEP_TIME, - }; // Don't sleep on the final lap if i != FORK_LAPS - 1 { - unsafe { libc::nanosleep(&pollint, std::ptr::null_mut()) }; + std::thread::sleep(FORK_SLEEP_TIME); } }