From 7ae897c93a700bc9d98f9ceaf69ee6a3fa46ff1e Mon Sep 17 00:00:00 2001 From: FurryR Date: Thu, 24 Apr 2025 23:19:09 +0800 Subject: [PATCH 1/9] pidwait: optimize & cross-platform Signed-off-by: FurryR --- Cargo.lock | 2 + src/uu/pidwait/Cargo.toml | 6 ++ src/uu/pidwait/src/imp/bsd.rs | 51 +++++++++++++++ src/uu/pidwait/src/imp/linux.rs | 45 +++++++++++++ src/uu/pidwait/src/imp/windows.rs | 68 +++++++++++++++++++ src/uu/pidwait/src/pidwait.rs | 5 +- src/uu/pidwait/src/wait.rs | 104 +++++++++++++++++++----------- 7 files changed, 241 insertions(+), 40 deletions(-) create mode 100644 src/uu/pidwait/src/imp/bsd.rs create mode 100644 src/uu/pidwait/src/imp/linux.rs create mode 100644 src/uu/pidwait/src/imp/windows.rs diff --git a/Cargo.lock b/Cargo.lock index 17b99486..5a0cf6e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1554,8 +1554,10 @@ dependencies = [ "clap", "nix", "regex", + "rustix 1.0.5", "uu_pgrep", "uucore", + "windows-sys 0.59.0", ] [[package]] diff --git a/src/uu/pidwait/Cargo.toml b/src/uu/pidwait/Cargo.toml index 301257cf..33af45dd 100644 --- a/src/uu/pidwait/Cargo.toml +++ b/src/uu/pidwait/Cargo.toml @@ -19,6 +19,12 @@ clap = { workspace = true } regex = { workspace = true } uu_pgrep = { path = "../pgrep" } +[target.'cfg(unix)'.dependencies] +rustix = { version = "1", default-features = false, features = ["event", "process", "std"] } + +[target.'cfg(windows)'.dependencies] +windows-sys = { version = "0.59", features = ["Win32_Foundation", "Win32_System_Threading"] } + [lib] path = "src/pidwait.rs" diff --git a/src/uu/pidwait/src/imp/bsd.rs b/src/uu/pidwait/src/imp/bsd.rs new file mode 100644 index 00000000..f2e8de3b --- /dev/null +++ b/src/uu/pidwait/src/imp/bsd.rs @@ -0,0 +1,51 @@ +// This file is part of the uutils procps package. +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. + +// Reference: pidwait-any crate. +// Thanks to @oxalica's implementation. + +// FIXME: Test this implementation + +use rustix::event::kqueue::{kevent, kqueue, Event, EventFilter, EventFlags, ProcessEvents}; +use rustix::process::Pid; +use std::io::{Error, ErrorKind, Result}; +use std::mem::MaybeUninit; +use std::time::Duration; +use uu_pgrep::process::ProcessInformation; + +pub fn wait(procs: &[ProcessInformation], timeout: Option) -> Result> { + let mut events = Vec::with_capacity(procs.len()); + let kqueue = kqueue()?; + for proc in procs { + let pid = Pid::from_raw(proc.pid as i32).ok_or_else(|| { + Error::new( + ErrorKind::InvalidInput, + format!("Invalid PID: {}", proc.pid), + ) + })?; + let event = Event::new( + EventFilter::Proc { + pid, + flags: ProcessEvents::EXIT, + }, + EventFlags::ADD, + std::ptr::null_mut(), + ); + events.push(event); + } + let ret = unsafe { kevent::<_, &mut [Event; 0]>(&kqueue, &events, &mut [], None)? }; + debug_assert_eq!(ret, 0); + let mut buf = [MaybeUninit::uninit()]; + let (events, _rest_buf) = unsafe { kevent(&kqueue, &[], &mut buf, timeout)? }; + if events.is_empty() { + return Ok(None); + }; + debug_assert!(matches!( + events[0].filter(), + EventFilter::Proc { flags, .. } + if flags.contains(ProcessEvents::EXIT) + )); + Ok(Some(())) +} diff --git a/src/uu/pidwait/src/imp/linux.rs b/src/uu/pidwait/src/imp/linux.rs new file mode 100644 index 00000000..723761fb --- /dev/null +++ b/src/uu/pidwait/src/imp/linux.rs @@ -0,0 +1,45 @@ +// This file is part of the uutils procps package. +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. + +// Reference: pidwait-any crate. +// Thanks to @oxalica's implementation. + +use std::io::{Error, ErrorKind}; +use std::os::fd::OwnedFd; + +use rustix::event::{poll, PollFd, PollFlags}; +use rustix::io::Errno; +use rustix::process::{pidfd_open, Pid, PidfdFlags}; +use std::io::Result; +use std::time::Duration; +use uu_pgrep::process::ProcessInformation; + +pub fn wait(procs: &[ProcessInformation], timeout: Option) -> Result> { + let mut pidfds: Vec = Vec::with_capacity(procs.len()); + for proc in procs { + let pid = Pid::from_raw(proc.pid as i32).ok_or_else(|| { + Error::new( + ErrorKind::InvalidInput, + format!("Invalid PID: {}", proc.pid), + ) + })?; + let pidfd = pidfd_open(pid, PidfdFlags::empty())?; + pidfds.push(pidfd); + } + let timespec = match timeout { + Some(timeout) => Some(timeout.try_into().map_err(|_| Errno::INVAL)?), + None => None, + }; + let mut fds: Vec = Vec::with_capacity(pidfds.len()); + for pidfd in &pidfds { + fds.push(PollFd::new(pidfd, PollFlags::IN)); + } + let ret = poll(&mut fds, timespec.as_ref())?; + if ret == 0 { + return Ok(None); + } + debug_assert!(fds[0].revents().contains(PollFlags::IN)); + Ok(Some(())) +} diff --git a/src/uu/pidwait/src/imp/windows.rs b/src/uu/pidwait/src/imp/windows.rs new file mode 100644 index 00000000..e2a7fafe --- /dev/null +++ b/src/uu/pidwait/src/imp/windows.rs @@ -0,0 +1,68 @@ +// This file is part of the uutils procps package. +// +// For the full copyright and license information, please view the LICENSE +// file that was distributed with this source code. + +// Reference: pidwait-any crate. +// Thanks to @oxalica's implementation. + +use std::time::Duration; +use uu_pgrep::process::ProcessInformation; + +use std::ffi::c_void; +use std::io::{Error, Result}; +use std::ptr::NonNull; + +use windows_sys::Win32::Foundation::{CloseHandle, WAIT_OBJECT_0, WAIT_TIMEOUT}; +use windows_sys::Win32::System::Threading::{ + OpenProcess, WaitForMultipleObjects, INFINITE, PROCESS_SYNCHRONIZE, +}; + +struct HandleWrapper(NonNull); +unsafe impl Send for HandleWrapper {} +impl Drop for HandleWrapper { + fn drop(&mut self) { + unsafe { + CloseHandle(self.0.as_ptr()); + }; + } +} + +pub fn wait(procs: &[ProcessInformation], timeout: Option) -> Result> { + let hprocess = unsafe { + let mut result = Vec::with_capacity(procs.len()); + for proc in procs { + let handle = OpenProcess(PROCESS_SYNCHRONIZE, 0, proc.pid as u32); + result.push(HandleWrapper( + NonNull::new(handle).ok_or_else(Error::last_os_error)?, + )); + } + result + }; + const _: [(); 1] = [(); (INFINITE == u32::MAX) as usize]; + let timeout = match timeout { + Some(timeout) => timeout + .as_millis() + .try_into() + .unwrap_or(INFINITE - 1) + .min(INFINITE - 1), + None => INFINITE, + }; + let ret = unsafe { + WaitForMultipleObjects( + hprocess.len() as u32, + hprocess + .into_iter() + .map(|proc| proc.0.as_ptr()) + .collect::>() + .as_ptr(), + 1, + timeout, + ) + }; + match ret { + WAIT_OBJECT_0 => Ok(Some(())), + WAIT_TIMEOUT => Ok(None), + _ => Err(Error::last_os_error()), + } +} diff --git a/src/uu/pidwait/src/pidwait.rs b/src/uu/pidwait/src/pidwait.rs index 1a110a6e..798c06c5 100644 --- a/src/uu/pidwait/src/pidwait.rs +++ b/src/uu/pidwait/src/pidwait.rs @@ -18,6 +18,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let matches = uu_app().try_get_matches_from(args)?; let settings = process_matcher::get_match_settings(&matches)?; + + // FIXME: process_matcher::find_matching_pids() is not working on Windows let mut proc_infos = process_matcher::find_matching_pids(&settings); // For empty result @@ -42,7 +44,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } } - wait(&proc_infos); + // It should be fine to reserve a `timeout` parameter for future use. + wait(&proc_infos, None)?; Ok(()) } diff --git a/src/uu/pidwait/src/wait.rs b/src/uu/pidwait/src/wait.rs index 027bfdd2..5e79db45 100644 --- a/src/uu/pidwait/src/wait.rs +++ b/src/uu/pidwait/src/wait.rs @@ -3,51 +3,77 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. +use std::io::Result; +use std::time::Duration; use uu_pgrep::process::ProcessInformation; +// Reference: pidwait-any crate. +// Thanks to @oxalica's implementation. + +#[cfg(target_os = "linux")] +#[path = "./imp/linux.rs"] +mod imp; + +#[cfg(windows)] +#[path = "./imp/windows.rs"] +mod imp; + +#[cfg(any( + target_os = "freebsd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", +))] +#[path = "./imp/bsd.rs"] +mod imp; + +pub(crate) fn wait(procs: &[ProcessInformation], timeout: Option) -> Result> { + imp::wait(procs, timeout) +} + // Dirty, but it works. // TODO: Use better implementation instead -#[cfg(target_os = "linux")] -pub(crate) fn wait(procs: &[ProcessInformation]) { - use std::{thread::sleep, time::Duration}; +// #[cfg(target_os = "linux")] +// pub(crate) fn wait(procs: &[ProcessInformation]) { +// use std::{thread::sleep, time::Duration}; - let mut list = procs.to_vec(); +// let mut list = procs.to_vec(); - loop { - for proc in &list.clone() { - // Check is running - if !is_running(proc.pid) { - list.retain(|it| it.pid != proc.pid); - } - } +// loop { +// for proc in &list.clone() { +// // Check is running +// if !is_running(proc.pid) { +// list.retain(|it| it.pid != proc.pid); +// } +// } - if list.is_empty() { - return; - } +// if list.is_empty() { +// return; +// } - sleep(Duration::from_millis(50)); - } -} -#[cfg(target_os = "linux")] -fn is_running(pid: usize) -> bool { - use std::{path::PathBuf, str::FromStr}; - use uu_pgrep::process::RunState; - - let proc = PathBuf::from_str(&format!("/proc/{}", pid)).unwrap(); - - if !proc.exists() { - return false; - } - - match ProcessInformation::try_new(proc) { - Ok(mut proc) => proc - .run_state() - .map(|it| it != RunState::Stopped) - .unwrap_or(false), - Err(_) => false, - } -} +// sleep(Duration::from_millis(50)); +// } +// } +// #[cfg(target_os = "linux")] +// fn is_running(pid: usize) -> bool { +// use std::{path::PathBuf, str::FromStr}; +// use uu_pgrep::process::RunState; + +// let proc = PathBuf::from_str(&format!("/proc/{}", pid)).unwrap(); + +// if !proc.exists() { +// return false; +// } + +// match ProcessInformation::try_new(proc) { +// Ok(mut proc) => proc +// .run_state() +// .map(|it| it != RunState::Stopped) +// .unwrap_or(false), +// Err(_) => false, +// } +// } -// Just for passing compile on other system. -#[cfg(not(target_os = "linux"))] -pub(crate) fn wait(_procs: &[ProcessInformation]) {} +// // Just for passing compile on other system. +// #[cfg(not(target_os = "linux"))] +// pub(crate) fn wait(_procs: &[ProcessInformation]) {} From 7e2813b67a4e468cd37ae6725b43f0a913fee4fb Mon Sep 17 00:00:00 2001 From: FurryR Date: Sat, 31 May 2025 10:45:42 +0800 Subject: [PATCH 2/9] fix(pidwait): add length check for procs Signed-off-by: FurryR --- src/uu/pidwait/src/wait.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/uu/pidwait/src/wait.rs b/src/uu/pidwait/src/wait.rs index 5e79db45..5d14effd 100644 --- a/src/uu/pidwait/src/wait.rs +++ b/src/uu/pidwait/src/wait.rs @@ -28,7 +28,11 @@ mod imp; mod imp; pub(crate) fn wait(procs: &[ProcessInformation], timeout: Option) -> Result> { - imp::wait(procs, timeout) + if procs.len() > 0 { + imp::wait(procs, timeout) + } else { + Ok(None) + } } // Dirty, but it works. From dc7b00071aec0c46d5f8f723abed1661bc1b1431 Mon Sep 17 00:00:00 2001 From: FurryR Date: Sat, 31 May 2025 10:47:02 +0800 Subject: [PATCH 3/9] chore(pidwait): use workspace `windows-sys` crate Signed-off-by: FurryR --- src/uu/pidwait/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/pidwait/Cargo.toml b/src/uu/pidwait/Cargo.toml index 33af45dd..617e8341 100644 --- a/src/uu/pidwait/Cargo.toml +++ b/src/uu/pidwait/Cargo.toml @@ -23,7 +23,7 @@ uu_pgrep = { path = "../pgrep" } rustix = { version = "1", default-features = false, features = ["event", "process", "std"] } [target.'cfg(windows)'.dependencies] -windows-sys = { version = "0.59", features = ["Win32_Foundation", "Win32_System_Threading"] } +windows-sys = { workspace = true, features = ["Win32_Foundation", "Win32_System_Threading"] } [lib] path = "src/pidwait.rs" From c41708d56b4bc6bf366736630b3ee4092ed54412 Mon Sep 17 00:00:00 2001 From: FurryR Date: Sat, 31 May 2025 17:27:01 +0800 Subject: [PATCH 4/9] fix(pidwait): sync with master Signed-off-by: FurryR --- src/uu/pidwait/src/pidwait.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/uu/pidwait/src/pidwait.rs b/src/uu/pidwait/src/pidwait.rs index 798c06c5..0f4bdfab 100644 --- a/src/uu/pidwait/src/pidwait.rs +++ b/src/uu/pidwait/src/pidwait.rs @@ -18,9 +18,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let matches = uu_app().try_get_matches_from(args)?; let settings = process_matcher::get_match_settings(&matches)?; - - // FIXME: process_matcher::find_matching_pids() is not working on Windows - let mut proc_infos = process_matcher::find_matching_pids(&settings); + let mut proc_infos = process_matcher::find_matching_pids(&settings)?; // For empty result if proc_infos.is_empty() { @@ -61,4 +59,4 @@ pub fn uu_app() -> Command { "Name of the program to wait for", true, )) -} +} \ No newline at end of file From 50291130f46ac89542e7997b74f47127145cfa1e Mon Sep 17 00:00:00 2001 From: FurryR Date: Sat, 31 May 2025 17:28:35 +0800 Subject: [PATCH 5/9] chore(pidwait): add newline at eof sorry that is my fault. Signed-off-by: FurryR --- src/uu/pidwait/src/pidwait.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/pidwait/src/pidwait.rs b/src/uu/pidwait/src/pidwait.rs index 0f4bdfab..02a6130e 100644 --- a/src/uu/pidwait/src/pidwait.rs +++ b/src/uu/pidwait/src/pidwait.rs @@ -59,4 +59,4 @@ pub fn uu_app() -> Command { "Name of the program to wait for", true, )) -} \ No newline at end of file +} From 1836a9db454a55d2cf3993b447a47c127e28f816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=86=8A=E8=B0=B7=20=E5=87=8C?= Date: Mon, 9 Jun 2025 11:46:57 +0800 Subject: [PATCH 6/9] chore(pidwait): make clippy happy Signed-off-by: FurryR Co-authored-by: Daniel Hofstetter --- src/uu/pidwait/src/wait.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/pidwait/src/wait.rs b/src/uu/pidwait/src/wait.rs index 5d14effd..bbbb91c7 100644 --- a/src/uu/pidwait/src/wait.rs +++ b/src/uu/pidwait/src/wait.rs @@ -28,7 +28,7 @@ mod imp; mod imp; pub(crate) fn wait(procs: &[ProcessInformation], timeout: Option) -> Result> { - if procs.len() > 0 { + if !procs.is_empty() { imp::wait(procs, timeout) } else { Ok(None) From ce291ddf386f18d0eef8434b5beb95203fcd9dc2 Mon Sep 17 00:00:00 2001 From: FurryR Date: Mon, 9 Jun 2025 12:07:50 +0800 Subject: [PATCH 7/9] chore(pidwait): update structure Signed-off-by: FurryR --- src/uu/pidwait/src/pidwait.rs | 15 +++- src/uu/pidwait/src/{imp => platform}/bsd.rs | 0 src/uu/pidwait/src/{imp => platform}/linux.rs | 0 src/uu/pidwait/src/platform/mod.rs | 27 ++++++ .../pidwait/src/{imp => platform}/windows.rs | 0 src/uu/pidwait/src/wait.rs | 83 ------------------- 6 files changed, 39 insertions(+), 86 deletions(-) rename src/uu/pidwait/src/{imp => platform}/bsd.rs (100%) rename src/uu/pidwait/src/{imp => platform}/linux.rs (100%) create mode 100644 src/uu/pidwait/src/platform/mod.rs rename src/uu/pidwait/src/{imp => platform}/windows.rs (100%) delete mode 100644 src/uu/pidwait/src/wait.rs diff --git a/src/uu/pidwait/src/pidwait.rs b/src/uu/pidwait/src/pidwait.rs index 02a6130e..fea6dcff 100644 --- a/src/uu/pidwait/src/pidwait.rs +++ b/src/uu/pidwait/src/pidwait.rs @@ -4,15 +4,16 @@ // file that was distributed with this source code. use clap::{arg, crate_version, Command}; +use std::time::Duration; use uu_pgrep::process_matcher; use uucore::{error::UResult, format_usage, help_about, help_usage}; -use wait::wait; - -mod wait; +use uu_pgrep::process::ProcessInformation; const ABOUT: &str = help_about!("pidwait.md"); const USAGE: &str = help_usage!("pidwait.md"); +mod platform; + #[uucore::main] pub fn uumain(args: impl uucore::Args) -> UResult<()> { let matches = uu_app().try_get_matches_from(args)?; @@ -48,6 +49,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { Ok(()) } +pub(crate) fn wait(procs: &[ProcessInformation], timeout: Option) -> Result, std::io::Error> { + if !procs.is_empty() { + platform::wait(procs, timeout) + } else { + Ok(None) + } +} + pub fn uu_app() -> Command { Command::new(env!("CARGO_PKG_NAME")) .version(crate_version!()) diff --git a/src/uu/pidwait/src/imp/bsd.rs b/src/uu/pidwait/src/platform/bsd.rs similarity index 100% rename from src/uu/pidwait/src/imp/bsd.rs rename to src/uu/pidwait/src/platform/bsd.rs diff --git a/src/uu/pidwait/src/imp/linux.rs b/src/uu/pidwait/src/platform/linux.rs similarity index 100% rename from src/uu/pidwait/src/imp/linux.rs rename to src/uu/pidwait/src/platform/linux.rs diff --git a/src/uu/pidwait/src/platform/mod.rs b/src/uu/pidwait/src/platform/mod.rs new file mode 100644 index 00000000..55e965f1 --- /dev/null +++ b/src/uu/pidwait/src/platform/mod.rs @@ -0,0 +1,27 @@ +#[cfg(target_os = "linux")] +pub use self::linux::wait; + +#[cfg(windows)] +pub use self::windows::wait; + +#[cfg(any( + target_os = "freebsd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", +))] +pub use self::bsd::wait; + +#[cfg(target_os = "linux")] +mod linux; + +#[cfg(windows)] +mod windows; + +#[cfg(any( + target_os = "freebsd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", +))] +mod bsd; \ No newline at end of file diff --git a/src/uu/pidwait/src/imp/windows.rs b/src/uu/pidwait/src/platform/windows.rs similarity index 100% rename from src/uu/pidwait/src/imp/windows.rs rename to src/uu/pidwait/src/platform/windows.rs diff --git a/src/uu/pidwait/src/wait.rs b/src/uu/pidwait/src/wait.rs deleted file mode 100644 index bbbb91c7..00000000 --- a/src/uu/pidwait/src/wait.rs +++ /dev/null @@ -1,83 +0,0 @@ -// This file is part of the uutils procps package. -// -// For the full copyright and license information, please view the LICENSE -// file that was distributed with this source code. - -use std::io::Result; -use std::time::Duration; -use uu_pgrep::process::ProcessInformation; - -// Reference: pidwait-any crate. -// Thanks to @oxalica's implementation. - -#[cfg(target_os = "linux")] -#[path = "./imp/linux.rs"] -mod imp; - -#[cfg(windows)] -#[path = "./imp/windows.rs"] -mod imp; - -#[cfg(any( - target_os = "freebsd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", -))] -#[path = "./imp/bsd.rs"] -mod imp; - -pub(crate) fn wait(procs: &[ProcessInformation], timeout: Option) -> Result> { - if !procs.is_empty() { - imp::wait(procs, timeout) - } else { - Ok(None) - } -} - -// Dirty, but it works. -// TODO: Use better implementation instead -// #[cfg(target_os = "linux")] -// pub(crate) fn wait(procs: &[ProcessInformation]) { -// use std::{thread::sleep, time::Duration}; - -// let mut list = procs.to_vec(); - -// loop { -// for proc in &list.clone() { -// // Check is running -// if !is_running(proc.pid) { -// list.retain(|it| it.pid != proc.pid); -// } -// } - -// if list.is_empty() { -// return; -// } - -// sleep(Duration::from_millis(50)); -// } -// } -// #[cfg(target_os = "linux")] -// fn is_running(pid: usize) -> bool { -// use std::{path::PathBuf, str::FromStr}; -// use uu_pgrep::process::RunState; - -// let proc = PathBuf::from_str(&format!("/proc/{}", pid)).unwrap(); - -// if !proc.exists() { -// return false; -// } - -// match ProcessInformation::try_new(proc) { -// Ok(mut proc) => proc -// .run_state() -// .map(|it| it != RunState::Stopped) -// .unwrap_or(false), -// Err(_) => false, -// } -// } - -// // Just for passing compile on other system. -// #[cfg(not(target_os = "linux"))] -// pub(crate) fn wait(_procs: &[ProcessInformation]) {} From 76310ac723552b98b27b57445a69b875d68b8a61 Mon Sep 17 00:00:00 2001 From: FurryR Date: Mon, 9 Jun 2025 12:08:46 +0800 Subject: [PATCH 8/9] chore(pidwait): styling Signed-off-by: FurryR --- src/uu/pidwait/src/pidwait.rs | 7 +++++-- src/uu/pidwait/src/platform/mod.rs | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/uu/pidwait/src/pidwait.rs b/src/uu/pidwait/src/pidwait.rs index fea6dcff..651b9a58 100644 --- a/src/uu/pidwait/src/pidwait.rs +++ b/src/uu/pidwait/src/pidwait.rs @@ -5,9 +5,9 @@ use clap::{arg, crate_version, Command}; use std::time::Duration; +use uu_pgrep::process::ProcessInformation; use uu_pgrep::process_matcher; use uucore::{error::UResult, format_usage, help_about, help_usage}; -use uu_pgrep::process::ProcessInformation; const ABOUT: &str = help_about!("pidwait.md"); const USAGE: &str = help_usage!("pidwait.md"); @@ -49,7 +49,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { Ok(()) } -pub(crate) fn wait(procs: &[ProcessInformation], timeout: Option) -> Result, std::io::Error> { +pub(crate) fn wait( + procs: &[ProcessInformation], + timeout: Option, +) -> Result, std::io::Error> { if !procs.is_empty() { platform::wait(procs, timeout) } else { diff --git a/src/uu/pidwait/src/platform/mod.rs b/src/uu/pidwait/src/platform/mod.rs index 55e965f1..d1f08e25 100644 --- a/src/uu/pidwait/src/platform/mod.rs +++ b/src/uu/pidwait/src/platform/mod.rs @@ -24,4 +24,4 @@ mod windows; target_os = "netbsd", target_os = "openbsd", ))] -mod bsd; \ No newline at end of file +mod bsd; From 1e9a3dd241237bcf43fafcf182c60205591e3906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=86=8A=E8=B0=B7=20=E5=87=8C?= Date: Thu, 12 Jun 2025 21:57:08 +0800 Subject: [PATCH 9/9] refactor(pidwait): merge suggestions Co-authored-by: Daniel Hofstetter --- src/uu/pidwait/src/platform/linux.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/uu/pidwait/src/platform/linux.rs b/src/uu/pidwait/src/platform/linux.rs index 723761fb..aaa8e592 100644 --- a/src/uu/pidwait/src/platform/linux.rs +++ b/src/uu/pidwait/src/platform/linux.rs @@ -28,10 +28,9 @@ pub fn wait(procs: &[ProcessInformation], timeout: Option) -> Result Some(timeout.try_into().map_err(|_| Errno::INVAL)?), - None => None, - }; + let timespec = timeout + .map(|t| t.try_into().map_err(|_| Errno::INVAL)) + .transpose()?; let mut fds: Vec = Vec::with_capacity(pidfds.len()); for pidfd in &pidfds { fds.push(PollFd::new(pidfd, PollFlags::IN));