node: Properly reap git-daemon process

This commit is contained in:
Alexis Sellier 2023-02-09 17:42:50 +01:00
parent e1986e4570
commit 488f043226
No known key found for this signature in database
3 changed files with 20 additions and 1 deletions

1
Cargo.lock generated
View File

@ -1991,6 +1991,7 @@ dependencies = [
"git-ref-format", "git-ref-format",
"io-reactor", "io-reactor",
"lexopt", "lexopt",
"libc",
"localtime", "localtime",
"log", "log",
"netservices", "netservices",

View File

@ -20,6 +20,7 @@ cyphernet = { version = "0.1.0", features = ["tor", "dns", "ed25519", "p2p-ed255
fastrand = { version = "1.8.0" } fastrand = { version = "1.8.0" }
git-ref-format = { version = "0", features = ["serde", "macro"] } git-ref-format = { version = "0", features = ["serde", "macro"] }
lexopt = { version = "0.2.1" } lexopt = { version = "0.2.1" }
libc = { version = "0.2.137" }
log = { version = "0.4.17", features = ["std"] } log = { version = "0.4.17", features = ["std"] }
localtime = { version = "1" } localtime = { version = "1" }
netservices = { version = "0.1.0", features = ["io-reactor", "socket2"] } netservices = { version = "0.1.0", features = ["io-reactor", "socket2"] }

View File

@ -218,7 +218,7 @@ impl<G: Signer + EcSign + 'static> Runtime<G> {
self.reactor.join().unwrap(); self.reactor.join().unwrap();
control.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()?; daemon.wait()?;
fs::remove_file(home.socket()).ok(); fs::remove_file(home.socket()).ok();
@ -234,6 +234,20 @@ pub mod daemon {
use std::process::{Child, Command, Stdio}; use std::process::{Child, Command, Stdio};
use std::{env, io, net}; 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> { pub fn spawn(storage: &Path, addr: net::SocketAddr) -> io::Result<Child> {
let storage = storage.canonicalize()?; let storage = storage.canonicalize()?;
let listen = format!("--listen={}", addr.ip()); let listen = format!("--listen={}", addr.ip());
@ -247,6 +261,9 @@ pub mod daemon {
.arg("daemon") .arg("daemon")
// Make all git directories available. // Make all git directories available.
.arg("--export-all") .arg("--export-all")
.arg("--reuseaddr")
.arg("--max-connections=32")
.arg("--informative-errors")
.arg("--verbose") .arg("--verbose")
// The git "root". Should be our storage path. // The git "root". Should be our storage path.
.arg("--base-path=.") .arg("--base-path=.")