aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs3
-rw-r--r--src/utils/signals.rs25
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 {