evidence · 6.2 KiB

teardown-crash.md

Committed at docs/evidence/hdmi-hotplug/landscape/teardown-crash.md. This is what grounds the requirements that cite it.

Open raw source

Sway crash when HDMI is plugged into the landscape image

Board: second board, keyboard case, installed landscape profile (.#kernelMainlineDrmShellLandscapeBootFiles), 2026-10-14.

Operator report

Operator, 2026-10-14: “hdmi didn’t work idk why i plugged it up … nothing happened”, then “i had to unplug the hdmi, the board showed a white screen and when i unplugged it rebooted” / “it might not have been reboot might’ve been shell crashing”.

What the journal shows (evidence class: board-read)

journalctl on the board, cable plugged at 02:58:41 CDT (trimmed):

02:58:41 sway[1052]: [wlr] [backend/drm/backend.c:139] Received hotplug event for /dev/dri/card0
02:58:41 sway[1052]: [wlr] [backend/drm/drm.c:1778] Scanning DRM connector 52 on /dev/dri/card0
02:58:41 sway[1052]: [wlr] [backend/drm/drm.c:1869] 'DSI-1' disconnected
02:58:41 sway[1052]: [sway/card_shell.c:631] K230_CARD_SHELL mirror-release id=5
02:58:41 sway[1052]: [sway/desktop/transaction.c:821] Transaction 0x2fa2b867d0 committing with 1 instructions
02:58:41 sway[1052]: [sway/desktop/transaction.c:717] Applying transaction 0x2fa2b867d0
02:58:41 kernel: sway[1052]: unhandled signal 11 code 0x1 at 0x0000000000000068 in libwlroots-0.20.so[7fcd0,36be735000+135000]
02:58:41 kernel: epc : 00000036be7b4cd0 ra : 0000002fa2836c7e … a0 : 0000000000000000
02:58:41 systemd-coredump[1226]: Process 1052 (sway) of user 1000 terminated abnormally with signal 11/SEGV, processing...
02:59:38 systemd[1]: shell.service: The kernel OOM killer killed some processes in this unit.

The kernel did not reboot. Sway crashed. systemd-coredump then read the ~600 MB core of Sway’s shared memory, which ran the board out of memory, and the OOM killer took the rest of the session. The session restarted at 03:00:03, which looked like a reboot from the glass.

Symbolized from the core (host, against the deployed store paths): epc is wlr_scene_output_set_position+0xa in wlroots (load base 0x36be735000, offset 0x7fcd0), dereferencing a NULL scene_output (a0 = 0, badaddr 0x68). ra is in Sway’s transaction_progress, reached through arrange_root. Sway’s base came from gp = 0x2fa28a14f8.

Sequence: wlroots tore down DSI-1. Sway’s output teardown cleared that output’s scene_output but had not yet removed it from root->outputs. Sway then called card_shell_output_disable, which left the card overview through restore(). restore() committed a transaction, arrange_root() walked root->outputs, and passed the half-destroyed output’s NULL scene_output to wlr_scene_output_set_position().

Two questions are still open, and HDMI task 8.7 depends on them. Why did the kernel’s HPD worker report DSI-1 disconnected? And did it ever report HDMI-A-1 connected? Only connector 52 (DSI-1) was scanned before the crash.

Fix

nix/card-shell/adapter.c: handle_output_destroy sets output_teardown around cs_leave, and restore() skips transaction_commit_dirty() while it is set. Sway commits its own transaction once it has moved the output’s workspaces.

Forced disconnect on the fixed build (evidence class: injected, sysfs)

Deployed system /nix/store/i7r10d4x… (bundle bundle-teardown). The overview was opened with swaymsg card_shell enter, then echo off > /sys/class/drm/card0-DSI-1/status, 08:57 CDT:

08:57:01 sway[1069]: [wlr] [backend/drm/drm.c:1869] 'DSI-1' disconnected
08:57:01 sway[1069]: [sway/card_shell.c:1928] K230_CARD_SHELL restored focus=5 message=0
08:57:01 sway[1069]: [sway/tree/output.c:290] Disabling output 'DSI-1'
08:57:01 sway[1069]: [sway/tree/output.c:307] Destroying output 'DSI-1'
08:57:01 sway[1069]: [wlr] [backend/drm/drm.c:984] connector DSI-1: Turning off
08:57:02 sway[1069]: [sway/config/output.c:1072] Commit of 0 outputs succeeded
08:57:06 sway[1069]: [wlr] [backend/drm/drm.c:1861] 'DSI-1' connected
08:57:06 sway[1069]: [sway/desktop/output.c:570] New output 0x36c967ff10: DSI-1 (non-desktop: 0)

Sway kept PID 1069 the whole time, and the journal has no unhandled signal. echo detect brought the panel back: swaymsg -t get_outputs showed DSI-1 active with transform 270. A native grim capture afterwards was 1232×568 and showed the terminal card that had focus in the overview (focus=5), restored in front.

Limits: the forced status drives the same teardown path (output destroyed while the overview is active), but this is not a cable plug. The unfixed build was not run through the forced test. HDMI output on the landscape image had not been observed at this point; see the cable test below.

Cable plug and unplug on the fixed build (physical: operator + native capture)

Same deployed system, 09:38–09:40 CDT, HP 27wm monitor. Sway kept PID 1069 throughout.

Plug, 09:38:19–21 (board journal):

09:38:19 [wlr] [backend/drm/drm.c:1869] 'DSI-1' disconnected
09:38:19 [sway/tree/output.c:307] Destroying output 'DSI-1'
09:38:20 [wlr] [backend/drm/drm.c:1778] Scanning DRM connector 54 on /dev/dri/card0
09:38:20 [wlr] [backend/drm/drm.c:1861] 'HDMI-A-1' connected
09:38:21 kernel: input: K230 Virtual Touchpad (HDMI mode) as /devices/virtual/input/input3
09:38:21 [sway/config/output.c:1080] Finalizing config for HDMI-A-1

The kernel’s hotplug handling reported HDMI about a second after the panel dropped. swaymsg -t get_outputs showed HDMI-A-1 at 1280x800 @ 59.910 Hz, transform 90: the existing HDMI arrangement, unchanged by the landscape panel transform. hdmi-plugged-grim.png (800×1280) is the native capture: the terminal that had focus, upright in portrait. libinput logged its usual rate-limited “Touch jump” and “lagging behind” messages for the relay while the operator used it.

Unplug, 09:40:02: DSI-1 reconnected and Sway first tried to commit both outputs. That failed because no CRTC or dumb buffer was free for HDMI. Sway then processed 'HDMI-A-1' disconnected, removed the relay touchpad, and the single-output commit for DSI-1 succeeded. The panel driver logged RDDID (0x04) failed: -22 and RDDPM (0x0A) failed: -110 during the panel’s re-enable, and the panel still came up. DSI-1 was then active at 568x1232, transform 270. panel-after-unplug-grim.png (1232×568) is the native capture.

Operator, 2026-10-14, after plugging in, using the relay and unplugging: “yeah it’s good to go”.