From 712ee935d6834bb2d70fb998c731c17ab5068e79 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Wed, 12 Aug 2026 13:29:26 +0200 Subject: [PATCH] fix(win-display): a failed devnode re-enable must keep its crash-journal entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit enable_instances cleared every requested id from the pnp-disabled-monitors journal unconditionally — a mid-life re-enable failure erased its own crash-recovery entry, so neither the running host nor the next start would ever retry, leaving the operator's monitor disabled (invisible to Windows and every display listing) until a manual Device Manager fix. Field 2026-08-12 (Android-client host running the pnp_disable_monitors axis): displays gone from the client after 2-3 sessions, only a full host restart bringing them back — the restart path only works while the journal still has the entry. Only successfully re-enabled ids clear now; failures stay journaled (and are logged with the consequence) so startup_recover retries them. --- crates/pf-win-display/src/monitor_devnode.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/pf-win-display/src/monitor_devnode.rs b/crates/pf-win-display/src/monitor_devnode.rs index 0d1df1cd..151ae157 100644 --- a/crates/pf-win-display/src/monitor_devnode.rs +++ b/crates/pf-win-display/src/monitor_devnode.rs @@ -217,18 +217,32 @@ fn journal_and_disable(targets: Vec<(String, String)>) -> Vec { disabled } -/// Re-enable `ids` (teardown / recovery) and clear them from the journal. +/// Re-enable `ids` (teardown / recovery) and clear the ones that actually re-enabled from the +/// journal. A FAILED re-enable must keep its journal entry: it is the only record that the +/// devnode is still disabled, and the next host start's [`startup_recover`] is the only thing +/// left that will retry it. (The old behavior cleared every requested id unconditionally — a +/// mid-life re-enable failure erased its own crash-recovery entry, leaving the operator's +/// monitor invisible to Windows AND to every display listing until they re-enabled it by hand +/// in Device Manager: the "my displays are gone until I restart everything" field class.) pub fn enable_instances(ids: &[String]) -> u32 { let mut ok = 0u32; + let mut reenabled: Vec<&String> = Vec::with_capacity(ids.len()); for id in ids { if set_devnode(id, false) { tracing::info!(id, "PnP-disable: monitor devnode re-enabled"); + reenabled.push(id); ok += 1; + } else { + tracing::warn!( + id, + "PnP-disable: monitor devnode re-enable FAILED — keeping its crash-journal \ + entry so the next host start retries (until then this monitor stays disabled)" + ); } } let journal: Vec = read_journal() .into_iter() - .filter(|j| !ids.contains(j)) + .filter(|j| !reenabled.contains(&j)) .collect(); write_journal(&journal); ok