diag(base): trace fd transfer in init, daemon, and logd
Add diagnostics to pin down where the INIT_NOTIFY fd handoff hangs: - init/src/service.rs: log read_pipe fd and call_ro results - daemon/src/lib.rs: log cap_fd, write_pipe, and call_wo result - logd/src/main.rs: explicit ready_sync_scheme result and setrens fallback These are temporary diagnostics for the boot-hang investigation.
This commit is contained in:
+11
-3
@@ -106,12 +106,20 @@ impl SchemeDaemon {
|
||||
|
||||
/// 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(
|
||||
let raw_fd = cap_fd.into_raw();
|
||||
eprintln!(
|
||||
"daemon: ready_with_fd write_pipe={} cap_fd={}",
|
||||
self.write_pipe.as_raw_fd(),
|
||||
raw_fd
|
||||
);
|
||||
let res = syscall::call_wo(
|
||||
self.write_pipe.as_raw_fd() as usize,
|
||||
&cap_fd.into_raw().to_ne_bytes(),
|
||||
&raw_fd.to_ne_bytes(),
|
||||
syscall::CallFlags::FD,
|
||||
&[],
|
||||
)?;
|
||||
);
|
||||
eprintln!("daemon: ready_with_fd call_wo result={:?}", res);
|
||||
res?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
+43
-12
@@ -1,11 +1,11 @@
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::ffi::OsString;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::os::fd::{AsRawFd, FromRawFd, OwnedFd};
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::process::Command;
|
||||
use std::{env, io};
|
||||
use std::env;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
@@ -49,6 +49,8 @@ fn create_pipe() -> io::Result<(File, OwnedFd)> {
|
||||
|
||||
impl Service {
|
||||
pub fn spawn(&self, base_envs: &BTreeMap<String, OsString>) {
|
||||
eprintln!("init: service {} type={:?}", self.cmd, self.type_);
|
||||
let _ = io::stderr().flush();
|
||||
let mut command = Command::new(&self.cmd);
|
||||
command.args(self.args.iter().map(|arg| subst_env(arg)));
|
||||
command.env_clear();
|
||||
@@ -61,29 +63,52 @@ impl Service {
|
||||
|
||||
let (mut read_pipe, write_pipe) = create_pipe()
|
||||
.unwrap_or_else(|e| panic!("pipe() failed in service.spawn for {}: {}", self.cmd, e));
|
||||
eprintln!("init: {} pipe created read_pipe={}", self.cmd, read_pipe.as_raw_fd());
|
||||
let _ = io::stderr().flush();
|
||||
unsafe { pass_fd(&mut command, "INIT_NOTIFY", write_pipe.into()) };
|
||||
eprintln!("init: {} pass_fd done", self.cmd);
|
||||
let _ = io::stderr().flush();
|
||||
|
||||
let mut child = match command.spawn() {
|
||||
Ok(child) => child,
|
||||
Ok(child) => {
|
||||
eprintln!("init: {} spawned pid=??", self.cmd);
|
||||
let _ = io::stderr().flush();
|
||||
child
|
||||
},
|
||||
Err(err) => {
|
||||
status_fail(&format!("failed to execute {:?}: {}", command, err));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
eprintln!("init: {} entering match type={:?}", self.cmd, self.type_);
|
||||
let _ = io::stderr().flush();
|
||||
match &self.type_ {
|
||||
ServiceType::Notify => match read_pipe.read_exact(&mut [0]) {
|
||||
Ok(()) => {}
|
||||
Err(err) if err.kind() == io::ErrorKind::UnexpectedEof => {
|
||||
init_warn(&format!("{:?} exited without notifying readiness", command));
|
||||
ServiceType::Notify => {
|
||||
eprintln!("init: {} is Notify, waiting for byte", self.cmd);
|
||||
let _ = io::stderr().flush();
|
||||
match read_pipe.read_exact(&mut [0]) {
|
||||
Ok(()) => {}
|
||||
Err(err) if err.kind() == io::ErrorKind::UnexpectedEof => {
|
||||
init_warn(&format!("{:?} exited without notifying readiness", command));
|
||||
}
|
||||
Err(err) => {
|
||||
init_error(&format!("failed to wait for {:?}: {}", command, err));
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
init_error(&format!("failed to wait for {:?}: {}", command, err));
|
||||
}
|
||||
},
|
||||
}
|
||||
ServiceType::Scheme(scheme) => {
|
||||
eprintln!("init: SCHEME {} waiting for fd on read_pipe={}", self.cmd, read_pipe.as_raw_fd());
|
||||
let _ = io::stderr().flush();
|
||||
init_warn(&format!(
|
||||
"init: waiting for scheme fd from {:?}, read_pipe={}",
|
||||
command,
|
||||
read_pipe.as_raw_fd()
|
||||
));
|
||||
let mut new_fd = usize::MAX;
|
||||
loop {
|
||||
eprintln!("init: calling call_ro for {}", self.cmd);
|
||||
let _ = io::stderr().flush();
|
||||
match syscall::call_ro(
|
||||
read_pipe.as_raw_fd() as usize,
|
||||
unsafe { plain::as_mut_bytes(&mut new_fd) },
|
||||
@@ -97,7 +122,13 @@ impl Service {
|
||||
init_warn(&format!("{:?} exited without notifying readiness", command));
|
||||
return;
|
||||
}
|
||||
Ok(1) => break,
|
||||
Ok(1) => {
|
||||
init_warn(&format!(
|
||||
"init: received scheme fd {} from {:?}, registering as {}",
|
||||
new_fd, command, scheme
|
||||
));
|
||||
break;
|
||||
}
|
||||
Ok(n) => {
|
||||
init_error(&format!("incorrect amount of fds {} returned", n));
|
||||
return;
|
||||
|
||||
+8
-2
@@ -11,9 +11,15 @@ fn daemon(daemon: daemon::SchemeDaemon) -> ! {
|
||||
let mut scheme = LogScheme::new(&socket);
|
||||
let handler = Blocking::new(&socket, 16);
|
||||
|
||||
let _ = daemon.ready_sync_scheme(&socket, &mut scheme);
|
||||
match daemon.ready_sync_scheme(&socket, &mut scheme) {
|
||||
Ok(()) => eprintln!("logd: ready_sync_scheme succeeded"),
|
||||
Err(err) => eprintln!("logd: ready_sync_scheme failed: {err}"),
|
||||
}
|
||||
|
||||
libredox::call::setrens(0, 0).expect("logd: failed to enter null namespace");
|
||||
match libredox::call::setrens(0, 0) {
|
||||
Ok(_) => {}
|
||||
Err(err) => eprintln!("logd: warning: failed to enter null namespace: {err}"),
|
||||
}
|
||||
|
||||
handler
|
||||
.process_requests_blocking(scheme)
|
||||
|
||||
Reference in New Issue
Block a user