From 4395cb95368acfffd72707cddf69a5c625d3ee64 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 01:57:19 -0300 Subject: [PATCH] fix(xcat-dep): reach the per-package builder when a build is cancelled The worker spawned the builder with system(), so the builder, its schroot session and qemu were in the worker's process group but owned by nobody: a cancelled worker died and left them running, holding the chroot and writing into staging. Only the build inside the builder was protected, and nothing signalled the builder. The builder now runs through run_bounded, which gives it its own process group and forwards the signal, so one cancellation unwinds the whole chain. The wall-clock bound stays with the builder, which derives it from the chroot arch. A forked worker also drops the parent's forwarder, whose copy names siblings the parent already signals. --- sbuild-all.pl | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sbuild-all.pl b/sbuild-all.pl index 8015c3d..e920526 100755 --- a/sbuild-all.pl +++ b/sbuild-all.pl @@ -594,7 +594,17 @@ sub build_one_codename { '>', sh_quote($log), '2>&1', ); print " [$cn] -> $pkg ($dir/sbuild.pl)\n"; - my $ec = run($cmd, nofail => 1); + # run_bounded, not run(): it puts the builder in its own process group and forwards a + # signal to it. system() would leave the builder, its schroot session and qemu running + # after this worker died, holding the chroot and writing into staging. The wall-clock + # bound belongs to the builder itself, so this call only carries the cancellation. + print "+ $cmd\n"; + my $ec = 0; + unless ($dry_run) { + require XCAT::BuildUtils; + $ec = XCAT::BuildUtils::run_bounded(cmd => $cmd, timeout => 0, + label => "[$cn] $pkg", out => \*STDOUT)->{ec}; + } if ($ec != 0) { warn "FATAL: [$cn] $pkg build failed (rc=$ec) -- see $log\n"; return 1; } } print "== [$cn] done ==\n"; @@ -633,7 +643,12 @@ sub build_deps { my $cn = shift @queue; my $pid = fork(); die "FATAL: fork failed: $!\n" unless defined $pid; - if ($pid == 0) { exit(build_one_codename($cn)); } # child + # The child must not inherit the parent's forwarder: its copy names sibling workers, + # which the parent already signals. + if ($pid == 0) { + $SIG{$_} = 'DEFAULT' for qw(INT TERM HUP); + exit(build_one_codename($cn)); + } $pid2cn{$pid} = $cn; $running++; } my $pid = wait();