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
This commit is contained in:
Johannes Altmanninger 2024-08-07 12:19:54 +02:00
parent 55196ee2a0
commit c1fba4663b

View File

@ -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);
}
}