chore: consolidate parallel-session WIP (HOLD — do not push)
Local snapshot of intermingled in-flight work, committed to unblock the encode
refactor (a clean ffmpeg_win.rs for the vbv-dedup follow-on). These hunks span
the same files and can't be cleanly split here; the commit bundles three
distinct workstreams that each belong in their own PR:
- logging rework (~43 files: level re-tiering, structured fields, `?e`,
hot-path flood latches)
- conflicting-host detection (detect.rs + detect/{linux,windows}.rs + wiring
in main.rs/mgmt.rs/Cargo.toml/docs/packaging)
- standby-sink DWM-stall attribution (windows/display_events.rs + capture/
vdisplay wiring)
NOT verified as a combination. NOT to be pushed until the refactor is done and
these are re-verified and reorganized into their proper per-workstream PRs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1278,7 +1278,7 @@ fn launch_session(client: &str, unit_name: &str, mode: Mode) -> Result<u32> {
|
||||
// and the transient unit has no Restart= — without supervision the rest of this poll would
|
||||
// wait on a corpse. Re-run the unit so every readiness attempt inside the deadline is used.
|
||||
if !unit_starting_or_active(unit_name) {
|
||||
tracing::info!(
|
||||
tracing::warn!(
|
||||
unit = unit_name,
|
||||
"gamescope session: transient unit died (missed the wrapper's 5 s gamescope \
|
||||
readiness window?) — relaunching"
|
||||
|
||||
@@ -685,7 +685,7 @@ fn run(
|
||||
.dispatch_pending(&mut state)
|
||||
.context("dispatch_pending")?;
|
||||
if state.closed {
|
||||
tracing::warn!("KWin closed the virtual-output stream");
|
||||
tracing::warn!(output = %name, node_id, "KWin closed the virtual-output stream");
|
||||
break;
|
||||
}
|
||||
conn.flush().context("wayland flush")?;
|
||||
|
||||
@@ -255,12 +255,12 @@ fn session_thread(
|
||||
Ok(dc) => match get_state(&dc).await {
|
||||
Ok(state) => Some((dc, state)),
|
||||
Err(e) => {
|
||||
tracing::warn!("mutter: GetCurrentState (pre) failed ({e:#}); topology + scale persistence off");
|
||||
tracing::warn!(error = %format!("{e:#}"), "mutter: GetCurrentState (pre) failed; topology + scale persistence off");
|
||||
None
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
tracing::warn!("mutter: DisplayConfig unavailable ({e:#}); topology + scale persistence off");
|
||||
tracing::warn!(error = %format!("{e:#}"), "mutter: DisplayConfig unavailable; topology + scale persistence off");
|
||||
None
|
||||
}
|
||||
};
|
||||
@@ -301,14 +301,16 @@ fn session_thread(
|
||||
if exclusive { "disabled" } else { "kept" }
|
||||
),
|
||||
Err(e) => tracing::warn!(
|
||||
"mutter: could not set the virtual output primary ({e:#}); streaming continues — the desktop may render on the physical monitor"
|
||||
error = %format!("{e:#}"),
|
||||
"mutter: could not set the virtual output primary; streaming continues — the desktop may render on the physical monitor"
|
||||
),
|
||||
}
|
||||
}
|
||||
tracked = Some((dc, pre, vconn));
|
||||
}
|
||||
Err(e) => tracing::warn!(
|
||||
"mutter: virtual connector not identified ({e:#}); topology + scale persistence off"
|
||||
error = %format!("{e:#}"),
|
||||
"mutter: virtual connector not identified; topology + scale persistence off"
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -737,7 +739,8 @@ async fn make_virtual_primary(
|
||||
tracing::warn!(
|
||||
scale,
|
||||
derived,
|
||||
"mutter: ApplyMonitorsConfig at the remembered scale failed ({e:#}); retrying at the derived scale"
|
||||
error = %format!("{e:#}"),
|
||||
"mutter: ApplyMonitorsConfig at the remembered scale failed — retrying at the derived scale"
|
||||
);
|
||||
scale = derived;
|
||||
}
|
||||
|
||||
@@ -234,9 +234,12 @@ pub struct DisplayPolicy {
|
||||
/// untouched.
|
||||
#[serde(default)]
|
||||
pub ddc_power_off: bool,
|
||||
/// EXPERIMENTAL (Windows): after an `Exclusive` isolate deactivates the physical monitors,
|
||||
/// additionally DISABLE their PnP device nodes (persistently, so a standby monitor/TV whose
|
||||
/// hot-plug events re-arrive stays disabled) and re-enable them at restore. Targets the same
|
||||
/// EXPERIMENTAL (Windows): DISABLE physical monitors' PnP device nodes for the stream's
|
||||
/// duration (persistently, so a standby monitor/TV whose hot-plug events re-arrive stays
|
||||
/// disabled) and re-enable them at teardown. Two selectors: the monitors an `Exclusive`
|
||||
/// isolate deactivated, plus — in ANY topology — external monitors that are connected but not
|
||||
/// part of the desktop (the standby TV that was never active, whose input auto-scan /
|
||||
/// instant-on HPD cycling re-probes the link every few seconds). Targets the same
|
||||
/// "connected-but-dark head" periodic-stutter class as [`Self::ddc_power_off`], but at the
|
||||
/// Windows-reaction level: a disabled devnode's wake events trigger no PnP arrival, no CCD
|
||||
/// re-evaluation, no DWM invalidation. A crash-recovery journal re-enables leftovers on host
|
||||
|
||||
@@ -906,8 +906,9 @@ impl VirtualDisplayManager {
|
||||
Some(n) => {
|
||||
tracing::info!(
|
||||
backend = self.driver.name(),
|
||||
"target {} -> {n}",
|
||||
added.target_id
|
||||
target_id = added.target_id,
|
||||
gdi = %n,
|
||||
"IDD target activated into a display path"
|
||||
);
|
||||
// ADD only advertises the mode; force it active so DXGI captures the requested size.
|
||||
set_active_mode(n, mode);
|
||||
@@ -1015,6 +1016,26 @@ impl VirtualDisplayManager {
|
||||
}
|
||||
}
|
||||
thread::sleep(Duration::from_millis(1500)); // let the topology settle before capture opens
|
||||
|
||||
// EXPERIMENTAL `pnp_disable_monitors`, second selector (ANY topology): monitors
|
||||
// that are connected but NOT part of the desktop — the standby TV/monitor the
|
||||
// deactivated-set selector above structurally misses (it never had an active path
|
||||
// to deactivate), yet whose periodic standby wake events drive the same Windows
|
||||
// reaction cascade (rationale in `windows/monitor_devnode.rs`). Runs AFTER the
|
||||
// settle sleep so the active flags it reads are the committed ones (a display
|
||||
// still mid-activation from the primary topology's force-EXTEND must not read as
|
||||
// inactive and get disabled); in Extend the active physical panels are untouched
|
||||
// by construction. First member only — the sweep is group-scoped like the
|
||||
// isolate; later members join an already-swept desktop.
|
||||
if first_member && crate::vdisplay::policy::prefs().pnp_disable_monitors() {
|
||||
let mut keep = inner.target_ids();
|
||||
keep.push(added.target_id);
|
||||
for id in crate::monitor_devnode::disable_connected_inactive(&keep) {
|
||||
if !inner.group.pnp_disabled.contains(&id) {
|
||||
inner.group.pnp_disabled.push(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => tracing::warn!(
|
||||
"virtual-display target {} not yet an active display path (auto-activate, EXTEND \
|
||||
@@ -1067,8 +1088,11 @@ impl VirtualDisplayManager {
|
||||
) -> Result<Monitor> {
|
||||
tracing::info!(
|
||||
slot,
|
||||
old = %format!("{}x{}@{}", old.mode.width, old.mode.height, old.mode.refresh_hz),
|
||||
new = %format!("{}x{}@{}", mode.width, mode.height, mode.refresh_hz),
|
||||
old = format!(
|
||||
"{}x{}@{}",
|
||||
old.mode.width, old.mode.height, old.mode.refresh_hz
|
||||
),
|
||||
new = format!("{}x{}@{}", mode.width, mode.height, mode.refresh_hz),
|
||||
old_target = old.target_id,
|
||||
"virtual-display: re-arriving monitor for a mid-stream resize (exact mode)"
|
||||
);
|
||||
@@ -1207,17 +1231,19 @@ impl VirtualDisplayManager {
|
||||
// (stopped FIRST, as the per-monitor pinger was), and the group's topology restore runs
|
||||
// — first-in captured it, last-out restores it (design §6.1).
|
||||
self.stop_pinger();
|
||||
// EXPERIMENTAL `pnp_disable_monitors` restore: re-enable the devnodes FIRST and let
|
||||
// them re-arrive, so a CCD restore below re-activates paths whose monitors exist
|
||||
// again (a disabled devnode would leave the restored path modeless/EDID-less).
|
||||
// OUTSIDE the ccd_saved gate: the connected-inactive sweep disables devnodes in
|
||||
// Extend/Primary sessions too, where no isolate snapshot exists to restore.
|
||||
let pnp_disabled = std::mem::take(&mut inner.group.pnp_disabled);
|
||||
if !pnp_disabled.is_empty() {
|
||||
crate::monitor_devnode::enable_instances(&pnp_disabled);
|
||||
thread::sleep(Duration::from_millis(300));
|
||||
}
|
||||
// Re-attach detached display(s) BEFORE the REMOVE so the box is never left with zero
|
||||
// displays.
|
||||
if let Some(saved) = inner.group.ccd_saved.take() {
|
||||
// EXPERIMENTAL `pnp_disable_monitors` restore: re-enable the devnodes FIRST and let
|
||||
// them re-arrive, so the CCD restore below re-activates paths whose monitors exist
|
||||
// again (a disabled devnode would leave the restored path modeless/EDID-less).
|
||||
let pnp_disabled = std::mem::take(&mut inner.group.pnp_disabled);
|
||||
if !pnp_disabled.is_empty() {
|
||||
crate::monitor_devnode::enable_instances(&pnp_disabled);
|
||||
thread::sleep(Duration::from_millis(300));
|
||||
}
|
||||
restore_displays_ccd(&saved);
|
||||
// EXPERIMENTAL `ddc_power_off` wake: the restore re-activated the physical paths, and
|
||||
// returning signal alone wakes DPMS-off panels on most firmware — the explicit ON is
|
||||
@@ -1255,7 +1281,10 @@ impl VirtualDisplayManager {
|
||||
if is_device_gone(&e) {
|
||||
self.invalidate_device(&e);
|
||||
}
|
||||
tracing::warn!("virtual-display REMOVE failed: {e:#}");
|
||||
tracing::warn!(
|
||||
target_id = mon.target_id,
|
||||
"virtual-display REMOVE failed: {e:#}"
|
||||
);
|
||||
} else {
|
||||
tracing::info!(
|
||||
backend = self.driver.name(),
|
||||
|
||||
@@ -164,10 +164,14 @@ fn restart_vdisplay_device() -> bool {
|
||||
{
|
||||
Ok(o) => {
|
||||
let status = String::from_utf8_lossy(&o.stdout).trim().to_string();
|
||||
tracing::warn!(
|
||||
%status,
|
||||
"pf-vdisplay: cycled the adapter device (hostless-zombie recovery)"
|
||||
);
|
||||
if status == "ABSENT" {
|
||||
tracing::warn!("pf-vdisplay: no adapter devnode to cycle — driver not installed");
|
||||
} else {
|
||||
tracing::warn!(
|
||||
%status,
|
||||
"pf-vdisplay: cycled the adapter device (hostless-zombie recovery)"
|
||||
);
|
||||
}
|
||||
status != "ABSENT"
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -531,13 +535,13 @@ impl VdisplayDriver for PfVdisplayDriver {
|
||||
HighPart: reply.adapter_luid_high,
|
||||
};
|
||||
tracing::info!(
|
||||
"pf-vdisplay created {}x{}@{} (target_id={}, adapter_luid={:#x}, wudf_pid={})",
|
||||
target_id = reply.target_id,
|
||||
adapter_luid = %format_args!("{:#x}", luid.LowPart),
|
||||
wudf_pid = reply.wudf_pid,
|
||||
"pf-vdisplay monitor created {}x{}@{}",
|
||||
mode.width,
|
||||
mode.height,
|
||||
mode.refresh_hz,
|
||||
reply.target_id,
|
||||
luid.LowPart,
|
||||
reply.wudf_pid
|
||||
mode.refresh_hz
|
||||
);
|
||||
// Per-client identity diagnostic: did the driver honor the host's preferred (stable) monitor id?
|
||||
// A pre-Phase-2 driver leaves resolved_monitor_id=0 (it ignored the field); a current driver echoes
|
||||
|
||||
Reference in New Issue
Block a user