diff --git a/Cargo.lock b/Cargo.lock index 9593d7e5..a8c71541 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,6 +149,7 @@ dependencies = [ "rustix", "serde", "serde_json", + "signal-hook-registry", "tempfile", "walkdir", "widestring", @@ -899,6 +900,15 @@ dependencies = [ "digest", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "strsim" version = "0.11.1" diff --git a/Cargo.toml b/Cargo.toml index 679e9e4d..b29c90cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ serde_json = "^1.0" tempfile = "^3.13" widestring = "1.1.0" walkdir = "2.3.2" +signal-hook-registry = "1.4.2" [profile.release] # We assume we're being delivered via e.g. RPM which supports split debuginfo diff --git a/src/backend/statefile.rs b/src/backend/statefile.rs index 379c472c..02b4f5be 100644 --- a/src/backend/statefile.rs +++ b/src/backend/statefile.rs @@ -9,6 +9,25 @@ use std::fs::File; use std::io::prelude::*; use std::path::Path; +/// Suppress SIGTERM while active +// TODO: In theory we could record if we got SIGTERM and exit +// on drop, but in practice we don't care since we're going to exit anyways. +#[derive(Debug)] +struct SignalTerminationGuard(signal_hook_registry::SigId); + +impl SignalTerminationGuard { + pub(crate) fn new() -> Result { + let signal = unsafe { signal_hook_registry::register(libc::SIGTERM, || {})? }; + Ok(Self(signal)) + } +} + +impl Drop for SignalTerminationGuard { + fn drop(&mut self) { + signal_hook_registry::unregister(self.0); + } +} + impl SavedState { /// System-wide bootupd write lock (relative to sysroot). const WRITE_LOCK_PATH: &'static str = "run/bootupd-lock"; @@ -27,6 +46,7 @@ impl SavedState { lockfile.lock_exclusive()?; let guard = StateLockGuard { sysroot, + termguard: Some(SignalTerminationGuard::new()?), lockfile: Some(lockfile), }; Ok(guard) @@ -37,6 +57,7 @@ impl SavedState { pub(crate) fn unlocked(sysroot: openat::Dir) -> Result { Ok(StateLockGuard { sysroot, + termguard: None, lockfile: None, }) } @@ -91,6 +112,8 @@ impl SavedState { pub(crate) struct StateLockGuard { pub(crate) sysroot: openat::Dir, #[allow(dead_code)] + termguard: Option, + #[allow(dead_code)] lockfile: Option, }