mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Only determine clock res once; give up before sleeping more than 1 second
This commit is contained in:
parent
d8f21101ec
commit
716cc5ac93
@ -36,19 +36,25 @@ cfg_if::cfg_if! {
|
||||
use crate::thread;
|
||||
use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t};
|
||||
use crate::time::Duration;
|
||||
use crate::sync::LazyLock;
|
||||
// Get smallest amount of time we can sleep.
|
||||
// Return a common value if it cannot be determined.
|
||||
fn get_clock_resolution() -> Duration {
|
||||
let mut mindelay = libc::timespec { tv_sec: 0, tv_nsec: 0 };
|
||||
if unsafe { libc::clock_getres(libc::CLOCK_MONOTONIC, &mut mindelay) } == 0
|
||||
{
|
||||
Duration::from_nanos(mindelay.tv_nsec as u64)
|
||||
} else {
|
||||
Duration::from_millis(1)
|
||||
}
|
||||
static MIN_DELAY: LazyLock<Duration, fn() -> Duration> = LazyLock::new(|| {
|
||||
let mut mindelay = libc::timespec { tv_sec: 0, tv_nsec: 0 };
|
||||
if unsafe { libc::clock_getres(libc::CLOCK_MONOTONIC, &mut mindelay) } == 0
|
||||
{
|
||||
Duration::from_nanos(mindelay.tv_nsec as u64)
|
||||
} else {
|
||||
Duration::from_millis(1)
|
||||
}
|
||||
});
|
||||
*MIN_DELAY
|
||||
}
|
||||
// Arbitrary minimum sleep duration for retrying fork/spawn
|
||||
const MIN_FORKSPAWN_SLEEP: Duration = Duration::from_nanos(1);
|
||||
// Maximum duration of sleeping before giving up and returning an error
|
||||
const MAX_FORKSPAWN_SLEEP: Duration = Duration::from_millis(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,21 +181,22 @@ impl Command {
|
||||
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
|
||||
use crate::sys::os::errno;
|
||||
|
||||
let mut minimum_delay = None;
|
||||
let mut delay = MIN_FORKSPAWN_SLEEP;
|
||||
|
||||
loop {
|
||||
let r = libc::fork();
|
||||
if r == -1 as libc::pid_t && errno() as libc::c_int == libc::EBADF {
|
||||
if minimum_delay.is_none() {
|
||||
minimum_delay = Some(get_clock_resolution());
|
||||
}
|
||||
if delay < minimum_delay.unwrap() {
|
||||
if delay < get_clock_resolution() {
|
||||
// We cannot sleep this short (it would be longer).
|
||||
// Yield instead.
|
||||
thread::yield_now();
|
||||
} else {
|
||||
} else if delay < MAX_FORKSPAWN_SLEEP {
|
||||
thread::sleep(delay);
|
||||
} else {
|
||||
return Err(io::const_io_error!(
|
||||
ErrorKind::WouldBlock,
|
||||
"forking returned EBADF too often",
|
||||
));
|
||||
}
|
||||
delay *= 2;
|
||||
continue;
|
||||
@ -504,27 +511,28 @@ impl Command {
|
||||
attrp: *const posix_spawnattr_t,
|
||||
argv: *const *mut c_char,
|
||||
envp: *const *mut c_char,
|
||||
) -> i32 {
|
||||
let mut minimum_delay = None;
|
||||
) -> io::Result<i32> {
|
||||
let mut delay = MIN_FORKSPAWN_SLEEP;
|
||||
loop {
|
||||
match libc::posix_spawnp(pid, file, file_actions, attrp, argv, envp) {
|
||||
libc::EBADF => {
|
||||
if minimum_delay.is_none() {
|
||||
minimum_delay = Some(get_clock_resolution());
|
||||
}
|
||||
if delay < minimum_delay.unwrap() {
|
||||
if delay < get_clock_resolution() {
|
||||
// We cannot sleep this short (it would be longer).
|
||||
// Yield instead.
|
||||
thread::yield_now();
|
||||
} else {
|
||||
} else if delay < MAX_FORKSPAWN_SLEEP {
|
||||
thread::sleep(delay);
|
||||
} else {
|
||||
return Err(io::const_io_error!(
|
||||
ErrorKind::WouldBlock,
|
||||
"posix_spawnp returned EBADF too often",
|
||||
));
|
||||
}
|
||||
delay *= 2;
|
||||
continue;
|
||||
}
|
||||
r => {
|
||||
return r;
|
||||
return Ok(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -654,14 +662,20 @@ impl Command {
|
||||
let spawn_fn = libc::posix_spawnp;
|
||||
#[cfg(target_os = "nto")]
|
||||
let spawn_fn = retrying_libc_posix_spawnp;
|
||||
cvt_nz(spawn_fn(
|
||||
|
||||
let spawn_res = spawn_fn(
|
||||
&mut p.pid,
|
||||
self.get_program_cstr().as_ptr(),
|
||||
file_actions.0.as_ptr(),
|
||||
attrs.0.as_ptr(),
|
||||
self.get_argv().as_ptr() as *const _,
|
||||
envp as *const _,
|
||||
))?;
|
||||
);
|
||||
|
||||
#[cfg(target_os = "nto")]
|
||||
let spawn_res = spawn_res?;
|
||||
|
||||
cvt_nz(spawn_res)?;
|
||||
Ok(Some(p))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user