aboutsummaryrefslogtreecommitdiff
path: root/src/utils/signals.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-07-31 14:49:24 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-07-31 14:57:46 +0300
commite19e1f0f10fa4e294e62292608635877715232dd (patch)
treeb57571e3ff93b1e05fd01211c45c76a9bf24a0e9 /src/utils/signals.rs
parentc0ddf3f9ff3961944e83f6d9d3b936aef967c566 (diff)
downloadniri-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.rs119
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())
+ }
}
}