From 4822c85e5cc121d5d3a77f22140c460b9f86724e Mon Sep 17 00:00:00 2001 From: vasilito Date: Sat, 25 Jul 2026 07:03:42 +0900 Subject: [PATCH] v4.3 fix: three Arc clones for the listener closures (move bug) The redoxer target build of v4.3 failed with: error[E0382]: the type `Arc` does not implement `Copy` ... let scheme_for_events = Arc::clone(&scheme); ... move || scheme_for_events_aer.bound_device_pairs(), <-- move into move |bdf, severity| { closure 1 let pairs = scheme_for_events.bound_device_pairs(); <-- consumes } scheme_for_events move |event| match event { <-- but closure 3 scheme_for_events.dispatch_recovery(...); wants it too } Root cause: three closures (, , ) all need access to the scheme. Each is `move` so each must own its own Arc. Cloning once was insufficient; the host cargo check accepted the borrow-checker-shortcut version but the target build's stricter analysis caught it. Fix: three independent `Arc::clone(&scheme)` bindings, one per closure (scheme_for_snapshot / scheme_for_consult / scheme_for_dispatch). Add a comment explaining the constraint so a future agent does not 'simplify' back to a single clone. Also remove the now-unused `scheme_for_events` binding. Verified: cargo check --target x86_64-unknown-redox clean (only pre-existing parse_linux_id_table warning) cargo check (host target) clean (same pre-existing) cargo test --bin driver-manager 70 passed cargo test --lib redox-driver-core 32 passed --- .../system/driver-manager/source/src/main.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/local/recipes/system/driver-manager/source/src/main.rs b/local/recipes/system/driver-manager/source/src/main.rs index 2d035074b8..ee622ba994 100644 --- a/local/recipes/system/driver-manager/source/src/main.rs +++ b/local/recipes/system/driver-manager/source/src/main.rs @@ -384,8 +384,6 @@ fn main() { &shared_blacklist, )); - let scheme_for_events = Arc::clone(&scheme); - match manager.lock() { Ok(mut mgr) => { mgr.register_bus(Box::new(PciBus::new())); @@ -420,11 +418,18 @@ fn main() { // overrides), then to None (severity-only). The listener then // maps the action through `RecoveryAction::Fatal` -> escalation // log marker (in main callback) before calling dispatch_recovery. - let scheme_for_events_aer = Arc::clone(&scheme); + // + // Each closure captures its own `Arc` clone of `scheme`. Cloning + // once is not enough — the closures are mutually exclusive + // (each runs on its own thread) and `move` semantics require + // independent ownership for each. + let scheme_for_snapshot = Arc::clone(&scheme); + let scheme_for_consult = Arc::clone(&scheme); + let scheme_for_dispatch = Arc::clone(&scheme); let _events_thread = unified_events::spawn_unified_listener( std::path::PathBuf::from("/scheme/pci/aer"), std::path::PathBuf::from("/scheme/pci/pciehp"), - move || scheme_for_events_aer.bound_device_pairs(), + move || scheme_for_snapshot.bound_device_pairs(), move |bdf, severity| { // 1) Sidecar IPC: ask the spawned driver daemon if it // opted in to error-reporting. @@ -440,7 +445,7 @@ fn main() { } // 2) In-process DriverConfig::on_error: drivers may // override the severity-default via the trait method. - let pairs = scheme_for_events.bound_device_pairs(); + let pairs = scheme_for_consult.bound_device_pairs(); let driver_name = match pairs.iter().find(|(addr, _)| addr == bdf) { Some((_, name)) => name.clone(), None => return None, @@ -498,7 +503,7 @@ fn main() { if let Some(action_str) = scheme::DriverManagerScheme::recovery_action_str(*action) { - scheme_for_events.dispatch_recovery(&event.device, action_str); + scheme_for_dispatch.dispatch_recovery(&event.device, action_str); } } unified_events::UnifiedEvent::Pciehp(e) => {