diff options
| author | Florian Bartels <Florian.Bartels@elektrobit.com> | 2023-06-02 17:52:14 +0200 |
|---|---|---|
| committer | Florian Bartels <Florian.Bartels@elektrobit.com> | 2023-06-02 17:52:14 +0200 |
| commit | 716cc5ac938ad0a5302fe924a7142c0cc1d7d515 (patch) | |
| tree | 10e2cee8c5f0b56870c6369a9a3476fa81980c65 /library/std/src/sys/unix/process/process_unix.rs | |
| parent | d8f21101ec383d33c68f1867faf2ba74b3dca1a8 (diff) | |
| download | rust-716cc5ac938ad0a5302fe924a7142c0cc1d7d515.tar.gz rust-716cc5ac938ad0a5302fe924a7142c0cc1d7d515.zip | |
Only determine clock res once; give up before sleeping more than 1 second
Diffstat (limited to 'library/std/src/sys/unix/process/process_unix.rs')
| -rw-r--r-- | library/std/src/sys/unix/process/process_unix.rs | 60 |
1 files changed, 37 insertions, 23 deletions
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index f68f2541902..3721988b405 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -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)) } } |
