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
This commit is contained in:
2026-07-25 07:03:42 +09:00
parent b5ca29570c
commit 4822c85e5c
@@ -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) => {