From 2354fe4255900ea77f5fe39d1271d61eb86e2841 Mon Sep 17 00:00:00 2001 From: Sergio Date: Tue, 8 Sep 2026 16:11:47 +0000 Subject: [PATCH] =?UTF-8?q?CLAUDE.md:=20usar=20flock=20-o=20=E2=80=94=20un?= =?UTF-8?q?=20nieto=20fugado=20retiene=20el=20lock=20de=20la=20granja=20pa?= =?UTF-8?q?ra=20siempre?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit El lock lo sostiene la descripción de fichero abierta y los hijos la heredan. Medido hoy: dos firefox colgados de una caza sobrevivieron al kill del bwrap que los envolvía y dejaron a la granja sin poder compilar durante hora y media, sin que nada fallara — el siguiente flock simplemente espera. Comprobado en los dos sentidos con control positivo y negativo: flock lock sh -c 'sleep 25 & exit 0' ⇒ el nieto retiene el lock flock -o lock sh -c 'sleep 25 & exit 0' ⇒ lock libre Se añade también cómo diagnosticarlo (fuser -v sobre el fichero de lock, que nombra al proceso fugado) y se deja anotado que los scripts de scripts/farm/ usan el estilo 'exec 9>' + 'flock 9', vulnerable igual, como deuda conocida sin barrer. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2 --- CLAUDE.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index b61eb80e..afd38200 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,6 +25,23 @@ el fetch concurrente de otra receta. Es el **ADR 0012**, sin decidir; hasta que (lock por árbol / árbol privado / caché inmutable + copia), serializar es la única mitigación correcta. Por eso el worker corre con `JOBS=1`. +⚠ **Y usar `flock -o`, no `flock` a secas — esto es medido, no teórico (2026-09-08).** El lock lo +sostiene la *descripción de fichero abierta*, y los hijos la HEREDAN: si un nieto se fuga, el lock +queda tomado para siempre aunque el `flock` haya terminado hace rato. Pasó: dos `firefox` colgados de +una caza de bugs sobrevivieron al `kill` del `bwrap` que los envolvía y **dejaron a la granja sin +poder compilar durante hora y media, en silencio** — nada falla, simplemente el siguiente `flock` +espera para siempre. Comprobado en los dos sentidos: + +```sh +flock lock sh -c 'sleep 25 & exit 0' # ⇒ el nieto RETIENE el lock tras salir flock +flock -o lock sh -c 'sleep 25 & exit 0' # ⇒ lock LIBRE; -o cierra el fd antes de ejecutar +``` + +Si el lock parece tomado y no hay ningún build, `fuser -v work/.farm-build.lock` dice quién lo tiene; +casi siempre es un proceso fugado que nadie asocia con el lock. **Los scripts de `scripts/farm/` usan +el estilo `exec 9>` + `flock 9`, que es vulnerable igual** (haría falta `9>&-` en cada hijo): deuda +conocida, no barrida. + `scripts/farm/farm-worker-loop.sh` y `campana-deuda.sh` ya toman **ese mismo fichero de lock**, así que usarlo nos serializa con la granja además de entre nosotros. **No está dentro de `hammer build` a propósito**: esos scripts lo toman por fuera y hammer se bloquearía contra ellos.