Fix pcid crash: pass valid INIT_NOTIFY pipe from hwd
The previous fire-and-forget fix passed hwd's own INIT_NOTIFY fd to pcid, but that fd had CLOEXEC set (by daemon::Daemon::new), so pcid inherited a closed fd and panicked in PipeWriter::from_raw_fd. Fix: create a new pipe in hwd before spawning pcid. Pass the write end as INIT_NOTIFY with CLOEXEC cleared (via pre_exec). Drop the read end immediately — pcid's daemon.ready() will get EPIPE, which is silently ignored by the daemon library. This gives pcid a valid fd while still being fully non-blocking from hwd's perspective.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/Cargo.lock b/Cargo.lock
|
diff --git a/Cargo.lock b/Cargo.lock
|
||||||
index 9fcbd662..760fd8b4 100644
|
index 9fcbd662..6aa362f6 100644
|
||||||
--- a/Cargo.lock
|
--- a/Cargo.lock
|
||||||
+++ b/Cargo.lock
|
+++ b/Cargo.lock
|
||||||
@@ -31,11 +31,20 @@ dependencies = [
|
@@ -31,11 +31,20 @@ dependencies = [
|
||||||
@@ -109,7 +109,13 @@ index 9fcbd662..760fd8b4 100644
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpt"
|
name = "gpt"
|
||||||
version = "3.1.0"
|
version = "3.1.0"
|
||||||
@@ -1004,6 +1064,68 @@ dependencies = [
|
@@ -999,11 +1059,74 @@ dependencies = [
|
||||||
|
"common",
|
||||||
|
"daemon",
|
||||||
|
"fdt 0.1.5",
|
||||||
|
+ "libc",
|
||||||
|
"libredox",
|
||||||
|
"log",
|
||||||
"ron",
|
"ron",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -178,7 +184,7 @@ index 9fcbd662..760fd8b4 100644
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.65"
|
version = "0.1.65"
|
||||||
@@ -1128,6 +1250,58 @@ dependencies = [
|
@@ -1128,6 +1251,58 @@ dependencies = [
|
||||||
"scheme-utils",
|
"scheme-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -237,7 +243,7 @@ index 9fcbd662..760fd8b4 100644
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ioslice"
|
name = "ioslice"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@@ -1174,6 +1348,7 @@ dependencies = [
|
@@ -1174,6 +1349,7 @@ dependencies = [
|
||||||
"daemon",
|
"daemon",
|
||||||
"driver-network",
|
"driver-network",
|
||||||
"libredox",
|
"libredox",
|
||||||
@@ -245,7 +251,7 @@ index 9fcbd662..760fd8b4 100644
|
|||||||
"pcid",
|
"pcid",
|
||||||
"redox_event",
|
"redox_event",
|
||||||
"redox_syscall 0.7.4",
|
"redox_syscall 0.7.4",
|
||||||
@@ -2390,6 +2565,24 @@ version = "1.19.0"
|
@@ -2390,6 +2566,24 @@ version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||||
|
|
||||||
@@ -8125,6 +8131,18 @@ index 22a985ee..c60facfd 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
diff --git a/drivers/hwd/Cargo.toml b/drivers/hwd/Cargo.toml
|
||||||
|
index 3d37cfb3..40b51a1b 100644
|
||||||
|
--- a/drivers/hwd/Cargo.toml
|
||||||
|
+++ b/drivers/hwd/Cargo.toml
|
||||||
|
@@ -6,6 +6,7 @@ edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
fdt.workspace = true
|
||||||
|
+libc.workspace = true
|
||||||
|
log.workspace = true
|
||||||
|
ron.workspace = true
|
||||||
|
libredox = { workspace = true, default-features = false, features = ["std", "call"] }
|
||||||
diff --git a/drivers/hwd/src/backend/acpi.rs b/drivers/hwd/src/backend/acpi.rs
|
diff --git a/drivers/hwd/src/backend/acpi.rs b/drivers/hwd/src/backend/acpi.rs
|
||||||
index 3da41d63..12d26261 100644
|
index 3da41d63..12d26261 100644
|
||||||
--- a/drivers/hwd/src/backend/acpi.rs
|
--- a/drivers/hwd/src/backend/acpi.rs
|
||||||
@@ -8280,10 +8298,16 @@ index 3da41d63..12d26261 100644
|
|||||||
+ is_elan_touchpad_id(id) || is_cypress_touchpad_id(id) || is_synaptics_rmi_id(id)
|
+ is_elan_touchpad_id(id) || is_cypress_touchpad_id(id) || is_synaptics_rmi_id(id)
|
||||||
+}
|
+}
|
||||||
diff --git a/drivers/hwd/src/main.rs b/drivers/hwd/src/main.rs
|
diff --git a/drivers/hwd/src/main.rs b/drivers/hwd/src/main.rs
|
||||||
index 79360e34..f58ec825 100644
|
index 79360e34..a0462f51 100644
|
||||||
--- a/drivers/hwd/src/main.rs
|
--- a/drivers/hwd/src/main.rs
|
||||||
+++ b/drivers/hwd/src/main.rs
|
+++ b/drivers/hwd/src/main.rs
|
||||||
@@ -37,8 +37,15 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
@@ -1,3 +1,5 @@
|
||||||
|
+use std::os::fd::AsRawFd;
|
||||||
|
+use std::os::unix::process::CommandExt;
|
||||||
|
use std::process;
|
||||||
|
|
||||||
|
mod backend;
|
||||||
|
@@ -37,8 +39,34 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||||
|
|
||||||
//TODO: launch pcid based on backend information?
|
//TODO: launch pcid based on backend information?
|
||||||
// Must launch after acpid but before probe calls /scheme/acpi/symbols
|
// Must launch after acpid but before probe calls /scheme/acpi/symbols
|
||||||
@@ -8292,10 +8316,29 @@ index 79360e34..f58ec825 100644
|
|||||||
+ // Fire-and-forget: daemon::Daemon::spawn blocks until pcid signals readiness,
|
+ // Fire-and-forget: daemon::Daemon::spawn blocks until pcid signals readiness,
|
||||||
+ // but pcid only signals after full PCI enumeration. If enumeration hangs on
|
+ // but pcid only signals after full PCI enumeration. If enumeration hangs on
|
||||||
+ // real hardware (unresponsive device, complex AML), hwd deadlocks initfs.
|
+ // real hardware (unresponsive device, complex AML), hwd deadlocks initfs.
|
||||||
+ match std::process::Command::new("pcid").spawn() {
|
+ {
|
||||||
+ Ok(_child) => {}
|
+ match std::io::pipe() {
|
||||||
+ Err(err) => {
|
+ Ok((_read_end, write_end)) => {
|
||||||
+ log::error!("hwd: failed to spawn pcid: {}", err);
|
+ let write_fd: std::os::fd::OwnedFd = write_end.into();
|
||||||
|
+ let raw_fd = write_fd.as_raw_fd();
|
||||||
|
+ let mut cmd = std::process::Command::new("pcid");
|
||||||
|
+ cmd.env("INIT_NOTIFY", raw_fd.to_string());
|
||||||
|
+ unsafe {
|
||||||
|
+ cmd.pre_exec(move || {
|
||||||
|
+ if libc::fcntl(raw_fd, libc::F_SETFD, 0) == -1 {
|
||||||
|
+ return Err(std::io::Error::last_os_error());
|
||||||
|
+ }
|
||||||
|
+ Ok(())
|
||||||
|
+ });
|
||||||
|
+ }
|
||||||
|
+ match cmd.spawn() {
|
||||||
|
+ Ok(_) => {}
|
||||||
|
+ Err(err) => log::error!("hwd: failed to spawn pcid: {}", err),
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ Err(err) => {
|
||||||
|
+ log::error!("hwd: failed to create pcid notification pipe: {}", err);
|
||||||
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user