From 775315425641f2872faddc09b4641a3bc87f1bab Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Fri, 20 Dec 2024 17:17:13 +0100
Subject: [PATCH] Remove duplication between `Process::wait` methods on unix
 targets

---
 src/unix/apple/macos/process.rs | 14 +-------------
 src/unix/freebsd/process.rs     | 16 +---------------
 src/unix/linux/process.rs       | 18 +++---------------
 src/unix/utils.rs               | 21 +++++++++++++++++++++
 src/windows/process.rs          | 12 +++++++-----
 5 files changed, 33 insertions(+), 48 deletions(-)

diff --git a/src/unix/apple/macos/process.rs b/src/unix/apple/macos/process.rs
index 244915d68..18f1d6eaf 100644
--- a/src/unix/apple/macos/process.rs
+++ b/src/unix/apple/macos/process.rs
@@ -3,7 +3,6 @@
 use std::ffi::{OsStr, OsString};
 use std::mem::{self, MaybeUninit};
 use std::os::unix::ffi::{OsStrExt, OsStringExt};
-use std::os::unix::process::ExitStatusExt;
 use std::path::{Path, PathBuf};
 use std::process::ExitStatus;
 
@@ -205,18 +204,7 @@ impl ProcessInner {
     }
 
     pub(crate) fn wait(&self) -> Option<ExitStatus> {
-        let mut status = 0;
-        // attempt waiting
-        unsafe {
-            if retry_eintr!(libc::waitpid(self.pid.0, &mut status, 0)) < 0 {
-                // attempt failed (non-child process) so loop until process ends
-                let duration = std::time::Duration::from_millis(10);
-                while kill(self.pid.0, 0) == 0 {
-                    std::thread::sleep(duration);
-                }
-            }
-            Some(ExitStatus::from_raw(status))
-        }
+        crate::unix::utils::wait_process(self.pid)
     }
 
     pub(crate) fn session_id(&self) -> Option<Pid> {
diff --git a/src/unix/freebsd/process.rs b/src/unix/freebsd/process.rs
index cdf38a341..7ab9d0d9b 100644
--- a/src/unix/freebsd/process.rs
+++ b/src/unix/freebsd/process.rs
@@ -4,12 +4,9 @@ use crate::{DiskUsage, Gid, Pid, Process, ProcessRefreshKind, ProcessStatus, Sig
 
 use std::ffi::{OsStr, OsString};
 use std::fmt;
-use std::os::unix::process::ExitStatusExt;
 use std::path::{Path, PathBuf};
 use std::process::ExitStatus;
 
-use libc::kill;
-
 use super::utils::{get_sys_value_str, WrapMap};
 
 #[doc(hidden)]
@@ -157,18 +154,7 @@ impl ProcessInner {
     }
 
     pub(crate) fn wait(&self) -> Option<ExitStatus> {
-        let mut status = 0;
-        // attempt waiting
-        unsafe {
-            if retry_eintr!(libc::waitpid(self.pid.0, &mut status, 0)) < 0 {
-                // attempt failed (non-child process) so loop until process ends
-                let duration = std::time::Duration::from_millis(10);
-                while kill(self.pid.0, 0) == 0 {
-                    std::thread::sleep(duration);
-                }
-            }
-            Some(ExitStatus::from_raw(status))
-        }
+        crate::unix::utils::wait_process(self.pid)
     }
 
     pub(crate) fn session_id(&self) -> Option<Pid> {
diff --git a/src/unix/linux/process.rs b/src/unix/linux/process.rs
index e501cef61..33769192c 100644
--- a/src/unix/linux/process.rs
+++ b/src/unix/linux/process.rs
@@ -7,13 +7,12 @@ use std::fmt;
 use std::fs::{self, DirEntry, File};
 use std::io::Read;
 use std::os::unix::ffi::OsStrExt;
-use std::os::unix::process::ExitStatusExt;
 use std::path::{Path, PathBuf};
 use std::process::ExitStatus;
 use std::str::{self, FromStr};
 use std::sync::atomic::{AtomicUsize, Ordering};
 
-use libc::{c_ulong, gid_t, kill, uid_t};
+use libc::{c_ulong, gid_t, uid_t};
 
 use crate::sys::system::SystemInfo;
 use crate::sys::utils::{
@@ -169,7 +168,7 @@ impl ProcessInner {
 
     pub(crate) fn kill_with(&self, signal: Signal) -> Option<bool> {
         let c_signal = crate::sys::system::convert_signal(signal)?;
-        unsafe { Some(kill(self.pid.0, c_signal) == 0) }
+        unsafe { Some(libc::kill(self.pid.0, c_signal) == 0) }
     }
 
     pub(crate) fn name(&self) -> &OsStr {
@@ -254,18 +253,7 @@ impl ProcessInner {
     }
 
     pub(crate) fn wait(&self) -> Option<ExitStatus> {
-        let mut status = 0;
-        // attempt waiting
-        unsafe {
-            if retry_eintr!(libc::waitpid(self.pid.0, &mut status, 0)) < 0 {
-                // attempt failed (non-child process) so loop until process ends
-                let duration = std::time::Duration::from_millis(10);
-                while kill(self.pid.0, 0) == 0 {
-                    std::thread::sleep(duration);
-                }
-            }
-            Some(ExitStatus::from_raw(status))
-        }
+        crate::unix::utils::wait_process(self.pid)
     }
 
     pub(crate) fn session_id(&self) -> Option<Pid> {
diff --git a/src/unix/utils.rs b/src/unix/utils.rs
index 66f83a7e6..ac3a5c33e 100644
--- a/src/unix/utils.rs
+++ b/src/unix/utils.rs
@@ -34,3 +34,24 @@ pub(crate) fn cstr_to_rust_with_size(
         String::from_utf8(s).ok()
     }
 }
+
+#[cfg(all(
+    feature = "system",
+    not(any(target_os = "ios", feature = "apple-sandbox"))
+))]
+pub(crate) fn wait_process(pid: crate::Pid) -> Option<std::process::ExitStatus> {
+    use std::os::unix::process::ExitStatusExt;
+
+    let mut status = 0;
+    // attempt waiting
+    unsafe {
+        if retry_eintr!(libc::waitpid(pid.0, &mut status, 0)) < 0 {
+            // attempt failed (non-child process) so loop until process ends
+            let duration = std::time::Duration::from_millis(10);
+            while libc::kill(pid.0, 0) == 0 {
+                std::thread::sleep(duration);
+            }
+        }
+        Some(std::process::ExitStatus::from_raw(status))
+    }
+}
diff --git a/src/windows/process.rs b/src/windows/process.rs
index 767e6af7f..85f375505 100644
--- a/src/windows/process.rs
+++ b/src/windows/process.rs
@@ -415,11 +415,13 @@ impl ProcessInner {
                 std::thread::sleep(std::time::Duration::from_millis(10));
             }
             let mut exit_status = 0;
-            match GetExitCodeProcess(handle, &mut exit_status) {
-                Ok(_) => Some(ExitStatus::from_raw(exit_status)),
-                Err(_error) => {
-                    sysinfo_debug!("failed to retrieve process exit status: {_error:?}");
-                    None
+            unsafe {
+                match GetExitCodeProcess(handle, &mut exit_status) {
+                    Ok(_) => Some(ExitStatus::from_raw(exit_status)),
+                    Err(_error) => {
+                        sysinfo_debug!("failed to retrieve process exit status: {_error:?}");
+                        None
+                    }
                 }
             }
         } else {