archlinux-s390x/scripts/lib-watch.sh
Mathieu Benoit eafa3355aa [FIX] stage 2: the build tools the host was providing silently
glibc rebuilt inside the chroot; binutils died on `make info-recursive`, and
makeinfo said why: its XS module was compiled against the host's perl 5.40 and
our perl is 5.42. Stage-1 texinfo cannot run in there. Everything that builds
.info documentation needs it, and it sat near the end of the list because that
is where its own dependencies are, so stage 2 hoists it.

linux-api-headers stopped earlier on `rsync: command not found` -- the kernel's
headers_install runs it. apt had put it there and a build that finds its tool
says nothing, so stage 1 never mentioned it. Its man pages come from Markdown
the git tag does not pre-render, hence --disable-md2man.

An inventory of the 110 apt packages against the chroot found 84 more such
binaries. Most are documentation; the rest wait until something needs them.

--- FR ---

glibc a été rebâti dans le chroot ; binutils est mort sur `make info-recursive`,
et makeinfo en donne la raison : son module XS a été compilé contre le perl 5.40
de l'hôte, or le nôtre est en 5.42. Le texinfo de l'étage 1 ne peut pas tourner
là-dedans. Tout ce qui bâtit de la documentation .info en dépend, et il figurait
en fin de liste, là où sont ses propres dépendances : l'étage 2 le remonte.

linux-api-headers s'était arrêté avant sur `rsync: command not found` — le
headers_install du noyau l'appelle. apt l'avait posé, et une construction qui
trouve son outil n'en dit rien : l'étage 1 ne l'a jamais mentionné. Ses pages de
manuel viennent d'un Markdown que l'étiquette git ne rend pas, d'où
--disable-md2man.

Un inventaire des 110 paquets apt face au chroot a trouvé 84 autres binaires du
même genre. La plupart sont de la documentation ; le reste attendra qu'un paquet
les réclame.

Assisted-by: Claude Opus 5
2026-08-20 01:34:41 -04:00

57 lines
2.2 KiB
Bash

#!/usr/bin/env bash
# The stall guard, and nothing else.
#
# WHY ITS OWN FILE. It belongs to both stages, so the obvious home was
# bootstrap-pacman.sh, which stage 1 already sources. Stage 2 cannot source
# that file: it opens with `set -euo pipefail`, and stage 2's whole rebuild
# loop depends on a failed package NOT ending the run -- one missing package
# must not hide the state of the hundred that follow. It also defines a main(),
# which is a second thing to be careful about for no benefit.
#
# So: one file, no `set -e`, no side effects, sourced by both. Nothing else
# goes in here.
# Run a command, and kill it if it stops saying anything.
#
# watched <logfile> <command...>
#
# Returns the command's status, or 2 if it was killed for silence.
#
# WHY IT EXISTS. python's build ran for ten hours. It was not slow: it was
# spinning in a shell loop waiting for an X server that this port will never
# have, printing nothing. Nothing distinguished it from a long compile except
# that the log had not grown -- and that is a measurement, so it can be made
# automatically.
#
# Both stages need it, and stage 2 needs it MORE: stage 2 runs the test suites
# that stage 1 skipped, and a test suite is the likeliest thing in a build to
# wait forever on a terminal, a network socket, or a display.
#
# Killed as a PROCESS GROUP -- set -m gives the subshell its own, so make and
# every compiler under it die too. Killing the pid alone leaves the tree
# running, holding the disk, invisible to the driver that thinks it stopped it.
watched() {
local log="$1"; shift
local limit="${EL_STALL_MIN:-45}"
if [ "$limit" -eq 0 ]; then
"$@" > "$log" 2>&1
return $?
fi
set -m
( "$@" ) > "$log" 2>&1 &
local pid=$! last=0 still=0 sz
set +m
while kill -0 "$pid" 2>/dev/null; do
sleep 60
sz=$(stat -c %s "$log" 2>/dev/null || echo 0)
if [ "$sz" -eq "$last" ]; then still=$((still + 1)); else still=0; fi
last="$sz"
if [ "$still" -ge "$limit" ]; then
printf '\n== driver: no output for %s minutes, killing ==\n' "$limit" >> "$log"
kill -9 -- "-$pid" 2>/dev/null
wait "$pid" 2>/dev/null
return 2
fi
done
wait "$pid"
}