Skip to content

Commit 4aeafd2

Browse files
committed
the run that needed the console produced no console
First hosted run of the hibernate gate. Everything through the resume passed -- on attempt 1, so the retry never had to fire -- and then the poweroff after the resume did something no local run has done: the guest neither powered off nor reset into a fresh boot. The harness waited five minutes for a machine that was never coming back and failed, its trap took qemu down, and the step ended on a signal rather than an exit code. Every `if: failure()` step after it was skipped, so the console log was never uploaded and the one run that needed evidence produced none. Captures now fire on `failure() || cancelled()`, because a step killed by a signal reports neither. The console tail also goes to the job log at the point of failure, so the evidence survives even when the upload does not. And the wait itself now knows three outcomes instead of two: it came back, it went off late -- which the old code would have called "never came back", the same misdiagnosis this file keeps unlearning -- or it wedged, which is taken down by force and warned about rather than losing the Secure Boot half to a boot that has nothing to do with it.
1 parent a9ac15a commit 4aeafd2

2 files changed

Lines changed: 89 additions & 42 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -221,11 +221,18 @@ jobs:
221221

222222
# A boot failure is only useful if the guest's own account of it
223223
# survives the runner.
224+
#
225+
# `failure() || cancelled()` rather than `failure()`, because a step
226+
# whose process is killed by a signal reports neither. The hibernate
227+
# job did exactly that on 2026-08-21: the harness's own trap took
228+
# qemu down, the step ended 143, and every capture step after it was
229+
# skipped -- so the one run that needed the console produced no
230+
# console at all.
224231
- name: guest console
225-
if: failure()
232+
if: failure() || cancelled()
226233
run: tail -200 "vm-smoke/${{ matrix.example }}/console.log" || true
227234
- uses: actions/upload-artifact@v7
228-
if: failure()
235+
if: failure() || cancelled()
229236
with:
230237
name: console-${{ matrix.example }}
231238
path: vm-smoke/${{ matrix.example }}/console.log
@@ -266,10 +273,10 @@ jobs:
266273
smoke_args: --published localhost/kuma-smoke-niri:latest
267274

268275
- name: guest console
269-
if: failure()
276+
if: failure() || cancelled()
270277
run: tail -200 vm-smoke/published/console.log || true
271278
- uses: actions/upload-artifact@v7
272-
if: failure()
279+
if: failure() || cancelled()
273280
with:
274281
name: console-install
275282
path: vm-smoke/published/console.log
@@ -313,10 +320,10 @@ jobs:
313320
--hibernate --secure-boot
314321
315322
- name: guest console
316-
if: failure()
323+
if: failure() || cancelled()
317324
run: tail -200 vm-smoke/published/console.log || true
318325
- uses: actions/upload-artifact@v7
319-
if: failure()
326+
if: failure() || cancelled()
320327
with:
321328
name: console-hibernate
322329
path: vm-smoke/published/console.log
@@ -352,10 +359,10 @@ jobs:
352359
smoke_args: --dead-disk
353360

354361
- name: guest console
355-
if: failure()
362+
if: failure() || cancelled()
356363
run: tail -200 vm-smoke/dead-disk/console.log || true
357364
- uses: actions/upload-artifact@v7
358-
if: failure()
365+
if: failure() || cancelled()
359366
with:
360367
name: console-dead-disk
361368
path: vm-smoke/dead-disk/console.log
@@ -417,11 +424,11 @@ jobs:
417424
run: ./scripts/smoke.sh --iso --keep niri
418425

419426
- name: what the live session said
420-
if: failure()
427+
if: failure() || cancelled()
421428
run: tail -100 vm-smoke/niri-iso/console.log || true
422429

423430
- uses: actions/upload-artifact@v7
424-
if: failure()
431+
if: failure() || cancelled()
425432
with:
426433
name: iso-console
427434
path: vm-smoke/niri-iso/console.log

‎scripts/smoke.sh‎

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,33 +1474,61 @@ smoke_published() {
14741474
# boot on this disk powers off correctly, so this reaches
14751475
# Secure Boot from a cleanly stopped machine instead of from
14761476
# whatever a SIGKILL leaves on the filesystem.
1477-
local back=0
1478-
until guest true; do
1479-
[ $back -lt 300 ] \
1480-
|| bad "it neither powered off nor came back; console at $log"
1477+
#
1478+
# Three things can happen from here, and the first CI run to
1479+
# reach this point found the third. It can come back, which is
1480+
# what a laptop-hosted run does. It can go off late, after the
1481+
# 180s above but before this gives up -- and reading that as
1482+
# "it never came back" would be the same misdiagnosis this
1483+
# file keeps having to unlearn, so qemu's own exit is checked
1484+
# every time round. Or it can wedge: neither off nor back,
1485+
# which is what the hosted runner did on 2026-08-21.
1486+
local back=0 came_back=0
1487+
while :; do
1488+
if guest true; then came_back=1; break; fi
1489+
kill -0 "$qemu" 2>/dev/null || break
1490+
[ $back -lt 300 ] || break
14811491
sleep 5
14821492
back=$((back + 5))
14831493
done
1484-
# The dying boot's own account, taken while it is still the
1485-
# previous boot. The console cannot carry this and never
1486-
# could: `fbcon: Taking over console` moves systemd's output
1487-
# off ttyS0 on a desktop image, which is why run 10 read as
1488-
# "no shutdown output at all" and why that reading was wrong.
1489-
# The journal shows systemd running an ordinary shutdown and
1490-
# the machine dying about 180ms into it, with nothing logged
1491-
# at error level.
1492-
gsudo "journalctl -b -1 --no-pager -o short-monotonic" \
1493-
>"$dir/poweroff-reset.log" 2>/dev/null || true
1494-
1495-
gsudo "systemd-run --no-block systemctl poweroff" >/dev/null 2>&1 || true
1496-
off=0
1497-
while kill -0 "$qemu" 2>/dev/null && [ $off -lt 180 ]; do
1498-
sleep 5
1499-
off=$((off + 5))
1500-
done
1501-
kill -0 "$qemu" 2>/dev/null \
1502-
&& bad "it would not power off from a cold boot either; console at $log"
1503-
echo " .. off, from the boot it reset into"
1494+
1495+
if [ $came_back -eq 1 ]; then
1496+
# The dying boot's own account, taken while it is still the
1497+
# previous boot. The console cannot carry this and never
1498+
# could: `fbcon: Taking over console` moves systemd's output
1499+
# off ttyS0 on a desktop image, which is why run 10 read as
1500+
# "no shutdown output at all" and why that reading was wrong.
1501+
# The journal shows systemd running an ordinary shutdown and
1502+
# the machine dying about 180ms into it, with nothing logged
1503+
# at error level.
1504+
gsudo "journalctl -b -1 --no-pager -o short-monotonic" \
1505+
>"$dir/poweroff-reset.log" 2>/dev/null || true
1506+
1507+
gsudo "systemd-run --no-block systemctl poweroff" >/dev/null 2>&1 || true
1508+
off=0
1509+
while kill -0 "$qemu" 2>/dev/null && [ $off -lt 180 ]; do
1510+
sleep 5
1511+
off=$((off + 5))
1512+
done
1513+
kill -0 "$qemu" 2>/dev/null \
1514+
&& bad "it would not power off from a cold boot either; console at $log"
1515+
echo " .. off, from the boot it reset into"
1516+
elif kill -0 "$qemu" 2>/dev/null; then
1517+
# Wedged. Take it down by force rather than losing the
1518+
# Secure Boot half, which is a separate question about a
1519+
# separate boot and has nothing to do with this one. The
1520+
# console tail goes to the job log here and not only to
1521+
# the artifact, because the run that needed it most is the
1522+
# run whose artifact upload never happened.
1523+
resumed_poweroff=wedged
1524+
echo " .. it neither powered off nor came back in ${back}s; taking it down" >&2
1525+
echo " .. last 40 lines of console:" >&2
1526+
tail -40 "$log" >&2 || true
1527+
kill -9 "$qemu" 2>/dev/null || true
1528+
wait "$qemu" 2>/dev/null || true
1529+
else
1530+
echo " .. it went off ${back}s after being asked, later than the 180s allowed"
1531+
fi
15041532
else
15051533
ok "the resumed machine powered off rather than resetting"
15061534
fi
@@ -1558,14 +1586,26 @@ smoke_published() {
15581586
fi
15591587

15601588
if [ -n "$resumed_poweroff" ]; then
1561-
warn "the resumed guest reset instead of powering off (known QEMU artifact; hardware powers off, 2026-08-21)"
1562-
echo " systemd runs an ordinary shutdown and the machine dies partway"
1563-
echo " through it; the console cannot show that, because fbcon takes"
1564-
echo " ttyS0 on a desktop image. The dying boot's own journal is at"
1565-
echo " $dir/poweroff-reset.log. The same disk cold-booted powers off"
1566-
echo " correctly, and so does real hardware after a real resume, so"
1567-
echo " this belongs to hibernating under one OVMF instance and"
1568-
echo " resuming under another."
1589+
case "$resumed_poweroff" in
1590+
wedged)
1591+
warn "the resumed guest neither powered off nor came back, and was taken down by force (known QEMU artifact; hardware powers off, 2026-08-21)"
1592+
echo " It took the poweroff, stopped answering, and reached"
1593+
echo " neither S5 nor a fresh boot inside five minutes. There is"
1594+
echo " no journal to read, because the machine never came back to"
1595+
echo " be asked; the console tail is above and the whole log is"
1596+
echo " at $log"
1597+
;;
1598+
*)
1599+
warn "the resumed guest reset instead of powering off (known QEMU artifact; hardware powers off, 2026-08-21)"
1600+
echo " systemd runs an ordinary shutdown and the machine dies partway"
1601+
echo " through it; the console cannot show that, because fbcon takes"
1602+
echo " ttyS0 on a desktop image. The dying boot's own journal is at"
1603+
echo " $dir/poweroff-reset.log."
1604+
;;
1605+
esac
1606+
echo " The same disk cold-booted powers off correctly, and so does real"
1607+
echo " hardware after a real resume, so this belongs to hibernating under"
1608+
echo " one OVMF instance and resuming under another."
15691609
fi
15701610

15711611
# --- the cross-version half ----------------------------------------

0 commit comments

Comments
 (0)