Skip to content

fix(whp-gui): WLR_LIBINPUT_NO_DEVICES=1 — root-cause the intermittent WHP GUI boot race#122

Merged
TimLai666 merged 1 commit into
mainfrom
fix/whp-gui-boot-race
Jul 10, 2026
Merged

fix(whp-gui): WLR_LIBINPUT_NO_DEVICES=1 — root-cause the intermittent WHP GUI boot race#122
TimLai666 merged 1 commit into
mainfrom
fix/whp-gui-boot-race

Conversation

@TimLai666

Copy link
Copy Markdown
Owner

Root-causes and fixes the intermittent WHP GUI boot failure flagged in #120 (guest-agent exits 1 ~0.45s into boot, before any frame; ~1 in 3 boots).

Investigation (followed the debugger methodology)

guest-agent's own stderr is invisible on the WHP serial console (init redirects to hvc0/ttyS0, but quiet drops console_loglevel to 4, so only init's <0> kmsg report() shows). Added note() mirroring GUI-startup diagnostics to /dev/kmsg at <2>, and captured cage's stderr (Stdio::piped) → forwarded to kmsg when cage dies during startup. (Two kmsg gotchas bit the instrumentation first: one write() = one record, so the line must be built + written with a single write_allwriteln! splits into records and the body record lost its <N> prefix, hidden by quiet; and priority must be < 4.)

The captured failure showed the real cause:

cage: [ERROR] libinput initialization failed, no input devices
cage: [ERROR] Set WLR_LIBINPUT_NO_DEVICES=1 to suppress this check
cage: [ERROR] Unable to start the wlroots backend

plus starting cage (dri card present=true)/dev/dri was fine; wlroots' libinput backend aborts when zero input devices exist yet. The virtio-input nodes (/dev/input/event*) are created by udev asynchronously; when cage wins the race it sees no devices and exits → wait_for_socket bails → exit 1. Intermittent = the udev-vs-cage race on input nodes.

Fix

WLR_LIBINPUT_NO_DEVICES=1 in cage's env — wlroots' own recommended flag: start with zero input devices, they hotplug in via udev afterward. (An earlier attempt waited for /dev/dri before cage, but the instrumentation proved dri was never the missing resource, so it was dropped for this one-line real fix.)

Verification

Real WHP hardware (this box): 14/14 consecutive clean boots succeed after the fix (was ~1/3 failing). The cage-stderr→kmsg observability is kept so future WHP GUI failures self-diagnose. No unit test — it's an in-VM udev/device race with no host-testable surface; the boot loop is the verification. Supersedes the "pre-existing boot race" caveat in #120.

🤖 Generated with Claude Code

…t devices

Root-causes the intermittent WHP GUI boot failure noted in #120 (guest-agent
exits 1 ~0.45s into boot, before any frame; ~1 in 3 boots).

Investigation: guest-agent's own stderr is invisible on the WHP serial console
(init redirects to hvc0/ttyS0 but `quiet` drops console_loglevel to 4, so only
init's `<0>` kmsg `report()` shows). Added a `note()` that mirrors GUI-startup
diagnostics to `/dev/kmsg` at `<2>` (KERN_CRIT, prints under `quiet`) — and
crucially, captured cage's stderr (`Stdio::piped`) and forward it to kmsg when
cage dies during startup. Two kmsg subtleties bit the instrumentation first and
are handled: each write() to /dev/kmsg is one record, so the line is built and
written with a single `write_all` (`writeln!`/write_fmt splits into multiple
records, and the message-body record lacked the `<N>` prefix so `quiet` hid it);
and the priority must be `< 4`.

With that, a captured failure showed the real cause:
  cage: [ERROR] libinput initialization failed, no input devices
  cage: [ERROR] Set WLR_LIBINPUT_NO_DEVICES=1 to suppress this check
  cage: [ERROR] Failed to initialize backend / Unable to start the wlroots backend
and `starting cage (dri card present=true)` — so /dev/dri was fine; wlroots'
libinput backend aborts when zero input devices exist yet. In the micro-VM the
virtio-input nodes (/dev/input/event*) are created by udev asynchronously; when
cage wins the race it sees no devices and exits → wait_for_socket bails →
exit 1. Intermittent = the udev-vs-cage race on input nodes.

Fix: `WLR_LIBINPUT_NO_DEVICES=1` in cage's env (wlroots' own recommended flag) —
start with zero input devices; they hotplug in via udev afterward. An earlier
attempt waited for /dev/dri before cage, but the instrumentation proved dri was
never the missing resource, so that was dropped for this one-line real fix.

Verified on real WHP hardware (this box): 14/14 consecutive clean boots succeed
after the fix (was ~1/3 failing before). The cage-stderr→kmsg observability is
kept so future WHP GUI failures are self-diagnosing. No unit test — it's an
in-VM udev/device race with no host-testable surface; verification is the boot
loop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@TimLai666
TimLai666 merged commit 0c9d9b0 into main Jul 10, 2026
17 checks passed
@TimLai666
TimLai666 deleted the fix/whp-gui-boot-race branch July 10, 2026 07:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant