gioser

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1184Shell 70Rust 62Markdown 501503 Definitions

fix(granja): dos recetas bloqueadas por el límite de DESCRIPTORES, no por un bug suyo

`obs-studio` y `spectacle` fallaban las dos con la misma línea:

```
error: failed to open object libavcodec/x86/rv34dsp_init.o: ProcessFdQuotaExceeded
make: *** [ffbuild/library.mak:119: libavcodec/libavcodec.so.61] Error 1
```

No es un fallo de ffmpeg: **libavcodec tiene 1.093 ficheros `.o` y el límite BLANDO era 1024**. El
enlazador los abre a la vez y se pasa por 69. El límite DURO es 524288, así que subir el blando no
necesita privilegios — nadie lo había subido porque 1024 alcanza para todo lo demás del corpus.

**Es el tercer miembro de la misma familia, y conviene verlo junto:** bytes (disco lleno ⇒ ✗ en
recetas sanas), inodos (`df -h` al 90 % con cero inodos ⇒ «0 fallan» mentiroso) y ahora fds. Los
tres son límites de la MÁQUINA que el informe presenta como defecto de la RECETA, y los tres cuestan
el mismo rato: alguien se sienta a leer `obs-studio.toml` buscando un bug que no está ahí.

Se sube en los dos puntos de entrada de la granja —el loop y `build-farm.sh`— y no en la unidad de
systemd, porque estos guiones VIAJAN con el código: una unidad que vive sólo en el worker se pierde
el día que la caja se rehaga, y eso ya pasó con otras cosas. Se clampa al límite duro y **se dice lo
que se hizo**: un límite que cambia en silencio es un límite que nadie sabe que existe hasta que
vuelve a estorbar.

Comprobado en el worker: `==> fds: límite blando 1024 → 65536 (duro: 524288)`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

8c3d6cb0fad559c17a30c8b84478cc7d546fda55 · by Sergio · (11 d ago) · parent 591a72202 · browse the tree at this commit

Semantic delta

No definition changed: this change is text, documentation or data.

2 files · +64 −0

diff --git a/scripts/build-farm.sh b/scripts/build-farm.sh
index 8c0e8ca1..2767ab4d 100755
--- a/scripts/build-farm.sh
+++ b/scripts/build-farm.sh
@@ -87,6 +87,38 @@ fi
 # `grep -v` porque el acumulador del filtro arranca con una línea vacía, y una línea vacía es un
 # elemento más para `xargs -I{}`: construiría la receta "" y ensuciaría el conteo.
 queue=$(printf '%s\n' "$queue" | grep -v '^[[:space:]]*$' || true)
+# ── ⚠ EL LÍMITE DE DESCRIPTORES, QUE SE LEE COMO RECETA ROTA (2026-10-11) ────────────────────
+# Medido en el worker: `obs-studio` y `spectacle` fallaban las dos con
+#
+#     error: failed to open object libavcodec/x86/rv34dsp_init.o: ProcessFdQuotaExceeded
+#     make: *** [ffbuild/library.mak:119: libavcodec/libavcodec.so.61] Error 1
+#
+# y no es un fallo de ffmpeg: **libavcodec tiene 1.093 ficheros `.o` y el límite BLANDO era 1024**.
+# El enlazador los abre a la vez y se pasa por 69. El límite DURO es 524288, así que subir el blando
+# no necesita privilegios — nadie lo había subido porque el default de 1024 alcanza para todo lo
+# demás del corpus.
+#
+# Es el tercer miembro de la misma familia, y conviene verlo junto: **bytes** (disco lleno ⇒ ✗ en
+# recetas sanas), **inodos** (`df -h` al 90 % y cero inodos ⇒ «0 fallan» mentiroso) y ahora **fds**.
+# Los tres son límites de la MÁQUINA que el informe presenta como defecto de la RECETA, y los tres
+# cuestan el mismo rato: alguien lee `obs-studio.toml` buscando un bug que no está ahí.
+#
+# Se sube acá y no en la unidad de systemd porque este guion VIAJA con el código: una unidad que
+# vive sólo en el worker se pierde el día que la caja se rehaga, y eso ya pasó con otras cosas.
+_subir_fds() {
+  local duro blando quiero=65536
+  duro=$(ulimit -Hn 2>/dev/null) || return 0
+  blando=$(ulimit -Sn 2>/dev/null) || return 0
+  [ "$duro" = "unlimited" ] && duro=$quiero
+  [ "$quiero" -gt "$duro" ] && quiero=$duro
+  if [ "$blando" -lt "$quiero" ] 2>/dev/null; then
+    # Se DICE lo que se hizo: un límite que cambia en silencio es un límite que nadie sabe que
+    # existe hasta que vuelve a estorbar.
+    ulimit -n "$quiero" 2>/dev/null && echo "==> fds: límite blando $blando → $quiero (duro: $duro)"
+  fi
+}
+_subir_fds
+
 n_total=$(printf '%s\n' "$queue" | grep -c . || true)
 echo "==> GRANJA: $n_total recetas en $QUEUE, $JOBS workers en paralelo"
 
diff --git a/scripts/farm/farm-worker-loop.sh b/scripts/farm/farm-worker-loop.sh
index 273cacba..17b2f14d 100755
--- a/scripts/farm/farm-worker-loop.sh
+++ b/scripts/farm/farm-worker-loop.sh
@@ -22,6 +22,38 @@ cd "$HAMMER_DIR"
 # El reintento serial de build-farm tampoco las salva, porque el árbol ya quedó inconsistente.
 # Serializar es la única mitigación correcta hasta que el ADR 0012 elija (lock por árbol / árbol
 # privado / caché inmutable + copia). Subirlo otra vez sin resolver eso reintroduce el bug.
+# ── ⚠ EL LÍMITE DE DESCRIPTORES, QUE SE LEE COMO RECETA ROTA (2026-10-11) ────────────────────
+# Medido en el worker: `obs-studio` y `spectacle` fallaban las dos con
+#
+#     error: failed to open object libavcodec/x86/rv34dsp_init.o: ProcessFdQuotaExceeded
+#     make: *** [ffbuild/library.mak:119: libavcodec/libavcodec.so.61] Error 1
+#
+# y no es un fallo de ffmpeg: **libavcodec tiene 1.093 ficheros `.o` y el límite BLANDO era 1024**.
+# El enlazador los abre a la vez y se pasa por 69. El límite DURO es 524288, así que subir el blando
+# no necesita privilegios — nadie lo había subido porque el default de 1024 alcanza para todo lo
+# demás del corpus.
+#
+# Es el tercer miembro de la misma familia, y conviene verlo junto: **bytes** (disco lleno ⇒ ✗ en
+# recetas sanas), **inodos** (`df -h` al 90 % y cero inodos ⇒ «0 fallan» mentiroso) y ahora **fds**.
+# Los tres son límites de la MÁQUINA que el informe presenta como defecto de la RECETA, y los tres
+# cuestan el mismo rato: alguien lee `obs-studio.toml` buscando un bug que no está ahí.
+#
+# Se sube acá y no en la unidad de systemd porque este guion VIAJA con el código: una unidad que
+# vive sólo en el worker se pierde el día que la caja se rehaga, y eso ya pasó con otras cosas.
+_subir_fds() {
+  local duro blando quiero=65536
+  duro=$(ulimit -Hn 2>/dev/null) || return 0
+  blando=$(ulimit -Sn 2>/dev/null) || return 0
+  [ "$duro" = "unlimited" ] && duro=$quiero
+  [ "$quiero" -gt "$duro" ] && quiero=$duro
+  if [ "$blando" -lt "$quiero" ] 2>/dev/null; then
+    # Se DICE lo que se hizo: un límite que cambia en silencio es un límite que nadie sabe que
+    # existe hasta que vuelve a estorbar.
+    ulimit -n "$quiero" 2>/dev/null && echo "==> fds: límite blando $blando → $quiero (duro: $duro)"
+  fi
+}
+_subir_fds
+
 JOBS="${JOBS:-1}"
 IDLE_SLEEP="${IDLE_SLEEP:-300}"
 # Fichero de lock compartido con campana-deuda.sh (mismo path en los dos, o no hay exclusión).