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); + } } } });