diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs index 9f507221..c69c2cfa 100644 --- a/daemon/src/lib.rs +++ b/daemon/src/lib.rs @@ -10,15 +10,26 @@ use libredox::Fd; use redox_scheme::Socket; use redox_scheme::scheme::{SchemeAsync, SchemeSync}; -unsafe fn get_fd(var: &str) -> RawFd { - let fd: RawFd = std::env::var(var).unwrap().parse().unwrap(); +unsafe fn get_fd(var: &str) -> Option { + 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 None, + }; if unsafe { libc::fcntl(fd, libc::F_SETFD, libc::FD_CLOEXEC) } == -1 { - panic!( + eprintln!( "daemon: failed to set CLOEXEC flag for {var} fd: {}", io::Error::last_os_error() ); + return None; } - fd + Some(fd) } unsafe fn pass_fd(cmd: &mut Command, env: &str, fd: OwnedFd) { @@ -38,20 +49,26 @@ 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(|fd| io::PipeWriter::from_raw_fd(fd)) }; f(Daemon { write_pipe }) } /// Notify the process that the daemon is ready to accept requests. pub fn ready(mut self) { - self.write_pipe.write_all(&[0]).unwrap(); + if let Some(write_pipe) = self.write_pipe.as_mut() { + if let Err(err) = write_pipe.write_all(&[0]) { + if err.kind() != io::ErrorKind::BrokenPipe { + eprintln!("daemon::ready write failed: {err}"); + } + } + } } /// Executes `Command` as a child process. @@ -83,25 +100,28 @@ 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(|fd| io::PipeWriter::from_raw_fd(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, - &[], - )?; + let cap_raw = cap_fd.into_raw(); + if let Some(write_pipe) = self.write_pipe { + syscall::call_wo( + write_pipe.as_raw_fd() as usize, + &cap_raw.to_ne_bytes(), + syscall::CallFlags::FD, + &[], + )?; + } Ok(()) }