worker-loop: que el watchdog no se lleve el post-mortem
El watchdog barre work/sources/* cada 180 s con un suelo de 2 minutos, así que
el árbol de una receta que ACABA DE FALLAR se destruye antes de que nadie lo
mire. Medido hoy: waterfox murió a las 03:20:15 tras 36 minutos y 23.980 pasos,
enlazando libxul.so con un `collect2: error: ld returned 1 exit status` SIN
mensaje del linker delante — o sea justo el caso en que hace falta el objdir. A
las 03:22 work/sources/ estaba vacío. Reproducirlo cuesta otros 36 minutos.
Lo que más molesta es que la doctrina ya estaba escrita en el repo, en dos
sitios, y este watchdog la contradecía sin que nadie lo notara:
campana-deuda.sh:138 «NO se poda tras un ✗: el árbol de una receta que falló
es el post-mortem»
poda-fuentes.sh suelo de 24 h, «deja el post-mortem del día»
No se arregla subiendo el suelo a secas: este watchdog existe para que una tanda
Go no llene el disco vendoreando, y ahí los minutos importan de verdad (80 G en
una tanda, con el I/O-wait disparando el load). Se arregla siendo agresivo SÓLO
cuando el recurso escasea: con el disco por debajo de DISK_HIGH el suelo pasa a
SUELO_FRIO_MIN (120 min por defecto, configurable); en cuanto el disco aprieta
vuelve a los 2 minutos de siempre. Un árbol frío con disco al 37% no le hace
daño a nadie.
Probado en los dos sentidos: árbol de 5 min -> se borra con suelo 2, protegido
con suelo 120; árbol de 3 h -> se borra con los dos (ya no es post-mortem).
Ojo al leerlo: `df --output=pcent` da el porcentaje USADO, no el libre. La
primera versión de este parche llamaba `libre` a esa variable.
Delta semántico
Ninguna definición cambió: el cambio es de texto, documentación o datos.
1 archivos · +20 −1
diff --git a/scripts/farm/farm-worker-loop.sh b/scripts/farm/farm-worker-loop.sh
index 60d5d200..27e77310 100755
--- a/scripts/farm/farm-worker-loop.sh
+++ b/scripts/farm/farm-worker-loop.sh
@@ -36,6 +36,9 @@ mkdir -p "$HAMMER_DIR/work"
# pisa un vendor en curso, esa receta reintenta el próximo ciclo (cache-hit el resto). Sin esto, una
# tanda Go grande llena el disco de 80G y el I/O-wait dispara el load (cuello real, no CPU/RAM).
DISK_HIGH="${DISK_HIGH:-82}"
+# Cuántos minutos se le respetan a un árbol EN FRÍO cuando el disco NO está apretado. Es la ventana
+# de post-mortem: por debajo de esto, un fallo se lleva su propia evidencia (ver protección 4).
+SUELO_FRIO_MIN="${SUELO_FRIO_MIN:-120}"
(
while :; do
sleep 180
@@ -56,7 +59,23 @@ DISK_HIGH="${DISK_HIGH:-82}"
# que NO coincide con la receta en vuelo ⇒ protecciones 1 y 2 no la cubren. Sin esto, el rm -rf
# compite con el tar y deja el árbol a medias ("Cannot mkdir" / luego "Directory not empty" para
# siempre). Un árbol en frío (extracción ya fallida/terminada) queda purgable ⇒ se re-extrae limpio.
- [ -n "$(find "$dd" -mmin -2 -print -quit 2>/dev/null)" ] && continue
+ # Protección 4: EL POST-MORTEM (2026-09-06). Con el suelo en 2 min, el árbol de una receta que
+ # ACABA DE FALLAR se barre antes de que nadie lo mire: `waterfox` murió a las 03:20:15 tras 36
+ # min y 23.980 pasos, enlazando `libxul.so`, y a las 03:22 `work/sources/` estaba VACÍO. El
+ # objdir con la evidencia se fue con él y reproducirlo cuesta otros 36 min.
+ #
+ # El repo ya tiene la doctrina escrita en otros dos sitios y este watchdog la contradecía:
+ # `campana-deuda.sh` dice «NO se poda tras un ✗: el árbol de una receta que falló es el
+ # post-mortem», y `poda-fuentes.sh` usa un suelo de 24 h justamente para «dejar el post-mortem
+ # del día».
+ #
+ # No se arregla subiendo el suelo a secas: este watchdog existe para que una tanda Go no llene
+ # el disco vendoreando, y ahí los minutos importan. Se arregla siendo agresivo SÓLO cuando el
+ # recurso escasea de verdad — con disco holgado, un árbol frío no le hace daño a nadie.
+ usado=$(df --output=pcent "$HAMMER_DIR" 2>/dev/null | tr -dc '0-9') # pcent = USADO, no libre
+ suelo=$SUELO_FRIO_MIN
+ [ -n "$usado" ] && [ "$usado" -ge "$DISK_HIGH" ] && suelo=2 # disco apretado ⇒ como antes
+ [ -n "$(find "$dd" -mmin -"$suelo" -print -quit 2>/dev/null)" ] && continue
rm -rf "$dd"
done
use=$(df --output=pcent "$HAMMER_DIR" 2>/dev/null | tr -dc '0-9')