Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
node: Properly reap git-daemon process
Alexis Sellier committed 3 years ago
commit 488f043226678111449f379741aed730316930ec
parent e1986e45701972d4630284f095aec6c6bf4178ac
3 files changed +20 -1
modified Cargo.lock
@@ -1991,6 +1991,7 @@ dependencies = [
 "git-ref-format",
 "io-reactor",
 "lexopt",
+
 "libc",
 "localtime",
 "log",
 "netservices",
modified radicle-node/Cargo.toml
@@ -20,6 +20,7 @@ cyphernet = { version = "0.1.0", features = ["tor", "dns", "ed25519", "p2p-ed255
fastrand = { version = "1.8.0" }
git-ref-format = { version = "0", features = ["serde", "macro"] }
lexopt = { version = "0.2.1" }
+
libc = { version = "0.2.137" }
log = { version = "0.4.17", features = ["std"] }
localtime = { version = "1" }
netservices = { version = "0.1.0", features = ["io-reactor", "socket2"] }
modified radicle-node/src/runtime.rs
@@ -218,7 +218,7 @@ impl<G: Signer + EcSign + 'static> Runtime<G> {
        self.reactor.join().unwrap();
        control.join().unwrap()?;

-
        daemon.kill().ok(); // Ignore error if daemon has already exited, for whatever reason.
+
        daemon::kill(&daemon).ok(); // Ignore error if daemon has already exited, for whatever reason.
        daemon.wait()?;

        fs::remove_file(home.socket()).ok();
@@ -234,6 +234,20 @@ pub mod daemon {
    use std::process::{Child, Command, Stdio};
    use std::{env, io, net};

+
    /// Kill the daemon process.
+
    pub fn kill(child: &Child) -> io::Result<()> {
+
        // SAFETY: We use `libc::kill` because `Child::kill` always sends a `SIGKILL` and that doesn't
+
        // work for us. We need to send a `SIGTERM` to fully reap the child process. This is because
+
        // `git-daemon` spawns its own children, and isn't able to reap them if it receives
+
        // a `SIGKILL`.
+
        let result = unsafe { libc::kill(child.id() as libc::c_int, libc::SIGTERM) };
+
        match result {
+
            0 => Ok(()),
+
            _ => Err(io::Error::last_os_error()),
+
        }
+
    }
+

+
    /// Spawn the daemon process.
    pub fn spawn(storage: &Path, addr: net::SocketAddr) -> io::Result<Child> {
        let storage = storage.canonicalize()?;
        let listen = format!("--listen={}", addr.ip());
@@ -247,6 +261,9 @@ pub mod daemon {
            .arg("daemon")
            // Make all git directories available.
            .arg("--export-all")
+
            .arg("--reuseaddr")
+
            .arg("--max-connections=32")
+
            .arg("--informative-errors")
            .arg("--verbose")
            // The git "root". Should be our storage path.
            .arg("--base-path=.")