From: Ian Jackson Date: Sun, 25 Sep 2022 12:35:13 +0000 (+0100) Subject: daemon: wip X-Git-Tag: hippotat/1.0.0~64 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=28d5cc5657d742a696894506ae58df523fc154ab;p=hippotat.git daemon: wip Signed-off-by: Ian Jackson --- diff --git a/server/daemon.rs b/server/daemon.rs index 4294eda..05252e7 100644 --- a/server/daemon.rs +++ b/server/daemon.rs @@ -4,14 +4,19 @@ #![allow(unused_imports)] #![allow(dead_code)] +#![allow(unused_macros)] use std::io::IoSlice; +use std::os::unix::io::RawFd; use extend::ext; use nix::errno::*; +use nix::fcntl::*; use nix::unistd::*; +use nix::sys::stat::*; use nix::sys::uio::*; +use nix::sys::wait::*; pub struct Daemoniser { } @@ -33,11 +38,16 @@ macro_rules! crashv { { $( $m:expr ),* $(,)? } => { { crashv(&ms) } } } +macro_rules! cstr { { $b:tt } => { + CStr::from_bytes_with_nul(concat!($b b"\0")) + .unwrap_or_else(|| crashm("cstr not nul terminated?! bug!")) +} } + fn crash(m: &str) -> ! { crashv!(m) } -fn crashe(m: &str, en: Errno) -> ! { - crashv!(m, ": ", en.desc()) +fn crashe(m: &str, e: Errno) -> ! { + crashv!(m, ": ", e.desc()) } #[ext] @@ -45,31 +55,89 @@ impl nix::Result { fn context(self, m: &str) -> T { match self { Ok(y) => y, - Err(en) => crashe(m, en), + Err(e) => crashe(m, e), } } } -impl Daemoniser { +fn mdup2(oldfd: RawFd, newfd: RawFd, what: &str) { + match dup2(oldfd, newfd) { + Ok(got) if got == newfd => { }, + Ok(_) => crash("dup2 gave wrong return value"), + Err(e) => crashv!("dup2 ", what, ": ", e.desc()), + } +} /* +#[throws(&'static str)] +unsafe fn handle_child_status(child: Pid, report_pipe: RawFd, + wstatus: WaitStatus) -> ! { + let pid = wstatus.pid(); + + + + +impl Daemoniser { pub fn phase1() -> Self { unsafe { - let (st_read, st_write) = pipe().context("pipe"); + let null_fd = open(cstr!(b"/dev/null"), OFlag::O_RDWR, Mode::empty()) + .context("open /dev/null"); + mdup2(null_fd, 0); + + let (st_rfd, st_wfd) = pipe().context("pipe"); mstch fork().context("fork (1)") { - ForkResult::Parent { child } => { - let _ = close(st_write); - let mut buf = [0u8]; + ForkResult::Parent { child: _ } => { + close(st_write).context("close st_write pipe"); + let mut exitstatus = [0u8]; loop { - match read(st_read, &mut buf) { - Ok(0) => { - - - let r = + match read(st_read, &mut exitstatus) { + Ok(0) => crash("startup/daemonisation failed"), + Ok(1) => {}, + Err(e) if e == Errno::EINTR => continue, + Err(e) => crashe("read startup signal pipe", en); + } + } + libc::_exit(exitstatus); }, ForkResult::Child => { } + } + + close(st_read).context("close st_read pipe"); + + setsid().context("setsid"); + + match fork().context("fork (2)") { + ForkResult::Parent { child } => { + let wstatus = waitpid(child, None).context("waitpid startup"); + match wstatus.pid() { + Some(got) if got == child => { }, + Some(got) => crash("await child startup status: wrong pid"), + None => crash("await child startup status: no children?!"), + } + + match wstatus { + WaitStatus::Exited(_, estatus) => { + let estatus: u8 = estatus.try_into() + .map_err(|_| "exit status out of range!")?; + match write(report_pipe, &estatus) { + Ok(1) => libc::_exit(0), + Ok(_) => crash("write child startup exit status: short write"); + Err(e) => crashe("write child startup exit status", e); + }, + } + + WaitStatus::Signaled(pid, signal, coredump) => { + check_pid(pid); + crashv!("startup failed: died due to signal: ", signal.as_str(), + if coredump { " (core dumped)" } else { "" }); + }, + + _ => crashm("child startup exit status was strange!"); + + } } -*/ } + +*/