node: remove git-daemon code

The git-daemon code is no longer needed since git-upload-pack is used
in its place.

Remove the git-daemon code from the runtime and worker.

Signed-off-by: Fintan Halpenny <fintan.halpenny@gmail.com>
X-Clacks-Overhead: GNU Terry Pratchett
This commit is contained in:
Fintan Halpenny 2023-08-22 13:24:27 +01:00 committed by cloudhead
parent ea7f26dbdf
commit d7abc0a8fc
No known key found for this signature in database
4 changed files with 2 additions and 108 deletions

View File

@ -26,7 +26,6 @@ Usage
Options
--config <path> Config file to use (default ~/.radicle/config.json)
--git-daemon <address> Address to bind git-daemon to (default 0.0.0.0:9418)
--force Force start even if an existing control socket is found
--listen <address> Address to listen on
--version Print program version
@ -35,7 +34,6 @@ Options
#[derive(Debug)]
struct Options {
daemon: Option<net::SocketAddr>,
config: Option<PathBuf>,
listen: Vec<net::SocketAddr>,
force: bool,
@ -47,7 +45,6 @@ impl Options {
let mut parser = lexopt::Parser::from_env();
let mut listen = Vec::new();
let mut daemon = None;
let mut config = None;
let mut force = false;
@ -56,10 +53,6 @@ impl Options {
Long("force") => {
force = true;
}
Long("git-daemon") => {
let addr = parser.value()?.parse()?;
daemon = Some(addr);
}
Long("config") => {
let value = parser.value()?;
let path = PathBuf::from(value);
@ -82,7 +75,6 @@ impl Options {
}
Ok(Self {
daemon,
force,
listen,
config,
@ -109,9 +101,6 @@ fn execute() -> anyhow::Result<()> {
let config = options.config.unwrap_or_else(|| home.config());
let config = profile::Config::load(&config)?.node;
let proxy = net::SocketAddr::new(net::Ipv4Addr::LOCALHOST.into(), 9050);
let daemon = options.daemon.unwrap_or_else(|| {
net::SocketAddr::new(net::Ipv4Addr::LOCALHOST.into(), radicle::git::PROTOCOL_PORT)
});
let listen: Vec<std::net::SocketAddr> = if !options.listen.is_empty() {
options.listen.clone()
} else {
@ -125,7 +114,7 @@ fn execute() -> anyhow::Result<()> {
log::debug!(target: "node", "Removing existing control socket..");
fs::remove_file(home.socket()).ok();
}
Runtime::init(home, config, listen, proxy, daemon, signals, signer)?.run()?;
Runtime::init(home, config, listen, proxy, signals, signer)?.run()?;
Ok(())
}

View File

@ -1,7 +1,6 @@
pub mod handle;
pub mod thread;
use std::io::{BufRead, BufReader};
use std::os::unix::net::UnixListener;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
@ -108,7 +107,6 @@ pub struct Runtime {
pub handle: Handle,
pub storage: Storage,
pub reactor: Reactor<wire::Control, popol::Poller>,
pub daemon: net::SocketAddr,
pub pool: worker::Pool,
pub local_addrs: Vec<net::SocketAddr>,
pub signals: chan::Receiver<()>,
@ -123,7 +121,6 @@ impl Runtime {
config: service::Config,
listen: Vec<net::SocketAddr>,
proxy: net::SocketAddr,
daemon: net::SocketAddr,
signals: chan::Receiver<()>,
signer: G,
) -> Result<Runtime, Error>
@ -255,7 +252,6 @@ impl Runtime {
capacity: 8,
timeout: time::Duration::from_secs(9),
storage: storage.clone(),
daemon,
fetch,
},
);
@ -275,7 +271,6 @@ impl Runtime {
control,
storage,
reactor,
daemon,
handle,
pool,
signals,
@ -300,28 +295,9 @@ impl Runtime {
}
});
log::info!(target: "node", "Spawning git daemon at {}..", self.storage.path().display());
let mut daemon = daemon::spawn(self.storage.path(), self.daemon)?;
thread::spawn(&self.id, "daemon", {
let stderr = daemon.stderr.take().unwrap();
|| {
for line in BufReader::new(stderr).lines().flatten() {
if line.starts_with("fatal") {
log::error!(target: "daemon", "{line}");
} else {
log::debug!(target: "daemon", "{line}");
}
}
}
});
self.pool.run().unwrap();
self.reactor.join().unwrap();
daemon::kill(&daemon).ok(); // Ignore error if daemon has already exited, for whatever reason.
daemon.wait()?;
// Nb. We don't join the control thread here, as we have no way of notifying it that the
// node is shutting down.
@ -333,62 +309,3 @@ impl Runtime {
Ok(())
}
}
pub mod daemon {
use std::path::Path;
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());
let port = format!("--port={}", addr.port());
let child = Command::new("git")
.env_clear()
.envs(env::vars().filter(|(k, _)| k == "PATH" || k.starts_with("GIT")))
.envs(radicle::git::env::GIT_DEFAULT_CONFIG)
.env("GIT_PROTOCOL", "version=2")
.current_dir(storage)
// Send a keep-alive packet every 3 seconds to make sure the client doesn't
// timeout during pack building.
.args(["-c", "uploadpack.keepAlive=3"])
.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=.")
// Timeout (in seconds) between the moment the connection is established
// and the client request is received (typically a rather low value,
// since that should be basically immediate).
.arg("--init-timeout=3")
// Timeout (in seconds) for specific client sub-requests.
// This includes the time it takes for the server to process the sub-request
// and the time spent waiting for the next clients request.
.arg("--timeout=9")
.arg("--log-destination=stderr")
.arg(listen)
.arg(port)
.stderr(Stdio::piped())
.spawn()?;
Ok(child)
}
}

View File

@ -353,20 +353,12 @@ impl<G: cyphernet::Ecdh<Pk = NodeId> + Signer + Clone> Node<G> {
pub fn spawn(self) -> NodeHandle<G> {
let listen = vec![([0, 0, 0, 0], 0).into()];
let proxy = net::SocketAddr::new(net::Ipv4Addr::LOCALHOST.into(), 9050);
let daemon: net::SocketAddr = {
// Find free port for git-daemon to bind to.
// This is a somewhat racy solution, though it works much better than assigning a random
// port.
let sock = net::TcpListener::bind("0.0.0.0:0").unwrap();
([0, 0, 0, 0], sock.local_addr().unwrap().port()).into()
};
let (_, signals) = chan::bounded(1);
let rt = Runtime::init(
self.home.clone(),
self.config,
listen,
proxy,
daemon,
signals,
self.signer.clone(),
)

View File

@ -5,7 +5,7 @@ mod upload_pack;
pub mod fetch;
use std::path::PathBuf;
use std::{io, net, time};
use std::{io, time};
use crossbeam_channel as chan;
@ -27,8 +27,6 @@ pub struct Config {
pub capacity: usize,
/// Timeout for all operations.
pub timeout: time::Duration,
/// Git daemon address.
pub daemon: net::SocketAddr,
/// Git storage.
pub storage: Storage,
/// Configuration for performing fetched.
@ -66,8 +64,6 @@ impl FetchError {
/// Error returned by fetch responder.
#[derive(thiserror::Error, Debug)]
pub enum UploadError {
#[error("worker failed to connect to git daemon: {0}")]
DaemonConnectionFailed(io::Error),
#[error("error parsing git command packet-line: {0}")]
PacketLine(io::Error),
#[error(transparent)]