From ccbf05e75868d335c6f23e711ee35eb9fa0b5d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Ferr=C3=A3o?= <2031761+viniciusferrao@users.noreply.github.com> Date: Sun, 6 Sep 2026 15:39:03 -0300 Subject: [PATCH] fix(xcat-dep): record a worker the kernel killed as failed A child killed by a signal leaves 0 in the high byte of its wait status. The per-codename worker loop read only that byte, so a cancelled or OOM-killed codename was counted as built, and the run could reach validation with the staging tree that worker never finished. One helper decodes a wait status for both the worker loop and run_bounded, and reports 128 plus the signal for a child the kernel killed. --- lib/XCAT/BuildUtils.pm | 13 +++++++++++-- sbuild-all.pl | 5 ++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/XCAT/BuildUtils.pm b/lib/XCAT/BuildUtils.pm index c0b4bc9..fc5172d 100644 --- a/lib/XCAT/BuildUtils.pm +++ b/lib/XCAT/BuildUtils.pm @@ -22,6 +22,7 @@ our @EXPORT_OK = qw( every_step_failed forward_signals_to_workers block_handled_signals + exit_status restore_signal_mask hashes_equal print_step @@ -202,6 +203,15 @@ sub stall_report { return $total; } +# exit_status($status): the exit code of a waited-for child, or 128 plus the signal that killed it. +# A child killed by a signal has 0 in the high byte, so reading only that byte reports a build the +# kernel terminated as a build that succeeded. +sub exit_status { + my ($status) = @_; + return 0 unless defined $status; + return ($status & 127) ? 128 + ($status & 127) : $status >> 8; +} + # block_handled_signals(): block INT, TERM and HUP and return the previous mask, for the window # between forking a child and being able to signal it. A cancellation arriving in that window would # otherwise kill the parent under a handler that does not know the child yet, and the child would @@ -323,8 +333,7 @@ sub run_bounded { return { ec => 124, timed_out => 1, elapsed => time - $t0 }; } - my $ec = ($status & 127) ? 128 + ($status & 127) : $status >> 8; - return { ec => $ec, timed_out => 0, elapsed => time - $t0 }; + return { ec => exit_status($status), timed_out => 0, elapsed => time - $t0 }; } sub display_quote { diff --git a/sbuild-all.pl b/sbuild-all.pl index 38eca37..5c9d9bd 100755 --- a/sbuild-all.pl +++ b/sbuild-all.pl @@ -662,7 +662,10 @@ sub build_deps { } my $pid = wait(); if ($pid > 0) { - my $ec = $? >> 8; + # A worker the kernel killed leaves 0 in the high byte, so the shifted status alone + # would record a cancelled or OOM-killed codename as built. + require XCAT::BuildUtils; + my $ec = XCAT::BuildUtils::exit_status($?); my $cn = delete $pid2cn{$pid} // '?'; $fail{$cn} = $ec if $ec != 0; $running--;