diff options
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/atuin-client/config.toml | 5 | ||||
| -rw-r--r-- | crates/atuin-client/src/settings.rs | 5 | ||||
| -rw-r--r-- | crates/atuin-daemon/Cargo.toml | 3 | ||||
| -rw-r--r-- | crates/atuin-daemon/src/server.rs | 55 |
4 files changed, 61 insertions, 7 deletions
diff --git a/crates/atuin-client/config.toml b/crates/atuin-client/config.toml index 49e06c45..4938991a 100644 --- a/crates/atuin-client/config.toml +++ b/crates/atuin-client/config.toml @@ -223,5 +223,10 @@ records = true ## windows: Not Supported # socket_path = "~/.local/share/atuin/atuin.sock" +## Use systemd socket activation rather than opening the given path (the path must still be correct for the client) +## linux: false +## mac/windows: Not Supported +# systemd_socket = false + ## The port that should be used for TCP on non unix systems # tcp_port = 8889 diff --git a/crates/atuin-client/src/settings.rs b/crates/atuin-client/src/settings.rs index a97d05eb..f4434e41 100644 --- a/crates/atuin-client/src/settings.rs +++ b/crates/atuin-client/src/settings.rs @@ -350,6 +350,9 @@ pub struct Daemon { /// The path to the unix socket used by the daemon pub socket_path: String, + /// Use a socket passed via systemd's socket activation protocol, instead of the path + pub systemd_socket: bool, + /// The port that should be used for TCP on non unix systems pub tcp_port: u64, } @@ -368,6 +371,7 @@ impl Default for Daemon { enabled: false, sync_frequency: 300, socket_path: "".to_string(), + systemd_socket: false, tcp_port: 8889, } } @@ -715,6 +719,7 @@ impl Settings { .set_default("daemon.sync_frequency", 300)? .set_default("daemon.enabled", false)? .set_default("daemon.socket_path", socket_path.to_str())? + .set_default("daemon.systemd_socket", false)? .set_default("daemon.tcp_port", 8889)? .set_default( "prefers_reduced_motion", diff --git a/crates/atuin-daemon/Cargo.toml b/crates/atuin-daemon/Cargo.toml index 390cb28f..e4c4779b 100644 --- a/crates/atuin-daemon/Cargo.toml +++ b/crates/atuin-daemon/Cargo.toml @@ -32,5 +32,8 @@ prost-types = "0.12" tokio-stream = {version="0.1.14", features=["net"]} rand.workspace = true +[target.'cfg(target_os = "linux")'.dependencies] +listenfd = "1.0.1" + [build-dependencies] tonic-build = "0.11" diff --git a/crates/atuin-daemon/src/server.rs b/crates/atuin-daemon/src/server.rs index 77824f60..1cfcef51 100644 --- a/crates/atuin-daemon/src/server.rs +++ b/crates/atuin-daemon/src/server.rs @@ -133,7 +133,7 @@ impl HistorySvc for HistoryService { } #[cfg(unix)] -async fn shutdown_signal(socket: PathBuf) { +async fn shutdown_signal(socket: Option<PathBuf>) { let mut term = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) .expect("failed to register sigterm handler"); let mut int = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::interrupt()) @@ -145,7 +145,9 @@ async fn shutdown_signal(socket: PathBuf) { } eprintln!("Removing socket..."); - std::fs::remove_file(socket).expect("failed to remove socket"); + if let Some(socket) = socket { + std::fs::remove_file(socket).expect("failed to remove socket"); + } eprintln!("Shutting down..."); } @@ -163,15 +165,54 @@ async fn start_server(settings: Settings, history: HistoryService) -> Result<()> use tokio::net::UnixListener; use tokio_stream::wrappers::UnixListenerStream; - let socket = settings.daemon.socket_path.clone(); + let socket_path = settings.daemon.socket_path; - let uds = UnixListener::bind(socket.clone())?; - let uds_stream = UnixListenerStream::new(uds); + let (uds, cleanup) = if cfg!(target_os = "linux") && settings.daemon.systemd_socket { + #[cfg(target_os = "linux")] + { + use eyre::OptionExt; + tracing::info!("getting systemd socket"); + let listener = listenfd::ListenFd::from_env() + .take_unix_listener(0)? + .ok_or_eyre("missing systemd socket")?; + listener.set_nonblocking(true)?; + let actual_path = listener + .local_addr() + .context("getting systemd socket's path") + .and_then(|addr| { + addr.as_pathname() + .ok_or_eyre("systemd socket missing path") + .map(|path| path.to_owned()) + }); + match actual_path { + Ok(actual_path) => { + tracing::info!("listening on systemd socket: {actual_path:?}"); + if actual_path != std::path::Path::new(&socket_path) { + tracing::warn!( + "systemd socket is not at configured client path: {socket_path:?}" + ); + } + } + Err(err) => { + tracing::warn!("could not detect systemd socket path, ensure that it's at the configured path: {socket_path:?}, error: {err:?}"); + } + } + (UnixListener::from_std(listener)?, false) + } + #[cfg(not(target_os = "linux"))] + unreachable!() + } else { + tracing::info!("listening on unix socket {socket_path:?}"); + (UnixListener::bind(socket_path.clone())?, true) + }; - tracing::info!("listening on unix socket {:?}", socket); + let uds_stream = UnixListenerStream::new(uds); Server::builder() .add_service(HistoryServer::new(history)) - .serve_with_incoming_shutdown(uds_stream, shutdown_signal(socket.into())) + .serve_with_incoming_shutdown( + uds_stream, + shutdown_signal(cleanup.then_some(socket_path.into())), + ) .await?; Ok(()) } |
