runtime_paths/
unix_process.rs1use std::path::PathBuf;
2use std::process::{Command, Stdio};
3
4pub fn is_pid_alive(pid: u32) -> bool {
5 Command::new("kill")
6 .arg("-0")
7 .arg(pid.to_string())
8 .stdout(Stdio::null())
9 .stderr(Stdio::null())
10 .status()
11 .map(|status| status.success())
12 .unwrap_or(false)
13}
14
15pub fn process_executable_path(pid: u32) -> Option<PathBuf> {
16 #[cfg(target_os = "linux")]
17 {
18 std::fs::read_link(format!("/proc/{}/exe", pid)).ok()
19 }
20 #[cfg(target_os = "macos")]
21 {
22 let mut buf = [0u8; libc::PROC_PIDPATHINFO_MAXSIZE as usize];
26 let len = unsafe {
27 libc::proc_pidpath(
28 pid as libc::c_int,
29 buf.as_mut_ptr() as *mut libc::c_void,
30 buf.len() as u32,
31 )
32 };
33 if len <= 0 {
34 return None;
35 }
36 let path = std::ffi::CStr::from_bytes_until_nul(&buf[..]).ok()?;
37 let path = path.to_str().ok()?;
38 if path.is_empty() {
39 return None;
40 }
41 Some(PathBuf::from(path))
42 }
43 #[cfg(not(any(target_os = "linux", target_os = "macos")))]
44 {
45 let _ = pid;
46 None
47 }
48}
49
50pub fn unix_peer_pid(fd: std::os::unix::io::RawFd) -> Option<u32> {
52 #[cfg(target_os = "macos")]
53 {
54 const LOCAL_PEERPID: libc::c_int = 0x002;
56 let mut pid: libc::pid_t = 0;
57 let mut len = std::mem::size_of::<libc::pid_t>() as libc::socklen_t;
58 let rc = unsafe {
59 libc::getsockopt(
60 fd,
61 libc::SOL_LOCAL,
62 LOCAL_PEERPID,
63 &mut pid as *mut _ as *mut libc::c_void,
64 &mut len,
65 )
66 };
67 if rc == 0 && pid > 0 {
68 Some(pid as u32)
69 } else {
70 None
71 }
72 }
73 #[cfg(target_os = "linux")]
74 {
75 let mut cred = libc::ucred {
76 pid: 0,
77 uid: 0,
78 gid: 0,
79 };
80 let mut len = std::mem::size_of::<libc::ucred>() as libc::socklen_t;
81 let rc = unsafe {
82 libc::getsockopt(
83 fd,
84 libc::SOL_SOCKET,
85 libc::SO_PEERCRED,
86 &mut cred as *mut _ as *mut libc::c_void,
87 &mut len,
88 )
89 };
90 if rc == 0 && cred.pid > 0 {
91 Some(cred.pid as u32)
92 } else {
93 None
94 }
95 }
96 #[cfg(not(any(target_os = "macos", target_os = "linux")))]
97 {
98 let _ = fd;
99 None
100 }
101}
102
103pub fn clear_stale_unix_socket(socket_path: &std::path::Path) -> std::io::Result<bool> {
112 if !socket_path.exists() {
113 return Ok(false);
114 }
115 if std::os::unix::net::UnixStream::connect(socket_path).is_ok() {
117 return Ok(false);
118 }
119 match std::fs::remove_file(socket_path) {
120 Ok(()) => Ok(true),
121 Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(false),
122 Err(err) => Err(err),
123 }
124}