signal_hook/iterator/exfiltrator/origin.rs
1//! An exfiltrator providing the process that caused the signal.
2//!
3//! The [`WithOrigin`] is an [`Exfiltrator`][crate::iterator::exfiltrator::Exfiltrator] that
4//! provides the information about sending process in addition to the signal number, through the
5//! [`Origin`] type.
6//!
7//! See the [`WithOrigin`] example.
8
9use libc::{c_int, siginfo_t};
10
11pub use super::raw::Slot;
12use super::sealed::Exfiltrator;
13use super::WithRawSiginfo;
14pub use crate::low_level::siginfo::{Origin, Process};
15
16/// The [`Exfiltrator`][crate::iterator::exfiltrator::Exfiltrator] that produces [`Origin`] of
17/// signals.
18///
19/// # Examples
20///
21/// ```rust
22/// # use signal_hook::consts::SIGUSR1;
23/// # use signal_hook::iterator::SignalsInfo;
24/// # use signal_hook::iterator::exfiltrator::WithOrigin;
25/// #
26/// # fn main() -> Result<(), std::io::Error> {
27/// // Subscribe to SIGUSR1, with information about the process.
28/// let mut signals = SignalsInfo::<WithOrigin>::new(&[SIGUSR1])?;
29///
30/// // Send a signal to ourselves.
31/// let my_pid = unsafe { libc::getpid() };
32/// unsafe { libc::kill(my_pid, SIGUSR1) };
33///
34/// // Grab the signal and look into the details.
35/// let received = signals.wait().next().unwrap();
36///
37/// assert_eq!(SIGUSR1, received.signal);
38/// assert_eq!(my_pid, received.process.unwrap().pid);
39/// # Ok(()) }
40/// ```
41#[derive(Copy, Clone, Debug, Default)]
42pub struct WithOrigin(WithRawSiginfo);
43
44// Safety: We need to be async-signal-safe. We delegate to other Exfiltrator, which already is and
45// call a function that promises to be (Origin::extract)
46unsafe impl Exfiltrator for WithOrigin {
47 type Storage = Slot;
48 type Output = Origin;
49 fn supports_signal(&self, signal: c_int) -> bool {
50 self.0.supports_signal(signal)
51 }
52
53 fn store(&self, slot: &Slot, signal: c_int, info: &siginfo_t) {
54 self.0.store(slot, signal, info)
55 }
56
57 fn load(&self, slot: &Self::Storage, signal: c_int) -> Option<Origin> {
58 self.0
59 .load(slot, signal)
60 .map(|info| unsafe { Origin::extract(&info) })
61 }
62
63 fn init(&self, slot: &Self::Storage, signal: c_int) {
64 self.0.init(slot, signal)
65 }
66}