codex_utils_pty/
process_group.rs1use std::io;
19
20use tokio::process::Child;
21
22#[cfg(target_os = "linux")]
23pub fn set_parent_death_signal(parent_pid: libc::pid_t) -> io::Result<()> {
28 if unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGTERM) } == -1 {
29 return Err(io::Error::last_os_error());
30 }
31
32 if unsafe { libc::getppid() } != parent_pid {
33 unsafe {
34 libc::raise(libc::SIGTERM);
35 }
36 }
37
38 Ok(())
39}
40
41#[cfg(not(target_os = "linux"))]
42pub fn set_parent_death_signal(_parent_pid: i32) -> io::Result<()> {
44 Ok(())
45}
46
47#[cfg(unix)]
48pub fn detach_from_tty() -> io::Result<()> {
50 let result = unsafe { libc::setsid() };
51 if result == -1 {
52 let err = io::Error::last_os_error();
53 if err.raw_os_error() == Some(libc::EPERM) {
54 return set_process_group();
55 }
56 return Err(err);
57 }
58 Ok(())
59}
60
61#[cfg(not(unix))]
62pub fn detach_from_tty() -> io::Result<()> {
64 Ok(())
65}
66
67#[cfg(unix)]
68pub fn set_process_group() -> io::Result<()> {
72 let result = unsafe { libc::setpgid(0, 0) };
73 if result == -1 {
74 Err(io::Error::last_os_error())
75 } else {
76 Ok(())
77 }
78}
79
80#[cfg(not(unix))]
81pub fn set_process_group() -> io::Result<()> {
83 Ok(())
84}
85
86#[cfg(unix)]
87pub fn kill_process_group_by_pid(pid: u32) -> io::Result<()> {
91 use std::io::ErrorKind;
92
93 let pid = pid as libc::pid_t;
94 let pgid = unsafe { libc::getpgid(pid) };
95 if pgid == -1 {
96 let err = io::Error::last_os_error();
97 if err.kind() != ErrorKind::NotFound && err.raw_os_error() != Some(libc::ESRCH) {
98 return Err(err);
99 }
100 return Ok(());
101 }
102
103 let result = unsafe { libc::killpg(pgid, libc::SIGKILL) };
104 if result == -1 {
105 let err = io::Error::last_os_error();
106 if err.kind() != ErrorKind::NotFound && err.raw_os_error() != Some(libc::ESRCH) {
107 return Err(err);
108 }
109 }
110
111 Ok(())
112}
113
114#[cfg(not(unix))]
115pub fn kill_process_group_by_pid(_pid: u32) -> io::Result<()> {
117 Ok(())
118}
119
120#[cfg(unix)]
121fn signal_process_group_id(pgid: libc::pid_t, signal: libc::c_int) -> io::Result<bool> {
122 use std::io::ErrorKind;
123
124 let result = unsafe { libc::killpg(pgid, signal) };
125 if result == -1 {
126 let err = io::Error::last_os_error();
127 if err.kind() == ErrorKind::NotFound || err.raw_os_error() == Some(libc::ESRCH) {
128 return Ok(false);
129 }
130 return Err(err);
131 }
132
133 Ok(true)
134}
135
136#[cfg(unix)]
137pub fn terminate_process_group(process_group_id: u32) -> io::Result<bool> {
142 signal_process_group_id(process_group_id as libc::pid_t, libc::SIGTERM)
143}
144
145#[cfg(not(unix))]
146pub fn terminate_process_group(_process_group_id: u32) -> io::Result<bool> {
148 Ok(false)
149}
150
151#[cfg(unix)]
152pub fn interrupt_process_group(process_group_id: u32) -> io::Result<()> {
154 signal_process_group_id(process_group_id as libc::pid_t, libc::SIGINT).map(|_| ())
155}
156
157#[cfg(not(unix))]
158pub fn interrupt_process_group(_process_group_id: u32) -> io::Result<()> {
160 Ok(())
161}
162
163#[cfg(unix)]
164pub fn kill_process_group(process_group_id: u32) -> io::Result<()> {
166 signal_process_group_id(process_group_id as libc::pid_t, libc::SIGKILL).map(|_| ())
167}
168
169#[cfg(not(unix))]
170pub fn kill_process_group(_process_group_id: u32) -> io::Result<()> {
172 Ok(())
173}
174
175#[cfg(unix)]
176pub fn kill_child_process_group(child: &mut Child) -> io::Result<()> {
178 if let Some(pid) = child.id() {
179 return kill_process_group_by_pid(pid);
180 }
181
182 Ok(())
183}
184
185#[cfg(not(unix))]
186pub fn kill_child_process_group(_child: &mut Child) -> io::Result<()> {
188 Ok(())
189}