fix(docking): retry the undock; a lost keyword left the panel black
Some checks failed
Check / eval (push) Has been cancelled
Some checks failed
Check / eval (push) Has been cancelled
Round 6 passed on the plug side but unplugging the cable left the laptop
panel black until it was re-docked. The journal named it: across three
undocks, two logged result=enable-timeout and one result=ok — a race, not
a logic error.
Two halves, both needed:
- `hyprctl keyword monitor eDP-1,preferred,auto,1` is accepted (exit 0)
while Hyprland is still tearing down the departing external, then
silently dropped. Re-issue it on every poll for 5s and keep `monitors`
listing the panel — not hyprctl's exit code — as the only proof.
- The watcher fired the undock once off the removal event and marked the
departure handled regardless (`|| true` + awaiting_lid_open=1). Since
known_outputs had already moved, the set-changed guard never reopened
and nothing retried, so one lost keyword cost the panel until re-dock.
The undock is now a queued invariant driven on the 1s tick, bounded at
6 attempts so a genuinely unenableable panel can't pin the inhibitor.
The VM harness cannot reach this race: QEMU's headless backend aborts
Hyprland if the last active output is deleted while the DRM output is
disabled, so the test must undock before removing DP-1 and never collides
the two. Noted there, and V3 queued as round 7 — unplug 5+ times, since
the old failure only hit ~2 in 3.
Verified: V2 — nix flake check --no-build; monitor-fallback.nix exit 0 in
57s; shellcheck clean. The fix itself is V3 pending.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -130,6 +130,13 @@ pkgs.testers.runNixOSTest {
|
||||
# monitorremoved event still proves that the watcher retains the inhibitor
|
||||
# until lid-open, without mistaking a backend limitation for product
|
||||
# behavior. Physical cable-yank timing remains the bounded V3 check.
|
||||
#
|
||||
# Undocking a quiescent output is therefore all this harness can assert —
|
||||
# and that gap is exactly what shipped a black panel in round 6: on real
|
||||
# hardware the enable collides with the departing external's teardown and
|
||||
# is silently dropped ~2 times in 3. The keyword re-issue in the
|
||||
# transition and the tick-driven retry in the watcher are what cover it;
|
||||
# neither is exercised below, so do not read a pass here as proof of them.
|
||||
user(f"{transition} undock Virtual-1")
|
||||
machine.wait_until_succeeds(
|
||||
hy + "-j monitors' | jq -e 'any(.[]; .name == \"Virtual-1\")'", timeout=20
|
||||
|
||||
Reference in New Issue
Block a user