brush_core/sys/unix/
signal.rs1use crate::{error, sys, traps};
4
5pub(crate) use nix::sys::signal::Signal;
6
7pub(crate) fn continue_process(pid: sys::process::ProcessId) -> Result<(), error::Error> {
8 nix::sys::signal::kill(nix::unistd::Pid::from_raw(pid), nix::sys::signal::SIGCONT)
9 .map_err(|_errno| error::ErrorKind::FailedToSendSignal)?;
10 Ok(())
11}
12
13pub fn kill_process(
19 pid: sys::process::ProcessId,
20 signal: traps::TrapSignal,
21) -> Result<(), error::Error> {
22 let translated_signal = match signal {
23 traps::TrapSignal::Signal(signal) => signal,
24 traps::TrapSignal::Debug
25 | traps::TrapSignal::Err
26 | traps::TrapSignal::Exit
27 | traps::TrapSignal::Return => {
28 return Err(error::ErrorKind::InvalidSignal(signal.to_string()).into());
29 }
30 };
31
32 nix::sys::signal::kill(nix::unistd::Pid::from_raw(pid), translated_signal)
33 .map_err(|_errno| error::ErrorKind::FailedToSendSignal)?;
34
35 Ok(())
36}
37
38pub(crate) fn lead_new_process_group() -> Result<(), error::Error> {
39 nix::unistd::setpgid(nix::unistd::Pid::from_raw(0), nix::unistd::Pid::from_raw(0))?;
40 Ok(())
41}
42
43pub(crate) fn tstp_signal_listener() -> Result<tokio::signal::unix::Signal, error::Error> {
44 let signal = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::from_raw(
45 nix::libc::SIGTSTP,
46 ))?;
47 Ok(signal)
48}
49
50pub(crate) fn chld_signal_listener() -> Result<tokio::signal::unix::Signal, error::Error> {
51 let signal = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::child())?;
52 Ok(signal)
53}
54
55pub(crate) use tokio::signal::ctrl_c as await_ctrl_c;
56
57pub(crate) fn mask_sigttou() -> Result<(), error::Error> {
58 let ignore = nix::sys::signal::SigAction::new(
59 nix::sys::signal::SigHandler::SigIgn,
60 nix::sys::signal::SaFlags::empty(),
61 nix::sys::signal::SigSet::empty(),
62 );
63
64 unsafe { nix::sys::signal::sigaction(nix::sys::signal::Signal::SIGTTOU, &ignore) }?;
71
72 Ok(())
73}
74
75pub(crate) fn poll_for_stopped_children() -> Result<bool, error::Error> {
76 let mut found_stopped = false;
77
78 loop {
79 let wait_status = waitid_all(
80 nix::sys::wait::WaitPidFlag::WUNTRACED | nix::sys::wait::WaitPidFlag::WNOHANG,
81 );
82 match wait_status {
83 Ok(nix::sys::wait::WaitStatus::Stopped(_stopped_pid, _signal)) => {
84 found_stopped = true;
85 }
86 Ok(_) => break,
87 Err(nix::errno::Errno::ECHILD) => break,
88 Err(e) => return Err(e.into()),
89 }
90 }
91
92 Ok(found_stopped)
93}
94
95#[cfg(not(target_os = "macos"))]
96fn waitid_all(
97 flags: nix::sys::wait::WaitPidFlag,
98) -> Result<nix::sys::wait::WaitStatus, nix::errno::Errno> {
99 nix::sys::wait::waitid(nix::sys::wait::Id::All, flags)
100}
101
102#[cfg(target_os = "macos")]
109fn waitid_all(
110 flags: nix::sys::wait::WaitPidFlag,
111) -> Result<nix::sys::wait::WaitStatus, nix::errno::Errno> {
112 let siginfo = unsafe {
115 let mut siginfo: nix::libc::siginfo_t = std::mem::zeroed();
118 nix::errno::Errno::result(nix::libc::waitid(
119 nix::libc::P_ALL,
120 0,
121 &raw mut siginfo,
122 flags.bits(),
123 ))?;
124 siginfo
125 };
126
127 siginfo_to_wait_status(siginfo)
128}
129
130#[cfg(target_os = "macos")]
131fn siginfo_to_wait_status(
132 siginfo: nix::libc::siginfo_t,
133) -> Result<nix::sys::wait::WaitStatus, nix::errno::Errno> {
134 let si_pid = unsafe { siginfo.si_pid() };
137 if si_pid == 0 {
138 return Ok(nix::sys::wait::WaitStatus::StillAlive);
139 }
140
141 let pid = nix::unistd::Pid::from_raw(si_pid);
142
143 let si_status = unsafe { siginfo.si_status() };
146
147 let status = match siginfo.si_code {
148 nix::libc::CLD_EXITED => nix::sys::wait::WaitStatus::Exited(pid, si_status),
149 nix::libc::CLD_KILLED | nix::libc::CLD_DUMPED => nix::sys::wait::WaitStatus::Signaled(
150 pid,
151 nix::sys::signal::Signal::try_from(si_status)?,
152 siginfo.si_code == nix::libc::CLD_DUMPED,
153 ),
154 nix::libc::CLD_STOPPED => {
155 nix::sys::wait::WaitStatus::Stopped(pid, nix::sys::signal::Signal::try_from(si_status)?)
156 }
157 nix::libc::CLD_CONTINUED => nix::sys::wait::WaitStatus::Continued(pid),
158 _ => return Err(nix::errno::Errno::EINVAL),
159 };
160
161 Ok(status)
162}