From 7d225602ecdd70e95d66d4e354dca040ae48872d Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Tue, 11 Aug 2026 06:43:59 +0000 Subject: [PATCH] Stop a failed log write from panicking a gateway task fips-gateway builds its subscriber the same way the daemon did, with the default internal-error reporting that sends a failed log write to `eprintln!`. Both shipped units set StandardOutput=journal and StandardError=journal, so one full disk fails both sinks together, which is the same precondition as on the daemon side. What dies here is a spawned task rather than a thread. The DNS resolver, the control accept loop and the pool tick are spawned and then not looked at again: their handles are first touched at shutdown, as `let _ = task.await`, which discards the JoinError. A task lost this way leaves the process running and reporting healthy with mesh name resolution or lease expiry and NAT cleanup stopped, and nothing recording that it stopped. Whether each task reaches a log site while the disk is full is not enumerated here; the resolver logs on exactly the error paths a full disk makes likely. --- src/bin/fips-gateway.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/bin/fips-gateway.rs b/src/bin/fips-gateway.rs index 7d8bc83..02bfbf0 100644 --- a/src/bin/fips-gateway.rs +++ b/src/bin/fips-gateway.rs @@ -67,7 +67,16 @@ async fn main() { ) .from_env_lossy(); - fmt().with_env_filter(filter).with_target(true).init(); + // As in the daemon: a failed log write must not panic whoever logged. The + // default reports write failures with `eprintln!`, which panics when stderr + // fails too, and both units send stdout and stderr to journald. Here the + // casualty is a spawned task — the DNS resolver or the pool tick — whose + // handle nothing observes until shutdown. + fmt() + .with_env_filter(filter) + .with_target(true) + .log_internal_errors(false) + .init(); info!("fips-gateway {} starting", version::short_version());