fix(host/linux): survive and self-heal dead gamescope sessions on headless SteamOS boxes
Three fixes for the "most connects simply fail" trap on a SteamOS host with no physical display (VM testbox, panel-less mini PC): - restore path: skip the restore-to-physical-panel when no DRM connector reports a connected display — removing the headless drop-in and restarting gamescope-session.target on such a box just crash-loops gamescope and strands every later connect on "no usable compositor". Keep the headless session (and the takeover state) instead. - connect path: when no live graphical session exists but the MANAGED gamescope infra is present (SteamOS gamescope-session / Bazzite session-plus), route to the gamescope takeover — which rebuilds the session at the client's mode — instead of failing the connect. - error delivery: a session-setup failure used to just drop the QUIC connection, reaching the client as "control stream finished mid-frame" (indistinguishable from transport trouble). Close with a typed setup-failed code (0x68, RejectedSetupFailed = -29) carrying the error text, and give the client handshake/pairing error paths a short grace for the CONNECTION_CLOSE to beat the stream error it caused. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -92,8 +92,24 @@ pub(super) fn resolve_compositor(
|
||||
let available = crate::vdisplay::available();
|
||||
let chosen = match pick_compositor(pref, &available, detected) {
|
||||
Some(c) => c,
|
||||
// No live session, but the MANAGED gamescope infra exists (SteamOS's
|
||||
// `gamescope-session`, Bazzite's `gamescope-session-plus`): route to the gamescope
|
||||
// backend anyway — its managed path stands the session up from nothing at the
|
||||
// client's mode (drop-in takeover / session relaunch), so a dead gaming session
|
||||
// self-heals on the next connect instead of bouncing every client until someone
|
||||
// restarts it by hand. (The trap that motivated this: a headless SteamOS box whose
|
||||
// gamescope died — every connect failed "no usable compositor" even though the
|
||||
// takeover could rebuild it.) Not under an operator pin: an explicit
|
||||
// `PUNKTFUNK_COMPOSITOR` keeps its exact, hand-configured meaning.
|
||||
None if !overridden && crate::vdisplay::managed_session_available() => {
|
||||
tracing::info!(
|
||||
"no live graphical session — managed gamescope infra present; routing to \
|
||||
the managed takeover to revive the session"
|
||||
);
|
||||
Compositor::Gamescope
|
||||
}
|
||||
None => {
|
||||
// No live session — the state a compositor crash leaves behind (gnome-shell
|
||||
// The state a compositor crash leaves behind (gnome-shell
|
||||
// SIGSEGV → GDM greeter, whose auto-login is once-per-boot). If the operator
|
||||
// configured a recovery hook, fire it (debounced) and tell the client to retry:
|
||||
// its next knock lands in the recovered desktop.
|
||||
|
||||
Reference in New Issue
Block a user