dw-i2c: deliver scheme capability fd to init in endpoint::serve (fix boot hang)
endpoint::serve used register_sync_scheme, which registers the scheme to
the daemon's own namespace but never returns the capability fd to init.
For type={scheme} services init blocks in call_ro(FD) waiting for that
fd, so the boot deadlocked right after 'Started Intel LPSS I2C
controller' (CPU halted, init asleep) — the ptyd-class bug.
Replace register_sync_scheme with an explicit capability-fd creation +
notify_init_scheme_fd() that writes the fd to the INIT_NOTIFY pipe
(same mechanism as SchemeDaemon::ready_with_fd / ready_sync_scheme,
which i2cd, ucsid, and ptyd already use). init then registers
/scheme/<name> and the boot proceeds.
Affects intel-lpss-i2cd and dw-acpi-i2cd, both type={scheme} services
using this endpoint.
This commit is contained in:
@@ -595,7 +595,7 @@ pub mod endpoint {
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use i2c_interface::{I2cTransferRequest, I2cTransferResponse, I2cTransferStatus};
|
||||
use redox_scheme::scheme::{register_sync_scheme, SchemeSync};
|
||||
use redox_scheme::scheme::SchemeSync;
|
||||
use redox_scheme::{CallerCtx, OpenResult, Socket};
|
||||
use scheme_utils::{Blocking, HandleMap};
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
@@ -861,8 +861,17 @@ pub mod endpoint {
|
||||
handles: HandleMap::new(),
|
||||
controllers,
|
||||
};
|
||||
register_sync_scheme(&socket, scheme_name, &mut endpoint)
|
||||
.with_context(|| format!("failed to register {scheme_name} scheme"))?;
|
||||
|
||||
// type={scheme} handshake: deliver the capability fd to init over
|
||||
// INIT_NOTIFY so init registers /scheme/<name> and returns from
|
||||
// call_ro(FD). register_sync_scheme alone deadlocks init (ptyd-class).
|
||||
let cap_id = endpoint
|
||||
.scheme_root()
|
||||
.context("failed to compute scheme root")?;
|
||||
let cap_fd = socket
|
||||
.create_this_scheme_fd(0, cap_id, 0, 0)
|
||||
.context("failed to create scheme capability fd")?;
|
||||
notify_init_scheme_fd(cap_fd).context("failed to deliver scheme fd to init")?;
|
||||
|
||||
log::info!(
|
||||
"dw-i2c: serving /scheme/{scheme_name} with {} controller(s)",
|
||||
@@ -882,6 +891,16 @@ pub mod endpoint {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn notify_init_scheme_fd(cap_fd: usize) -> Result<()> {
|
||||
let pipe_fd: usize = std::env::var("INIT_NOTIFY")
|
||||
.context("INIT_NOTIFY is not set")?
|
||||
.parse()
|
||||
.context("INIT_NOTIFY is not a valid fd")?;
|
||||
syscall::call_wo(pipe_fd, &cap_fd.to_ne_bytes(), syscall::CallFlags::FD, &[])
|
||||
.context("failed to write scheme fd to the INIT_NOTIFY pipe")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user