diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs --- a/daemon/src/lib.rs +++ b/daemon/src/lib.rs @@ -10,26 +10,35 @@ use libredox::Fd; use redox_scheme::scheme::{SchemeAsync, SchemeSync}; use redox_scheme::Socket; -unsafe fn get_fd(var: &str) -> RawFd { - let fd: RawFd = match std::env::var(var) - .map_err(|e| eprintln!("daemon: env var {var} not set: {e}")) - .ok() - .and_then(|val| { - val.parse() - .map_err(|e| eprintln!("daemon: failed to parse {var} as fd: {e}")) - .ok() - }) { - Some(fd) => fd, - None => return -1, +unsafe fn get_fd(var: &str) -> Option { + let value = match std::env::var(var) { + Ok(value) => value, + Err(_) => { + let exe = std::env::args() + .next() + .unwrap_or_else(|| "daemon".to_string()); + eprintln!("daemon: {var} not set for {exe}; readiness notification disabled"); + return None; + } + }; + let fd: RawFd = match value.parse() { + Ok(fd) => fd, + Err(err) => { + let exe = std::env::args() + .next() + .unwrap_or_else(|| "daemon".to_string()); + eprintln!("daemon: invalid {var} value {value:?} for {exe}: {err}; readiness notification disabled"); + return None; + } }; if unsafe { libc::fcntl(fd, libc::F_SETFD, libc::FD_CLOEXEC) } == -1 { eprintln!( "daemon: failed to set CLOEXEC flag for {var} fd: {}", io::Error::last_os_error() ); - return -1; + return None; } - fd + Some(fd) } unsafe fn pass_fd(cmd: &mut Command, env: &str, fd: OwnedFd) { @@ -47,22 +56,20 @@ unsafe fn pass_fd(cmd: &mut Command, env: &str, fd: OwnedFd) { /// A long running background process that handles requests. #[must_use = "Daemon::ready must be called"] pub struct Daemon { - write_pipe: PipeWriter, + write_pipe: Option, } impl Daemon { /// Create a new daemon. pub fn new(f: impl FnOnce(Daemon) -> !) -> ! { - let write_pipe = unsafe { io::PipeWriter::from_raw_fd(get_fd("INIT_NOTIFY")) }; + let write_pipe = unsafe { get_fd("INIT_NOTIFY").map(io::PipeWriter::from_raw_fd) }; f(Daemon { write_pipe }) } /// Notify the process that the daemon is ready to accept requests. pub fn ready(mut self) { - if let Err(err) = self.write_pipe.write_all(&[0]) { - if err.kind() != io::ErrorKind::BrokenPipe { - eprintln!("daemon::ready write failed: {err}"); - } + if let Some(write_pipe) = self.write_pipe.as_mut() { + write_pipe.write_all(&[0]).unwrap(); } } @@ -87,24 +94,26 @@ impl Daemon { /// A long running background process that handles requests using schemes. #[must_use = "SchemeDaemon::ready must be called"] pub struct SchemeDaemon { - write_pipe: PipeWriter, + write_pipe: Option, } impl SchemeDaemon { /// Create a new daemon for use with schemes. pub fn new(f: impl FnOnce(SchemeDaemon) -> !) -> ! { - let write_pipe = unsafe { io::PipeWriter::from_raw_fd(get_fd("INIT_NOTIFY")) }; + let write_pipe = unsafe { get_fd("INIT_NOTIFY").map(io::PipeWriter::from_raw_fd) }; f(SchemeDaemon { write_pipe }) } /// Notify the process that the scheme daemon is ready to accept requests. pub fn ready_with_fd(self, cap_fd: Fd) -> syscall::Result<()> { - syscall::call_wo( - self.write_pipe.as_raw_fd() as usize, - &cap_fd.into_raw().to_ne_bytes(), - syscall::CallFlags::FD, - &[], - )?; + if let Some(write_pipe) = self.write_pipe { + syscall::call_wo( + write_pipe.as_raw_fd() as usize, + &cap_fd.into_raw().to_ne_bytes(), + syscall::CallFlags::FD, + &[], + )?; + } Ok(()) }