cazador del cuelgue en headless: NO reproducido en 202 corridas, y qué descarta
Dos corridas del banco de PGO se colgaron en 120.034 y 120.030 ms — exactamente el timeout del arnés, o sea bloqueos y no lentitud. Dos de 56 (~3,5%). NO SE REPRODUJO. 202 corridas en cuatro condiciones, cero cuelgues: un binario, un sandbox compartido ......... 30 · 0 4 binarios alternando, un sandbox ......... 60 · 0 (descarta churn de caché) 4 binarios, UN SANDBOX NUEVO POR CORRIDA .. 56 · 0 (descarta los namespaces) ídem con LAS PÁGINAS EXACTAS del banco .... 56 · 0 (descarta la página) Si la tasa fuera 3,5%, ver cero en 202 tendría probabilidad ~0,06%. La tasa real bajo estas condiciones no es ésa, y lo que falta está fuera de ellas. UN ERROR DE MÉTODO QUE COSTÓ 146 CORRIDAS, anotado en el script para no repetirlo: las tres primeras cazas usaron flex.html y tablas.html porque las tenía a mano, cuando las colgadas habían sido en fuera-del-corpus.html y del-corpus.html. Estuve probando una condición que NO era la observada, creyendo que sí. Antes de concluir «no se reproduce», comprobar que el instrumento reproduce lo que dice reproducir. Lo que sí se aprendió, y acota: es TODO O NADA. En 202 corridas ninguna pasó siquiera de 45 s — o terminan en ~20 s o se bloquean hasta el timeout. No es degradación, es bloqueo. Sobrevive la hipótesis que no se puede probar retroactivamente: contención transitoria de otra cosa en la máquina —que es compartida con otros agentes— durante esas dos ventanas. El script queda para que la PRÓXIMA vez se capture en el acto (wchan, syscall, state, memoria y carga del host, y el log del navegador de esa corrida) en vez de empezar de cero.
This commit is contained in:
+77
@@ -0,0 +1,77 @@
|
||||
#!/bin/bash
|
||||
# cazar-cuelgue-headless.sh — cazador de un cuelgue INTERMITENTE de firefox en headless.
|
||||
#
|
||||
# ══ EL CASO, Y POR QUÉ ESTE SCRIPT SOBREVIVE AUNQUE NO LO RESOLVIÓ ═════════════════════════════
|
||||
# El 2026-09-08, dos corridas del banco de PGO se colgaron: 120.034 y 120.030 ms, o sea EXACTAMENTE
|
||||
# el `timeout 120` del arnés. No eran ruido de carga —una corrida normal son ~20 s— sino bloqueos
|
||||
# hasta que las maté. Dos de 56 (~3,5 %).
|
||||
#
|
||||
# NO SE REPRODUJO. 202 corridas en cuatro condiciones, CERO cuelgues:
|
||||
#
|
||||
# un binario, un sandbox compartido ............... 30 · 0
|
||||
# 4 binarios alternando, un sandbox ............... 60 · 0 (descarta churn de caché de página)
|
||||
# 4 binarios, UN SANDBOX NUEVO POR CORRIDA ........ 56 · 0 (descarta el montaje de namespaces)
|
||||
# ídem, con LAS PÁGINAS EXACTAS del banco ......... 56 · 0 (descarta la página)
|
||||
#
|
||||
# Si la tasa fuera 3,5 %, ver cero en 202 tendría probabilidad ~0,06 %. O sea que la tasa real bajo
|
||||
# estas condiciones NO es ésa, y lo que faltaba estaba fuera de ellas.
|
||||
#
|
||||
# ⚠ UN ERROR DE MÉTODO QUE COSTÓ 146 CORRIDAS, ANOTADO PARA NO REPETIRLO: las tres primeras cazas
|
||||
# usaron `flex.html` y `tablas.html` porque las tenía a mano, cuando las colgadas habían sido en
|
||||
# `fuera-del-corpus.html` y `del-corpus.html`. Estuve probando una condición que NO era la
|
||||
# observada, creyendo que sí. Antes de concluir «no se reproduce», comprobar que el instrumento
|
||||
# reproduce lo que dice reproducir.
|
||||
#
|
||||
# LO QUE SÍ SE APRENDIÓ, que acota al culpable:
|
||||
# · Es TODO O NADA. En 202 corridas ninguna pasó siquiera de 45 s: o terminan en ~20 s o se
|
||||
# bloquean hasta el timeout. No es lentitud ocasional, es un bloqueo.
|
||||
# · Sobrevive la hipótesis que no se puede probar retroactivamente: contención transitoria de otra
|
||||
# cosa en la máquina (es compartida con otros agentes) durante esas dos ventanas.
|
||||
#
|
||||
# ══ PARA QUÉ SIRVE ENTONCES ════════════════════════════════════════════════════════════════════
|
||||
# Para que la PRÓXIMA vez que aparezca, se capture en el acto en vez de empezar de cero: `wchan`,
|
||||
# `syscall` y `state` de cada proceso (distinguen espera de disco de espera de lock), memoria y
|
||||
# carga del host en ese instante, y el log del navegador de esa corrida —que en las buenas se tira—.
|
||||
#
|
||||
# Uso: N=56 UMBRAL=45 scripts/diagnostico/cazar-cuelgue-headless.sh
|
||||
# (necesita el rootfs hidratado en store/.rootfs/sway-v2 y las páginas en el scratchpad;
|
||||
# ajustar las rutas de arriba si se mueven)
|
||||
set -u
|
||||
RAIZ=/mnt/vvv/hammer; R=$RAIZ/store/.rootfs/sway-v2
|
||||
S=/tmp/claude-1001/-mnt-vvv-hammer/9d639cb7-92ff-4a26-bd7f-ec9988b972cf/scratchpad
|
||||
N=${N:-56}; UMBRAL=${UMBRAL:-45}
|
||||
FF=($(ls -d $RAIZ/store/8116bdec*-firefox $RAIZ/store/1d730334*-firefox \
|
||||
$RAIZ/store/3d199174*-firefox $RAIZ/store/bb33fd56*-firefox))
|
||||
PAGS=(fuera-del-corpus.html del-corpus.html) # LAS DEL BANCO: es donde ocurrieron las 2 colgadas
|
||||
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 \
|
||||
--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 \
|
||||
--setenv PATH /usr/bin:/bin \
|
||||
/bin/sh -c 'export HOME=/tmp/h MOZ_HEADLESS=1 MOZ_DISABLE_CONTENT_SANDBOX=1 LIBGL_ALWAYS_SOFTWARE=1 LANG=C.UTF-8; mkdir -p $HOME
|
||||
LD_LIBRARY_PATH=/usr/lib/firefox /usr/lib/firefox/firefox --headless --screenshot /salida/x.png "file:///bench/'"$pag"'"' \
|
||||
>/dev/null 2>&1 &
|
||||
BW=$!
|
||||
t=0
|
||||
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
|
||||
colgadas=$((colgadas+1))
|
||||
D=$S/caza4/colgada-$i; mkdir -p "$D"
|
||||
{ echo "corrida $i · $(basename $art | cut -c1-12) · $pag · colgada a los ${t}s"
|
||||
echo "--- memoria del host ---"; head -4 /proc/meminfo
|
||||
echo "--- carga ---"; cat /proc/loadavg; } > "$D/resumen.txt"
|
||||
ps -eo pid,ppid,stat,rss,wchan:24,comm 2>/dev/null | grep -iE 'bwrap|firefox|Web Con|Isolated|PID' > "$D/ps.txt"
|
||||
for p in $(pgrep -P $BW 2>/dev/null; pgrep -f 'usr/lib/firefox/firefox' 2>/dev/null | head -8); do
|
||||
{ echo "--- pid $p comm=$(cat /proc/$p/comm 2>/dev/null) state=$(awk '/^State:/{print $2,$3}' /proc/$p/status 2>/dev/null)"
|
||||
echo " wchan=$(cat /proc/$p/wchan 2>/dev/null)"
|
||||
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
|
||||
printf 'X'
|
||||
else printf '.'; fi
|
||||
done
|
||||
echo ""; echo "== colgadas: $colgadas de $N"
|
||||
Reference in New Issue
Block a user