Commit 8ae66f06204a
tarball2 files changed+60-0
@@ -22,6 +22,7 @@ mod pacing;
2222
mod power;2323
mod scene;2424
mod seat;25
+mod signals;2526
mod state;2627
mod stats;2728
mod toplevels;@@ -269,6 +270,7 @@ fn run(
269270
None => nested::init(&mut event_loop, &mut state)?,270271
}271272
ipc::init(&event_loop, &mut state)?;273
+ signals::init(&event_loop)?;272274
xwayland::init(&mut state);273275
state.configure_idle();274276
tracing::info!(socket = ?state.core.socket_name, device = state.renderer.device_name(), "monolith running");@@ -0,0 +1,58 @@
1
+//! SIGINT and SIGTERM stop the event loop like `msg quit`, so the socket and2
+//! the X11 lock file are cleaned up when a session manager logs us out.3
+4
+use crate::state::State;5
+use smithay::reexports::calloop::generic::Generic;6
+use smithay::reexports::calloop::{EventLoop, Interest, Mode, PostAction};7
+use std::io::{ErrorKind, Read};8
+use std::os::fd::IntoRawFd;9
+use std::os::unix::net::UnixStream;10
+use std::sync::atomic::{AtomicI32, Ordering};11
+12
+const STOPPING: [libc::c_int; 2] = [libc::SIGINT, libc::SIGTERM];13
+14
+static WAKE: AtomicI32 = AtomicI32::new(-1);15
+16
+extern "C" fn on_signal(sig: libc::c_int) {17
+ let byte = sig as u8;18
+ // SAFETY: write is async-signal-safe and the buffer is a live local.19
+ unsafe { libc::write(WAKE.load(Ordering::Relaxed), (&raw const byte).cast(), 1) };20
+}21
+22
+pub fn init(event_loop: &EventLoop<'static, State>) -> std::io::Result<()> {23
+ let (wake, read) = UnixStream::pair()?;24
+ read.set_nonblocking(true)?;25
+ wake.set_nonblocking(true)?;26
+ WAKE.store(wake.into_raw_fd(), Ordering::Relaxed);27
+ // SAFETY: the handler only calls write, and the set is a plain local.28
+ unsafe {29
+ let mut set: libc::sigset_t = std::mem::zeroed();30
+ libc::sigemptyset(&mut set);31
+ for sig in STOPPING {32
+ libc::signal(sig, on_signal as *const () as libc::sighandler_t);33
+ libc::sigaddset(&mut set, sig);34
+ }35
+ libc::pthread_sigmask(libc::SIG_UNBLOCK, &set, std::ptr::null_mut());36
+ }37
+ event_loop38
+ .handle()39
+ .insert_source(40
+ Generic::new(read, Interest::READ, Mode::Level),41
+ |_, read, state| {42
+ let mut buf = [0u8; 16];43
+ loop {44
+ match (&**read).read(&mut buf) {45
+ Ok(0) => return Ok(PostAction::Remove),46
+ Ok(_) => {}47
+ Err(e) if e.kind() == ErrorKind::WouldBlock => break,48
+ Err(e) => return Err(e),49
+ }50
+ }51
+ tracing::info!("stop signal received");52
+ state.core.signal.stop();53
+ Ok(PostAction::Continue)54
+ },55
+ )56
+ .map_err(|e| std::io::Error::other(e.to_string()))?;57
+ Ok(())58
+}