diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-07-31 14:49:24 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-07-31 14:57:46 +0300 |
| commit | e19e1f0f10fa4e294e62292608635877715232dd (patch) | |
| tree | b57571e3ff93b1e05fd01211c45c76a9bf24a0e9 /src/utils/signals.rs | |
| parent | c0ddf3f9ff3961944e83f6d9d3b936aef967c566 (diff) | |
| download | niri-e19e1f0f10fa4e294e62292608635877715232dd.tar.gz niri-e19e1f0f10fa4e294e62292608635877715232dd.tar.bz2 niri-e19e1f0f10fa4e294e62292608635877715232dd.zip | |
signals: Gate on target_os = "linux"
Hopefully fixes build on FreeBSD.
Diffstat (limited to 'src/utils/signals.rs')
| -rw-r--r-- | src/utils/signals.rs | 119 |
1 files changed, 71 insertions, 48 deletions
diff --git a/src/utils/signals.rs b/src/utils/signals.rs index bf757131..73e3f10a 100644 --- a/src/utils/signals.rs +++ b/src/utils/signals.rs @@ -18,65 +18,88 @@ //! never intended to spawn niri with a nonempty sigmask. It indicates a bug in whoever spawned us, //! so we may as well clean up after them (which is easier than not doing so). -use std::{io, mem}; +pub use platform::*; -use calloop::signals::{Signal, Signals}; +#[cfg(not(target_os = "linux"))] +mod platform { + use std::io; -pub fn listen(handle: &calloop::LoopHandle<crate::niri::State>) { - handle - .insert_source( - Signals::new(&[Signal::SIGINT, Signal::SIGTERM, Signal::SIGHUP]).unwrap(), - |event, _, state| { - info!("quitting due to receiving signal {:?}", event.signal()); - state.niri.stop_signal.stop(); - }, - ) - .unwrap(); -} + // FIXME: implement for FreeBSD. But probably, that should be done in calloop::signals. + pub fn listen(_handle: &calloop::LoopHandle<crate::niri::State>) {} -// We block the signals early, so that they apply to all threads. -// They are then blocked *again* by the `Signals` source. That's fine. -pub fn block_early() -> io::Result<()> { - set_sigmask(&preferred_sigset()?) + // These two actually build as-is on FreeBSD, but without our own signal handling in listen(), + // they do more harm than good (they block termination signals without actually installing a + // termination handler). + pub fn block_early() -> io::Result<()> { + Ok(()) + } + pub fn unblock_all() -> io::Result<()> { + Ok(()) + } } -pub fn unblock_all() -> io::Result<()> { - set_sigmask(&empty_sigset()?) -} +#[cfg(target_os = "linux")] +mod platform { + use std::{io, mem}; + + pub fn listen(handle: &calloop::LoopHandle<crate::niri::State>) { + use calloop::signals::{Signal, Signals}; -fn empty_sigset() -> io::Result<libc::sigset_t> { - let mut sigset = mem::MaybeUninit::uninit(); - if unsafe { libc::sigemptyset(sigset.as_mut_ptr()) } == 0 { - Ok(unsafe { sigset.assume_init() }) - } else { - Err(io::Error::last_os_error()) + handle + .insert_source( + Signals::new(&[Signal::SIGINT, Signal::SIGTERM, Signal::SIGHUP]).unwrap(), + |event, _, state| { + info!("quitting due to receiving signal {:?}", event.signal()); + state.niri.stop_signal.stop(); + }, + ) + .unwrap(); } -} -fn preferred_sigset() -> io::Result<libc::sigset_t> { - let mut set = empty_sigset()?; - unsafe { - add_signal(&mut set, libc::SIGINT)?; - add_signal(&mut set, libc::SIGTERM)?; - add_signal(&mut set, libc::SIGHUP)?; + // We block the signals early, so that they apply to all threads. + // They are then blocked *again* by the `Signals` source. That's fine. + pub fn block_early() -> io::Result<()> { + set_sigmask(&preferred_sigset()?) } - Ok(set) -} -// SAFETY: `signum` must be a valid signal number. -unsafe fn add_signal(set: &mut libc::sigset_t, signum: libc::c_int) -> io::Result<()> { - if unsafe { libc::sigaddset(set, signum) } == 0 { - Ok(()) - } else { - Err(io::Error::last_os_error()) + pub fn unblock_all() -> io::Result<()> { + set_sigmask(&empty_sigset()?) } -} -fn set_sigmask(set: &libc::sigset_t) -> io::Result<()> { - let oldset = std::ptr::null_mut(); // ignore old mask - if unsafe { libc::pthread_sigmask(libc::SIG_SETMASK, set, oldset) } == 0 { - Ok(()) - } else { - Err(io::Error::last_os_error()) + fn empty_sigset() -> io::Result<libc::sigset_t> { + let mut sigset = mem::MaybeUninit::uninit(); + if unsafe { libc::sigemptyset(sigset.as_mut_ptr()) } == 0 { + Ok(unsafe { sigset.assume_init() }) + } else { + Err(io::Error::last_os_error()) + } + } + + fn preferred_sigset() -> io::Result<libc::sigset_t> { + let mut set = empty_sigset()?; + unsafe { + add_signal(&mut set, libc::SIGINT)?; + add_signal(&mut set, libc::SIGTERM)?; + add_signal(&mut set, libc::SIGHUP)?; + } + Ok(set) + } + + // SAFETY: `signum` must be a valid signal number. + unsafe fn add_signal(set: &mut libc::sigset_t, signum: libc::c_int) -> io::Result<()> { + if unsafe { libc::sigaddset(set, signum) } == 0 { + Ok(()) + } else { + Err(io::Error::last_os_error()) + } + } + + fn set_sigmask(set: &libc::sigset_t) -> io::Result<()> { + let oldset = std::ptr::null_mut(); // ignore old mask + if unsafe { libc::pthread_sigmask(libc::SIG_SETMASK, set, oldset) } == 0 { + Ok(()) + } else { + Err(io::Error::last_os_error()) + } } } |
