diff options
| -rw-r--r-- | src/main.rs | 3 | ||||
| -rw-r--r-- | src/utils/signals.rs | 25 |
2 files changed, 28 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs index f73f25fa..43325a77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -134,6 +134,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { } } + // Needs to be done before starting Tracy, so that it applies to Tracy's threads. + niri::utils::signals::block_early().unwrap(); + // Avoid starting Tracy for the `niri msg` code path since starting/stopping Tracy is a bit // slow. tracy_client::Client::start(); diff --git a/src/utils/signals.rs b/src/utils/signals.rs index 9aae44b1..bdface0f 100644 --- a/src/utils/signals.rs +++ b/src/utils/signals.rs @@ -34,6 +34,12 @@ pub fn listen(handle: &calloop::LoopHandle<crate::niri::State>) { .unwrap(); } +// 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()?) +} + pub fn unblock_all() -> io::Result<()> { set_sigmask(&empty_sigset()?) } @@ -47,6 +53,25 @@ pub fn empty_sigset() -> io::Result<libc::sigset_t> { } } +pub 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()) + } +} + pub 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 { |
