From 0d7beefb606fae8408c2936427cec4433892562f Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 8 Sep 2026 18:12:31 +0000 Subject: [PATCH] =?UTF-8?q?cazadores:=20setsid=20+=20matar=20el=20GRUPO=20?= =?UTF-8?q?=E2=80=94=20mataban=20el=20bwrap=20y=20el=20firefox=20sobreviv?= =?UTF-8?q?=C3=ADa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Segunda vez el mismo día: un firefox colgado de la verificación A/B se quedó con el lock de build de la granja. La causa es del arnés, no de firefox: 'kill $BW' mata el bwrap EXTERIOR, que no es el init del namespace de PID, así que el proceso de dentro sigue vivo — y si el arnés corría bajo flock, hereda el fd del lock y deja a la granja muda hasta que alguien mire. Medido con control negativo y positivo: matar sólo el bwrap → queda 1 firefox vivo (reproduce la fuga) setsid + matar grupo → quedan 0 (arreglado) Se documenta además que el 'flock' del uso lleva '-o', que no es opcional. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2 --- scripts/diagnostico/cazar-cuelgue-bajo-presion.sh | 13 ++++++++++--- scripts/diagnostico/cazar-cuelgue-headless.sh | 9 +++++++-- scripts/diagnostico/verificar-arreglo-sandbox.sh | 9 +++++++-- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/scripts/diagnostico/cazar-cuelgue-bajo-presion.sh b/scripts/diagnostico/cazar-cuelgue-bajo-presion.sh index 1bd5831d..eb815e5d 100755 --- a/scripts/diagnostico/cazar-cuelgue-bajo-presion.sh +++ b/scripts/diagnostico/cazar-cuelgue-bajo-presion.sh @@ -26,7 +26,9 @@ # matar a alguien es a él, nunca a un build de la granja. Y toda la caza corre con el flock de la # granja tomado, para que no arranque una compilación de 4 h mientras se estrangula la RAM. # -# Uso: N=20 scripts/diagnostico/cazar-cuelgue-bajo-presion.sh +# Uso: N=20 flock -o work/.farm-build.lock scripts/diagnostico/cazar-cuelgue-bajo-presion.sh +# El `-o` NO es opcional: sin él, un firefox que se cuelgue hereda el fd del lock y lo +# retiene DESPUÉS de que el arnés termine (regla 1 de CLAUDE.md). Pasó dos veces. set -u RAIZ=/mnt/vvv/hammer; R=$RAIZ/store/.rootfs/sway-v2 AQUI=$(cd "$(dirname "$0")" && pwd) @@ -55,7 +57,12 @@ for NIVEL in 0 2000 1200 700; do colg=0; muer=0; ok=0 for i in $(seq 1 $N); do d0=$(disp); p0=$(psi); o0=$(ooms) - bwrap --ro-bind "$R" / --ro-bind /usr/lib/musl/lib/libc.so /lib/ld-musl-x86_64.so.1 \ + # ⚠ `setsid` + matar el GRUPO, no el bwrap (medido 2026-09-08, DOS veces el mismo día). + # `kill $BW` mata el bwrap EXTERIOR, que no es el init del namespace de PID: el firefox de + # dentro sobrevive. Y si el arnés corría bajo `flock`, ese superviviente HEREDA el fd del lock + # y deja a la granja sin poder compilar hasta que alguien lo note — pasó hora y media, en + # silencio. Medido: matando sólo el bwrap queda 1 firefox vivo; matando el grupo, 0. + setsid bwrap --ro-bind "$R" / --ro-bind /usr/lib/musl/lib/libc.so /lib/ld-musl-x86_64.so.1 \ --ro-bind "${FF[$(( i % 2 ))]}/usr/lib/firefox" /usr/lib/firefox \ --dev /dev --proc /proc --tmpfs /run --tmpfs /tmp --unshare-pid \ --ro-bind "$AQUI" /bench --bind "$SAL" /salida --unshare-user --uid 0 --gid 0 \ @@ -80,7 +87,7 @@ for NIVEL in 0 2000 1200 700; do echo " rss=$(awk '/^VmRSS:/{print $2,$3}' /proc/$p/status 2>/dev/null)"; } >>"$D/procesos.txt" 2>/dev/null done cp "$SAL/nav-$i.log" "$D/navegador.log" 2>/dev/null - kill -TERM $BW 2>/dev/null; sleep 3; kill -KILL $BW 2>/dev/null; printf 'X' + kill -TERM -$BW 2>/dev/null; sleep 3; kill -KILL -$BW 2>/dev/null # el GRUPO; printf 'X' else wait $BW; rc=$? od=$(( $(ooms) - o0 )) diff --git a/scripts/diagnostico/cazar-cuelgue-headless.sh b/scripts/diagnostico/cazar-cuelgue-headless.sh index feba49c8..4b4949bc 100755 --- a/scripts/diagnostico/cazar-cuelgue-headless.sh +++ b/scripts/diagnostico/cazar-cuelgue-headless.sh @@ -130,7 +130,12 @@ PAGS=(fuera-del-corpus.html del-corpus.html) # LAS DEL BANCO: es donde ocurrie colgadas=0 for i in $(seq 1 $N); do art=${FF[$(( i % 4 ))]}; pag=${PAGS[$(( i % 2 ))]} - bwrap --ro-bind "$R" / --ro-bind /usr/lib/musl/lib/libc.so /lib/ld-musl-x86_64.so.1 \ + # ⚠ `setsid` + matar el GRUPO, no el bwrap: `kill $BW` mata el bwrap EXTERIOR, que no es el init + # del namespace de PID, y el firefox de dentro SOBREVIVE. Si el arnés corre bajo `flock`, ese + # superviviente hereda el fd del lock y deja a la granja sin compilar hasta que alguien lo note + # (pasó dos veces el 2026-09-08, hora y media la primera). Medido: matando sólo el bwrap queda + # 1 firefox vivo; matando el grupo, 0. + setsid bwrap --ro-bind "$R" / --ro-bind /usr/lib/musl/lib/libc.so /lib/ld-musl-x86_64.so.1 \ --ro-bind "$art/usr/lib/firefox" /usr/lib/firefox \ --dev /dev --proc /proc --tmpfs /run --tmpfs /tmp --unshare-pid \ --ro-bind "$S/bench" /bench --bind "$S/caza4" /salida --unshare-user --uid 0 --gid 0 \ @@ -154,7 +159,7 @@ for i in $(seq 1 $N); do echo " syscall=$(cut -c1-70 /proc/$p/syscall 2>/dev/null)" echo " rss=$(awk '/^VmRSS:/{print $2,$3}' /proc/$p/status 2>/dev/null)"; } >> "$D/procesos.txt" 2>/dev/null done - kill -TERM $BW 2>/dev/null; sleep 3; kill -KILL $BW 2>/dev/null + kill -TERM -$BW 2>/dev/null; sleep 3; kill -KILL -$BW 2>/dev/null # el GRUPO printf 'X' else printf '.'; fi done diff --git a/scripts/diagnostico/verificar-arreglo-sandbox.sh b/scripts/diagnostico/verificar-arreglo-sandbox.sh index 7e70d5c4..4209f051 100755 --- a/scripts/diagnostico/verificar-arreglo-sandbox.sh +++ b/scripts/diagnostico/verificar-arreglo-sandbox.sh @@ -26,7 +26,12 @@ for i in $(seq 1 $N); do for k in viejo nuevo; do [ $k = viejo ] && ENV="$VIEJO" || ENV="$NUEVO" SAL=$(mktemp -d) - bwrap --ro-bind "$R" / --ro-bind /usr/lib/musl/lib/libc.so /lib/ld-musl-x86_64.so.1 \ + # ⚠ `setsid` + matar el GRUPO, no el bwrap (medido 2026-09-08, DOS veces el mismo día). + # `kill $BW` mata el bwrap EXTERIOR, que no es el init del namespace de PID: el firefox de + # dentro sobrevive. Y si el arnés corría bajo `flock`, ese superviviente HEREDA el fd del lock + # y deja a la granja sin poder compilar hasta que alguien lo note — pasó hora y media, en + # silencio. Medido: matando sólo el bwrap queda 1 firefox vivo; matando el grupo, 0. + setsid bwrap --ro-bind "$R" / --ro-bind /usr/lib/musl/lib/libc.so /lib/ld-musl-x86_64.so.1 \ --ro-bind "$A/usr/lib/firefox" /usr/lib/firefox --dev /dev --proc /proc --tmpfs /run --tmpfs /tmp \ --unshare-pid --ro-bind "$AQUI" /bench --bind "$SAL" /salida --unshare-user --uid 0 --gid 0 \ --setenv PATH /usr/bin:/bin --setenv APAGA "$ENV" \ @@ -37,7 +42,7 @@ for i in $(seq 1 $N); do while kill -0 $BW 2>/dev/null && [ $t -lt $UMBRAL ]; do sleep 1; t=$((t+1)); done if kill -0 $BW 2>/dev/null; then COLG[$k]=$(( ${COLG[$k]} + 1 )); cp -r "$SAL" "$RAIZ/work/colgada-$k-$i" 2>/dev/null - kill -TERM $BW 2>/dev/null; sleep 3; kill -KILL $BW 2>/dev/null + kill -TERM -$BW 2>/dev/null; sleep 3; kill -KILL -$BW 2>/dev/null # el GRUPO else wait $BW 2>/dev/null SEGV[$k]=$(( ${SEGV[$k]} + $(grep -c 'exited on signal 11' "$SAL/nav.log") ))