From 37f8b37267caf48dc8d594cd0e1028499db2fab2 Mon Sep 17 00:00:00 2001 From: vasilito Date: Mon, 27 Jul 2026 21:55:34 +0900 Subject: [PATCH] driver-manager: share Arc + crash-aware reaper + S3 self_weak (N18 Q1+Q2+S3) Three changes in one file because the regions are interleaved and the changes are all upstream of the audit plan's N18 single-day batch. - Q1: `main.rs:636-661` rewritten to build one `Vec>` and pass `Arc::clone` to both `DeviceManager` via the new `register_driver_shared` and to the reaper registry via `Arc::downgrade`. Removes the dead `registry_configs` second-loop block. - Q2: reaper closure at `main.rs:765-772` interprets `waitpid` status via `WIFEXITED && WEXITSTATUS == 0` or `WIFSIGNALED && WTERMSIG in (SIGTERM, SIGINT)` as a clean exit, routing to `reap_pid_clean`; anything else routes to `reap_pid` (crash). - S3: cfg-gated `set_self_weak(Arc::downgrade(&scheme))` call after `set_manager` so the detached AER recovery worker can notify the scheme of rebind events. driver-manager tests: 164 passing (no regression). --- .../system/driver-manager/source/src/main.rs | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/local/recipes/system/driver-manager/source/src/main.rs b/local/recipes/system/driver-manager/source/src/main.rs index 6fb79a2fea..535b8a9ac5 100644 --- a/local/recipes/system/driver-manager/source/src/main.rs +++ b/local/recipes/system/driver-manager/source/src/main.rs @@ -605,6 +605,12 @@ fn main() { let scheme = Arc::new(DriverManagerScheme::new()); scheme.set_manager(Arc::clone(&manager)); + // N18 S3: store a Weak self-reference so the AER recovery worker + // (which runs detached) can call back into the scheme to record + // rebind events without keeping a long-lived strong Arc. + #[cfg(target_os = "redox")] + scheme.set_self_weak(std::sync::Arc::downgrade(&scheme)); + let heartbeat = heartbeat::Heartbeat::new( std::path::PathBuf::from("/var/run/driver-manager.heartbeat.json"), std::time::Duration::from_secs(5), @@ -633,12 +639,22 @@ fn main() { initfs_manifest: Some(std::sync::Arc::clone(&shared_initfs_manifest)), }); + // N18 Q1: one Arc per driver, shared between manager + // and registry. The manager mutates spawned/pid_to_device via probe(); + // the reaper's Weak::upgrade returns the same allocation so the maps + // it cleans match the maps the manager populated. + let driver_arcs: Vec> = driver_configs + .iter() + .map(|dc| std::sync::Arc::new(dc.clone())) + .collect(); match manager.lock() { Ok(mut mgr) => { mgr.register_bus(Box::new(PciBus::new())); - - for dc in &driver_configs { - mgr.register_driver(Box::new(dc.clone())); + for dc in &driver_arcs { + // Unsized coercion: Arc -> Arc. + // Coercion fires at the function-call site (argument position + // accepts Arc, which Arc satisfies). + mgr.register_driver_shared(dc.clone()); } } Err(err) => { @@ -650,13 +666,8 @@ fn main() { let mgr_clone = Arc::clone(&manager); let scheme_clone = Arc::clone(&scheme); - let registry_configs: Vec> = driver_configs - .iter() - .map(|dc| std::sync::Arc::new(dc.clone())) - .collect(); - for cfg in ®istry_configs { - let weak: std::sync::Weak = - std::sync::Arc::downgrade(cfg); + for dc in &driver_arcs { + let weak: std::sync::Weak = std::sync::Arc::downgrade(dc); registry::register(weak); } @@ -762,11 +773,21 @@ fn main() { }, ); - let _reaper_thread = reaper::spawn_reaper_thread(|pid| { + let _reaper_thread = reaper::spawn_reaper_thread(|pid, status| { + // Clean exit: WIFEXITED && WEXITSTATUS == 0, or WIFSIGNALED with + // SIGTERM/SIGINT (our own remove() sends SIGTERM). Anything else + // is a crash. + let clean = unsafe { libc::WIFEXITED(status) } && unsafe { libc::WEXITSTATUS(status) } == 0 + || unsafe { libc::WIFSIGNALED(status) } + && matches!(unsafe { libc::WTERMSIG(status) }, libc::SIGTERM | libc::SIGINT); let registry = registry::snapshot(); for weak in registry { if let Some(cfg) = weak.upgrade() { - cfg.reap_pid(pid); + if clean { + cfg.reap_pid_clean(pid); + } else { + cfg.reap_pid(pid); + } } } });