fix(host): admit exactly ONE parked knock per Approve — stop crashing gnome-shell, and self-heal dead sessions
ci / docs-site (push) Successful in 55s
ci / web (push) Successful in 1m11s
apple / swift (push) Successful in 1m12s
decky / build-publish (push) Successful in 17s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 13s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 6s
ci / bench (push) Successful in 7m3s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6m57s
windows-host / package (push) Successful in 8m20s
arch / build-publish (push) Successful in 11m48s
deb / build-publish (push) Successful in 12m57s
apple / screenshots (push) Successful in 5m42s
android / android (push) Successful in 17m23s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m32s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 17m28s
ci / rust (push) Successful in 25m57s
docker / deploy-docs (push) Failing after 5m44s
ci / docs-site (push) Successful in 55s
ci / web (push) Successful in 1m11s
apple / swift (push) Successful in 1m12s
decky / build-publish (push) Successful in 17s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 13s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 6s
ci / bench (push) Successful in 7m3s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6m57s
windows-host / package (push) Successful in 8m20s
arch / build-publish (push) Successful in 11m48s
deb / build-publish (push) Successful in 12m57s
apple / screenshots (push) Successful in 5m42s
android / android (push) Successful in 17m23s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m32s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 17m28s
ci / rust (push) Successful in 25m57s
docker / deploy-docs (push) Failing after 5m44s
A retrying unpaired client parks one QUIC connection per knock, but the delegated-approval waiters were keyed on fingerprint alone — one console Approve resolved ALL of them. Observed live (2026-07-10): an iPad knocked 3x, one Approve admitted three full sessions, three Mutter virtual monitors were created within ~200us plus an ApplyMonitorsConfig, and gnome-shell SIGSEGV'd inside meta_monitor_manager_rebuild — dropping the box to the GDM greeter, unreachable until reboot (GDM auto-login runs once per boot) while the lingering host spammed "RemoteDesktop ... not activatable" libei errors. Four fixes, outermost symptom inward: - Knock generations (native_pairing): note_pending returns a per-knock generation; a re-knock bumps it and wakes the previous waiter, which resolves the new PairingDecision::Superseded (connection closes; the console list is unchanged). An approval records WHICH generation it admitted, so a stale waiter polling only after the pending entry is cleared still loses the tie — exactly one admission, no matter the interleaving. - TOPOLOGY_LOCK (vdisplay/mutter): every Mutter monitor mutation (pre-snapshot -> RecordVirtual -> ApplyMonitorsConfig, and the teardown Stop) is serialized process-wide. Concurrent rebuilds are what segfault the shell (second on-glass crash of this class — the teardown race is already documented in-file), and serialization also keeps wait_virtual_connector's snapshot diff from attributing a sibling's connector. Create timeout 20s -> 45s for lock queueing. - Session-env hygiene (vdisplay): when detection finds NOTHING live, clear the previous connect's XDG_CURRENT_DESKTOP/WAYLAND_DISPLAY retarget. A stale GNOME value kept mutter::is_available() true after the crash, routing explicit-backend connects into the dead session (create timeouts + libei error loops) instead of the crisp "no live graphical session" handshake error. - Opt-in recovery hook (config + punktfunk1): PUNKTFUNK_RECOVER_SESSION_CMD fires (detached via sh -c, debounced to one launch/min) when a client connects while no graphical session is live — e.g. `sudo -n systemctl restart gdm` re-runs auto-login and the client's retry lands in the recovered desktop. The handshake error tells the client to retry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -60,6 +60,15 @@ PUNKTFUNK_VIDEO_SOURCE=virtual
|
||||
# Lower (e.g. 3000) to reclaim kept displays sooner after an
|
||||
# ungraceful drop; clamped ≥1s, keep-alive ping scales with it so a
|
||||
# live session never false-disconnects. A deliberate quit is instant.
|
||||
# Session recovery hook: fired (debounced, ≥60 s apart) when a client connects while NO graphical
|
||||
# session is live for this uid — e.g. a compositor crash dropped the box to the GDM greeter, whose
|
||||
# auto-login only runs once per boot, so the box would otherwise need a walk-up login or a reboot.
|
||||
# Restarting the display manager re-runs auto-login and the client's retry lands in the recovered
|
||||
# desktop. Runs detached via `sh -c` as the host's user, so it needs passwordless privilege for
|
||||
# exactly this action (sudoers drop-in: `youruser ALL=(root) NOPASSWD: /usr/bin/systemctl restart
|
||||
# gdm`, or a polkit rule + plain `systemctl restart display-manager`). Unset = disabled.
|
||||
#PUNKTFUNK_RECOVER_SESSION_CMD=sudo -n systemctl restart gdm
|
||||
|
||||
# Full-chroma 4:4:4 (HEVC Range Extensions) — sharper text/desktop, no chroma loss. Honored only on
|
||||
# the punktfunk/1 native path when the client advertises 4:4:4 AND the GPU supports it (probed; else
|
||||
# the session stays 4:2:0). HEVC-only; independent of 10-bit. NVENC (NVIDIA) is the validated path;
|
||||
|
||||
Reference in New Issue
Block a user