From 34342e110f8eb731289f72a1d2c4bf8c990a3228 Mon Sep 17 00:00:00 2001 From: reverse Date: Sun, 23 Aug 2026 02:17:44 +0000 Subject: [PATCH] rehash: write the pidfile only when configured + CLI verifies a live echoircd, so a stale/clobbered pid can't misfire --- src/main.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main.rs b/src/main.rs index 84fce2f..b6ba6e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -38,18 +38,21 @@ fn rehash_cli(cfgpath: &str) -> i32 { return 1; } }; - if pid.parse::().is_err() { - eprintln!("echoircd: bad pidfile {pidfile} (contents: {pid:?})"); + // Verify the pid is a live echoircd — guards a stale pidfile or a reused pid. + let comm = std::fs::read_to_string(format!("/proc/{pid}/comm")).unwrap_or_default(); + if pid.parse::().is_err() || comm.trim() != "echoircd" { + eprintln!("echoircd: no running echoircd for pid {pid} (stale {pidfile}?) — start the server first."); return 1; } println!("rehashing server config file."); let sent = std::process::Command::new("kill") .args(["-s", "HUP", &pid]) + .stderr(std::process::Stdio::null()) .status() .map(|st| st.success()) .unwrap_or(false); if !sent { - eprintln!("echoircd: could not signal pid {pid} — is the server running?"); + eprintln!("echoircd: could not signal pid {pid}."); return 1; } println!("server configuration is reloaded."); @@ -102,15 +105,13 @@ fn main() { std::process::exit(1); } - // Write a pidfile (default echoircd.pid) so `echoircd rehash` can find us. - let pidfile = cfg - .raw - .get("pidfile") - .and_then(|v| v.first()) - .cloned() - .unwrap_or_else(|| "echoircd.pid".to_string()); - if let Err(e) = std::fs::write(&pidfile, format!("{}\n", std::process::id())) { - eprintln!("echoircd: could not write pidfile {pidfile}: {e}"); + // Write a pidfile only when `pidfile` is configured, so throwaway instances in + // the same directory (e.g. the integration-test harness) can't clobber a real + // server's pidfile and leave `echoircd rehash` pointing at a dead process. + if let Some(pidfile) = cfg.raw.get("pidfile").and_then(|v| v.first()).filter(|p| !p.is_empty()) { + if let Err(e) = std::fs::write(pidfile, format!("{}\n", std::process::id())) { + eprintln!("echoircd: could not write pidfile {pidfile}: {e}"); + } } // global queue limits (per-class overrides layer on top of these in the reactor)