tcrm_task/tasks/process/action/
pause.rs1#[cfg(unix)]
21pub fn pause_process(pid: u32) -> Result<(), std::io::Error> {
22 use nix::errno::Errno;
23 use nix::sys::signal::{Signal, kill};
24 use nix::unistd::Pid;
25
26 if pid == 0 {
28 return Err(std::io::Error::new(
29 std::io::ErrorKind::InvalidInput,
30 "Invalid PID: 0",
31 ));
32 }
33
34 let pid_i32 = match i32::try_from(pid) {
36 Ok(p) => p,
37 Err(_) => {
38 return Err(std::io::Error::new(
39 std::io::ErrorKind::InvalidInput,
40 format!("PID {} is too large for this system", pid),
41 ));
42 }
43 };
44
45 match kill(Pid::from_raw(pid_i32), Signal::SIGSTOP) {
46 Ok(_) => Ok(()),
47 Err(e) => match e {
48 Errno::ESRCH => Err(std::io::Error::new(
49 std::io::ErrorKind::NotFound,
50 format!("Process with PID {} does not exist", pid),
51 )),
52 Errno::EPERM => Err(std::io::Error::new(
53 std::io::ErrorKind::PermissionDenied,
54 format!("Permission denied to pause PID {}", pid),
55 )),
56 _ => Err(std::io::Error::new(
57 std::io::ErrorKind::Other,
58 format!("Failed to send SIGSTOP to PID {}: {}", pid, e),
59 )),
60 },
61 }
62}
63
64#[cfg(windows)]
84pub fn pause_process(pid: u32) -> Result<(), std::io::Error> {
85 use windows::Win32::Foundation::CloseHandle;
86 use windows::Win32::System::Diagnostics::ToolHelp::{
87 CreateToolhelp32Snapshot, TH32CS_SNAPTHREAD, THREADENTRY32, Thread32First, Thread32Next,
88 };
89 use windows::Win32::System::Threading::{OpenThread, SuspendThread, THREAD_SUSPEND_RESUME};
90
91 unsafe {
92 let snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0).map_err(|e| {
93 std::io::Error::new(
94 std::io::ErrorKind::Other,
95 format!("Failed to create thread snapshot: {:?}", e),
96 )
97 })?;
98
99 let mut thread_entry = THREADENTRY32 {
100 dwSize: std::mem::size_of::<THREADENTRY32>() as u32,
101 ..Default::default()
102 };
103
104 let mut suspended_count = 0;
105
106 if Thread32First(snapshot, &mut thread_entry).is_ok() {
107 loop {
108 if thread_entry.th32OwnerProcessID == pid {
109 let thread_handle =
110 OpenThread(THREAD_SUSPEND_RESUME, false, thread_entry.th32ThreadID);
111 if let Ok(handle) = thread_handle {
112 SuspendThread(handle);
113 let _ = CloseHandle(handle);
114 suspended_count += 1;
115 }
116 }
117
118 if Thread32Next(snapshot, &mut thread_entry).is_err() {
119 break;
120 }
121 }
122 }
123
124 let _ = CloseHandle(snapshot);
125
126 if suspended_count == 0 {
127 Err(std::io::Error::new(
128 std::io::ErrorKind::NotFound,
129 format!("No threads found for process with PID {}", pid),
130 ))
131 } else {
132 Ok(())
133 }
134 }
135}
136
137#[cfg(not(any(unix, windows)))]
139pub fn pause_process(_pid: u32) -> Result<(), std::io::Error> {
140 Err(std::io::Error::new(
141 std::io::ErrorKind::Other,
142 "Process pausing not supported on this platform",
143 ))
144}