Files
RedBear-OS/local/patches/base/P0-daemon-fix-init-notify-unwrap.patch
T
vasilito cee25393d8 fix: boot process improvements — dependency cycle, INIT_NOTIFY, probing loop, and log spam fixes
- Fix P15-8-init-cycle-detection.patch: replace visiting+error with seen+silent-skip
  to eliminate 11 false-positive 'dependency cycle detected' errors on shared deps
- Fix P0-daemon-fix-init-notify-unwrap.patch: remove eprintln! for missing
  INIT_NOTIFY (expected for oneshot_async services, ~7 daemons affected)
- Fix driver-manager hotplug loop: add PERMANENTLY_SKIPPED static set shared
  between hotplug handler and DriverConfig::probe() to stop infinite re-probing
  of Fatal/NotSupported/deferred-exhausted device+driver pairs (e.g. ided)
- Fix driver-manager log_timeline: suppress repeated EPIPE/ENOENT errors with
  AtomicI32 dedup and AtomicBool one-shot guards for boot timeline JSON
- Add driver-manager SIGTERM handler, ACPI bus registration, --status mode,
  driver reap loop, graceful shutdown, and reduced deferred retries (30→3)
2026-05-17 12:34:02 +03:00

102 lines
3.4 KiB
Diff

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,25 @@ 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<RawFd> {
+ let fd: RawFd = match std::env::var(var)
+ .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 +48,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<PipeWriter>,
}
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 +99,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<PipeWriter>,
}
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(())
}