Skip to content

Commit

Permalink
Fix systemd stopping notif, vendor sd_notify
Browse files Browse the repository at this point in the history
  • Loading branch information
stephank committed Apr 22, 2024
1 parent caa7aaa commit 6062ab7
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 15 deletions.
7 changes: 0 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,6 @@ features = ["tokio-runtime"]
version = "2.1.1"
features = ["serde"]

[target.'cfg(unix)'.dependencies]
sd-notify = "0.4.0"

# Per `rsa` crate docs, significantly speeds up key generation for debug builds.
[profile.dev.package.num-bigint-dig]
opt-level = 3
10 changes: 5 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,9 @@ async fn start_server(builder: ConfigBuilder) {
let mut connections = JoinSet::new();

#[cfg(unix)]
sd_notify::notify(true, &[sd_notify::NotifyState::Ready])
.expect("Failed to signal ready to the service manager");
let sd_notify = utils::SdNotify::new();
#[cfg(unix)]
sd_notify.notify_ready();

// Snippet for the connection loop with graceful shutdown.
// This is shared between TCP and Unix socket code.
Expand Down Expand Up @@ -281,9 +282,8 @@ async fn start_server(builder: ConfigBuilder) {
}

#[cfg(unix)]
if let Err(err) = sd_notify::notify(true, &[sd_notify::NotifyState::Stopping]) {
log::error!("Failed to signal stopping to the service manager: {}", err);
}
sd_notify.notify_stopping();

while connections.join_next().await.is_some() {}
log::info!("Shutdown complete");
}
Expand Down
5 changes: 5 additions & 0 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,10 @@ pub use real_ip::*;
pub use rng::*;
pub use time::*;

#[cfg(unix)]
mod sd_notify;
#[cfg(unix)]
pub use sd_notify::*;

pub type BoxError = Box<dyn Error + Send + Sync>;
pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
41 changes: 41 additions & 0 deletions src/utils/sd_notify.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use std::{env, ffi::OsString, io, os::unix::net::UnixDatagram};

// Sends state notifications to systemd.
//
// Based on https://github.com/lnicola/sd-notify (MIT/Apache-2.0)
pub struct SdNotify {
path: Option<OsString>,
}

impl SdNotify {
pub fn new() -> Self {
let path = env::var_os("NOTIFY_SOCKET");
env::remove_var("NOTIFY_SOCKET");
Self { path }
}

pub fn notify_ready(&self) {
self.send(b"READY=1\n")
.expect("Failed to signal ready to the service manager");
}

pub fn notify_stopping(&self) {
if let Err(err) = self.send(b"STOPPING=1\n") {
log::error!("Failed to signal stopping to the service manager: {err}");
}
}

fn send(&self, msg: &[u8]) -> io::Result<()> {
let Some(path) = self.path.as_ref() else {
return Ok(());
};

let sock = UnixDatagram::unbound()?;
let len = sock.send_to(msg, path)?;
if len != msg.len() {
return Err(io::Error::new(io::ErrorKind::WriteZero, "incomplete write"));
}

Ok(())
}
}

0 comments on commit 6062ab7

Please sign in to comment.