Volver a la wiki

Incidente: Vigilante de auto-update muere silenciosamente post-swap (Agent 2.13.2, 03-07 y 05-07)

Resumen

El watchdog (vigilante) que monitorea y recupera un auto-update fallido del Agente Local moría antes de escribir su primera línea de log, quedando el Agente completamente muerto si el antivirus bloqueaba el arranque de la versión recién descargada.

Ocurrencias:

Causa raíz: Uso de flag DETACHED_PROCESS en el Popen del script PowerShell del watchdog, que priva a la consola de Windows de acceso válido → PowerShell muere en la inicialización del host antes de ejecutar el script.

Estado: ✅ RESUELTO en Agent 2.13.3 (APP v1.45.9, commit be210c6).


Línea temporal

FechaEventoNota
2.11.4+Watchdog introducido (agent-robustez F2)El vigilante debe relanzar la versión nueva o revertir la anterior si falla el arranque
2.13.1Traza persistente en update_watchdog.logPrimera evidencia: “watchdog lanzado (pid XXXX)” pero .ps1 jamás escribía su log
03-07-2026Primer incidente reportadoAgente muere tras actualización; recuperación manual
05-07-2026Segundo incidente + diagnósticoSwap 2.13.1→2.13.2: registro de lanzamiento del PID pero log vacío → pista decisiva
05-07 12:56Causa raíz cazada y fix verificadoDETACHED_PROCESS + CREATE_NO_WINDOW son modos excluyentes → PowerShell sin handles válidos
05-07 11:24Fix mergeado a main (2.13.3)Nueva línea de flags: CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW + DEVNULL en 3 handles

Descripción técnica

Síntoma observado

En update_watchdog.log (introducido en 2.13.1):

[2026-07-05 12:56:00] Swap a v2.13.2: watchdog lanzado (pid 20072, powershell)
[log vacío hasta el siguiente arranque del Agente]

El watchdog nunca ejecutó su primera línea de log, pese a tener un PID válido.

Diagnóstico reproducido en laboratorio

Código problemático (hasta 2.13.2):

proc = subprocess.Popen(
    [ps_exe, "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-File", str(ps1)],
    creationflags=subprocess.DETACHED_PROCESS
    | subprocess.CREATE_NEW_PROCESS_GROUP
    | getattr(subprocess, "CREATE_NO_WINDOW", 0),
)

El problema:

Por qué es silencioso:

Solución (Agent 2.13.3)

proc = subprocess.Popen(
    [ps_exe, "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-File", str(ps1)],
    creationflags=subprocess.CREATE_NEW_PROCESS_GROUP | getattr(subprocess, "CREATE_NO_WINDOW", 0),
    stdin=subprocess.DEVNULL,
    stdout=subprocess.DEVNULL,
    stderr=subprocess.DEVNULL,
    close_fds=True,
)

Cambios:

  1. ❌ Eliminar DETACHED_PROCESS (causaba conflicto con CREATE_NO_WINDOW).
  2. ✅ Mantener CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW (consola propia y oculta).
  3. ✅ Asignar explícitamente stdin/stdout/stderr=DEVNULL → PowerShell obtiene handles válidos.

Comportamiento post-fix:


Alcance y transición

⚠️ Actualización HACIA 2.13.3 (última con mecanismo viejo)

✅ Actualización DESDE 2.13.3 en adelante


Verificación

Test de regresión (src inspection)

Archivo: tests/agent/test_agent_updater_trace.py (nueva función test_watchdog_launch_sin_detached_process):

def test_watchdog_launch_sin_detached_process():
    """Regresión del watchdog mudo (incidentes 03-07 y 05-07-2026)."""
    import inspect
    src = inspect.getsource(updater._launch_swap_watchdog)
    assert "subprocess.DETACHED_PROCESS" not in src
    assert "CREATE_NO_WINDOW" in src
    assert "DEVNULL" in src

Motivo CI Linux: Los flags de Windows no existen en POSIX → test por inspección del source (verificar que el código no contiene DETACHED_PROCESS).


Impacto usuario

RolAntesDespués
Admin de flotaAuto-update falla silenciosamente si el AV bloquea → hay que relanzar Agente a mano en cada máquina afectada.Auto-update se recupera automáticamente; el vigilante relanza o revierte sin intervención.
SoporteIncidentes de “Agente muerto después de actualizar” sin explicación clara en logs.Diagnóstico claro en update_watchdog.log (lanzamiento, resultado del healthcheck, acción tomada).
DevRaíz oscura (flags de Windows contradictorios, timing race en PowerShell).Causa documentada, fix verificado, test de regresión.

Véase también

Subir