Skip to content

Commit 716cc5a

Browse files
committed
Only determine clock res once; give up before sleeping more than 1 second
1 parent d8f2110 commit 716cc5a

File tree

1 file changed

+37
-23
lines changed

1 file changed

+37
-23
lines changed

Diff for: library/std/src/sys/unix/process/process_unix.rs

+37-23
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,25 @@ cfg_if::cfg_if! {
3636
use crate::thread;
3737
use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t};
3838
use crate::time::Duration;
39+
use crate::sync::LazyLock;
3940
// Get smallest amount of time we can sleep.
4041
// Return a common value if it cannot be determined.
4142
fn get_clock_resolution() -> Duration {
42-
let mut mindelay = libc::timespec { tv_sec: 0, tv_nsec: 0 };
43-
if unsafe { libc::clock_getres(libc::CLOCK_MONOTONIC, &mut mindelay) } == 0
44-
{
45-
Duration::from_nanos(mindelay.tv_nsec as u64)
46-
} else {
47-
Duration::from_millis(1)
48-
}
43+
static MIN_DELAY: LazyLock<Duration, fn() -> Duration> = LazyLock::new(|| {
44+
let mut mindelay = libc::timespec { tv_sec: 0, tv_nsec: 0 };
45+
if unsafe { libc::clock_getres(libc::CLOCK_MONOTONIC, &mut mindelay) } == 0
46+
{
47+
Duration::from_nanos(mindelay.tv_nsec as u64)
48+
} else {
49+
Duration::from_millis(1)
50+
}
51+
});
52+
*MIN_DELAY
4953
}
5054
// Arbitrary minimum sleep duration for retrying fork/spawn
5155
const MIN_FORKSPAWN_SLEEP: Duration = Duration::from_nanos(1);
56+
// Maximum duration of sleeping before giving up and returning an error
57+
const MAX_FORKSPAWN_SLEEP: Duration = Duration::from_millis(1000);
5258
}
5359
}
5460

@@ -175,21 +181,22 @@ impl Command {
175181
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
176182
use crate::sys::os::errno;
177183

178-
let mut minimum_delay = None;
179184
let mut delay = MIN_FORKSPAWN_SLEEP;
180185

181186
loop {
182187
let r = libc::fork();
183188
if r == -1 as libc::pid_t && errno() as libc::c_int == libc::EBADF {
184-
if minimum_delay.is_none() {
185-
minimum_delay = Some(get_clock_resolution());
186-
}
187-
if delay < minimum_delay.unwrap() {
189+
if delay < get_clock_resolution() {
188190
// We cannot sleep this short (it would be longer).
189191
// Yield instead.
190192
thread::yield_now();
191-
} else {
193+
} else if delay < MAX_FORKSPAWN_SLEEP {
192194
thread::sleep(delay);
195+
} else {
196+
return Err(io::const_io_error!(
197+
ErrorKind::WouldBlock,
198+
"forking returned EBADF too often",
199+
));
193200
}
194201
delay *= 2;
195202
continue;
@@ -504,27 +511,28 @@ impl Command {
504511
attrp: *const posix_spawnattr_t,
505512
argv: *const *mut c_char,
506513
envp: *const *mut c_char,
507-
) -> i32 {
508-
let mut minimum_delay = None;
514+
) -> io::Result<i32> {
509515
let mut delay = MIN_FORKSPAWN_SLEEP;
510516
loop {
511517
match libc::posix_spawnp(pid, file, file_actions, attrp, argv, envp) {
512518
libc::EBADF => {
513-
if minimum_delay.is_none() {
514-
minimum_delay = Some(get_clock_resolution());
515-
}
516-
if delay < minimum_delay.unwrap() {
519+
if delay < get_clock_resolution() {
517520
// We cannot sleep this short (it would be longer).
518521
// Yield instead.
519522
thread::yield_now();
520-
} else {
523+
} else if delay < MAX_FORKSPAWN_SLEEP {
521524
thread::sleep(delay);
525+
} else {
526+
return Err(io::const_io_error!(
527+
ErrorKind::WouldBlock,
528+
"posix_spawnp returned EBADF too often",
529+
));
522530
}
523531
delay *= 2;
524532
continue;
525533
}
526534
r => {
527-
return r;
535+
return Ok(r);
528536
}
529537
}
530538
}
@@ -654,14 +662,20 @@ impl Command {
654662
let spawn_fn = libc::posix_spawnp;
655663
#[cfg(target_os = "nto")]
656664
let spawn_fn = retrying_libc_posix_spawnp;
657-
cvt_nz(spawn_fn(
665+
666+
let spawn_res = spawn_fn(
658667
&mut p.pid,
659668
self.get_program_cstr().as_ptr(),
660669
file_actions.0.as_ptr(),
661670
attrs.0.as_ptr(),
662671
self.get_argv().as_ptr() as *const _,
663672
envp as *const _,
664-
))?;
673+
);
674+
675+
#[cfg(target_os = "nto")]
676+
let spawn_res = spawn_res?;
677+
678+
cvt_nz(spawn_res)?;
665679
Ok(Some(p))
666680
}
667681
}

0 commit comments

Comments
 (0)