No era la presión de memoria. La caza bajo presión (4 niveles × 20 corridas, con el nivel de
presión MEDIDO por MemAvailable y PSI) reprodujo el cuelgue por primera vez en 282 corridas
—2 de 80, 2,5%, compatible con el 3,5% original— pero SIN dosis-respuesta: los dos cuelgues
cayeron en el nivel con PSI 0,00 y los dos niveles apretados dieron cero.
Tres hipótesis muertas, cada una con su medición:
· OOM se lleva al hijo → oom_kill de /proc/vmstat no se movió (delta=0) y los hijos vivían
· presión de memoria → sin dosis-respuesta
· fork server de Gecko → A/B del pref: el proceso forkserver desaparece (35 muestras → 0,
o sea que el pref hizo efecto) y siguen los mismos 2 segfaults
La causa apareció comparando el log de una colgada con el de una BUENA, que es lo que faltaba:
en las 6 buenas TAMBIÉN revientan 2 hijos con SIGSEGV, después de escribir el PNG y por eso
invisibles. Muestreando /proc adentro, se llaman 'Sandbox Forked': los ayudantes que el sandbox
propio de Firefox forkea para montar su user-namespace, que no puede montar porque ya estamos
dentro del de bwrap ('writing /proc/self/uid_map: EPERM').
Las tres cantidades bajan juntas hasta cero, que es forma de cadena causal:
sandbox completo segv=7 SIN screenshot EPERM=9 SandboxForked=725
content.level=0 segv=2 con screenshot EPERM=2 SandboxForked=68
los 3 prefs .level a 0 segv=1 con screenshot EPERM=1 SandboxForked=33
las 5 MOZ_DISABLE_* segv=0 con screenshot EPERM=0 SandboxForked=0
Y el sandbox completo cuelga DETERMINISTA (rc=124 a los 180 s). Comparte familia con el
intermitente pero no está probado que sean el mismo: al determinista le faltan los 'Failed to
launch'. Queda dicho como lo que es.
Arreglo para cualquier firefox headless en bwrap (donde el sandbox de Gecko no aporta nada,
porque bwrap ya es la jaula):
MOZ_DISABLE_{CONTENT,GMP,RDD,SOCKET_PROCESS,UTILITY}_SANDBOX=1
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QPJteswQvP1L7zSBrQQe2