xcelerate_core/stealth/
process.rs1use std::process::Command;
2use std::sync::Mutex;
3use once_cell::sync::Lazy;
4use crate::error::{XcelerateResult, XcelerateError};
5
6#[cfg(windows)]
7use std::os::windows::process::CommandExt;
8
9#[cfg(unix)]
10use std::os::unix::process::CommandExt;
11
12pub static REGISTERED_PIDS: Lazy<Mutex<Vec<u32>>> = Lazy::new(|| Mutex::new(Vec::new()));
14
15pub fn spawn_detached(mut cmd: Command) -> XcelerateResult<u32> {
19 #[cfg(windows)]
20 {
21 cmd.creation_flags(0x00000200 | 0x00000008);
24 }
25
26 #[cfg(unix)]
27 {
28 unsafe {
29 cmd.pre_exec(|| {
30 if libc::setsid() == -1 {
32 return Err(std::io::Error::last_os_error());
33 }
34 Ok(())
35 });
36 }
37 }
38
39 let child = cmd.spawn().map_err(|e| XcelerateError::NotFound(format!("Failed to spawn detached process: {}", e)))?;
40 let pid = child.id();
41
42 if let Ok(mut pids) = REGISTERED_PIDS.lock() {
44 pids.push(pid);
45 }
46
47 Ok(pid)
48}
49
50pub struct ProcessGuard {
53 pub pid: u32,
54 pub auto_kill: bool,
55}
56
57impl Drop for ProcessGuard {
58 fn drop(&mut self) {
59 if self.auto_kill {
60 kill_pid(self.pid);
61 }
62
63 if let Ok(mut pids) = REGISTERED_PIDS.lock() {
65 pids.retain(|&p| p != self.pid);
66 }
67 }
68}
69
70pub fn kill_pid(pid: u32) {
72 #[cfg(windows)]
73 {
74 let _ = Command::new("taskkill")
75 .args(["/F", "/PID", &pid.to_string()])
76 .stdout(std::process::Stdio::null())
77 .stderr(std::process::Stdio::null())
78 .status();
79 }
80
81 #[cfg(unix)]
82 {
83 unsafe {
84 libc::kill(pid as i32, libc::SIGTERM);
85 }
86 }
87}
88
89pub fn cleanup_all() {
91 if let Ok(mut pids) = REGISTERED_PIDS.lock() {
92 for &pid in pids.iter() {
93 kill_pid(pid);
94 }
95 pids.clear();
96 }
97}
98
99pub struct ProcessRegistry;
100
101impl ProcessRegistry {
102 pub fn register(pid: u32) {
103 if let Ok(mut pids) = REGISTERED_PIDS.lock() {
104 pids.push(pid);
105 }
106 }
107
108 pub fn unregister(pid: u32) {
109 if let Ok(mut pids) = REGISTERED_PIDS.lock() {
110 pids.retain(|&p| p != pid);
111 }
112 }
113
114 pub fn cleanup() {
115 cleanup_all();
116 }
117}