faulthandler en Python: diagnostica bloqueos

Publicado el: 03/08/2026
Tempo de leitura: 7 minutos
Pantalla de error que representa diagnóstico de crashes y deadlocks con faulthandler en Python

Las excepciones normales pasan por el mecanismo habitual de Python y pueden registrarse con logging o traceback. Sin embargo, un proceso también puede fallar dentro de código nativo, sufrir un segmentation fault, entrar en deadlock, desbordar la pila o permanecer bloqueado indefinidamente. El módulo faulthandler en Python está diseñado para producir información mínima de la pila incluso en estados catastróficos en los que el tratamiento convencional puede no ejecutarse.

Esta guía explica cómo habilitarlo, solicitar dumps manuales, investigar timeouts, registrar señales Unix y usar las pilas C disponibles desde Python 3.14. Complementa nuestros artículos sobre traceback en Python, depuración con pdb, introspección con inspect y diagnóstico de rendimiento.

Cuándo resulta útil

El módulo atiende situaciones en las que quizá nunca se crea una excepción normal. Algunos ejemplos son crashes en extensiones C, desbordamientos de pila, aborts, llamadas nativas bloqueadas y deadlocks entre threads. Según la plataforma, instala handlers para señales fatales como SIGSEGV, SIGFPE, SIGABRT, SIGBUS y SIGILL.

Como el handler puede ejecutarse mientras el proceso está inestable, la salida es deliberadamente simple: archivos, funciones y números de línea con límites de frames y threads. Se sacrifica detalle para aumentar la probabilidad de obtener evidencia antes del cierre.

Habilitarlo desde el código

Llama a faulthandler.enable() al inicio del proceso.

import faulthandler

faulthandler.enable()

La salida va a sys.stderr por defecto e incluye todas las threads. Los servicios persistentes deberían habilitarlo antes de iniciar workers y bibliotecas que crean recursos nativos.

Habilitarlo desde la línea de comandos

Cuando no puedes modificar el código, usa -X faulthandler.

python -X faulthandler app.py

La variable de entorno ofrece otra alternativa:

PYTHONFAULTHANDLER=1 python app.py

El modo de desarrollo de Python lo activa automáticamente. La opción de línea de comandos es útil para reproducir errores en aplicaciones de terceros.

Comprobar el estado

is_enabled() informa si los handlers fatales están activos.

if not faulthandler.is_enabled():
    faulthandler.enable()

disable() elimina los handlers instalados por enable(). Un servidor normalmente mantiene el recurso activo durante toda su vida.

Generar un dump manual

dump_traceback() imprime la pila actual de todas las threads sin provocar un crash.

faulthandler.dump_traceback()

Ayuda a investigar un proceso que parece lento o congelado. Usa all_threads=False para mostrar únicamente la thread actual.

faulthandler.dump_traceback(all_threads=False)

Para deadlocks, la relación entre todas las pilas suele ser la evidencia más importante.

Escribir en un archivo

El destino debe permanecer abierto mientras el handler lo utilice.

archivo = open("fallos.log", "a", buffering=1)
faulthandler.enable(file=archivo, all_threads=True)

La documentación oficial de faulthandler advierte que el módulo conserva el descriptor. Si el archivo se cierra y el número se reutiliza, un dump posterior podría escribirse en un destino diferente.

Rotación de logs

Cuando la rotación sustituye el archivo, llama de nuevo a enable() con el nuevo objeto. La misma regla se aplica a dump_traceback_later() y register().

def reabrir_log():
    global archivo
    archivo.close()
    archivo = open("fallos.log", "a", buffering=1)
    faulthandler.enable(file=archivo, all_threads=True)

Documenta si el servicio se reinicia, recibe una señal o conserva el inode anterior después de la rotación.

Diagnosticar timeouts

dump_traceback_later() programa un dump tras un número de segundos.

faulthandler.dump_traceback_later(
    30,
    repeat=False,
)

Cancélalo cuando la operación termine:

try:
    ejecutar_operacion_larga()
finally:
    faulthandler.cancel_dump_traceback_later()

Este patrón aporta evidencia para tests congelados, llamadas nativas bloqueadas y deadlocks que nunca lanzan una excepción.

Dumps repetidos

Con repeat=True, el watchdog escribe pilas periódicamente.

faulthandler.dump_traceback_later(
    60,
    repeat=True,
)

Varios snapshots muestran si las threads siguen exactamente en los mismos frames o avanzan lentamente. Cancela el timer después del diagnóstico.

Salir después del timeout

exit=True llama a _exit(1) después de escribir el dump.

faulthandler.dump_traceback_later(
    120,
    exit=True,
)

_exit() termina de inmediato sin ejecutar finally, handlers de atexit ni el flush normal. Úsalo solo cuando permanecer bloqueado sea peor y exista un supervisor capaz de reiniciar de forma segura.

Diagnóstico bajo demanda con señales

En Unix, register() asocia una señal de usuario con el dump.

import signal

faulthandler.register(
    signal.SIGUSR1,
    all_threads=True,
)

Un operador puede solicitar información sin detener el proceso:

kill -USR1 ID_DEL_PROCESO

La documentación oficial de signal explica el comportamiento y las diferencias de plataforma. El registro de señales de usuario no está disponible en Windows.

Conservar un handler anterior

Usa chain=True para llamar al handler anterior después del dump.

faulthandler.register(
    signal.SIGUSR1,
    all_threads=True,
    chain=True,
)

Ten cuidado porque el handler previo puede terminar el proceso o ejecutar una acción incompatible. unregister() elimina el registro.

Pilas C en Python 3.14

Python 3.14 añade dump_c_stack() y el parámetro c_stack en enable(). Cuando el sistema y la compilación lo permiten, el informe incluye frames nativos después de los frames Python.

faulthandler.enable(c_stack=True)
faulthandler.dump_c_stack()

Es valioso en extensiones C, drivers, bibliotecas científicas, bindings criptográficos y procesamiento de imágenes. Los símbolos pueden estar incompletos y la generación puede ser lenta según la información DWARF disponible.

Compatibilidad de la pila C

No todas las plataformas ofrecen backtrace(), dladdr1(), soporte de compilador o símbolos adecuados. Cuando no hay compatibilidad, el módulo imprime un error explicativo. Trátalo como una limitación del entorno.

Builds sin GIL

En Python 3.14, cuando el GIL está deshabilitado, el handler fatal muestra solo la thread actual para reducir data races. Por lo tanto, all_threads=True puede producir un resultado diferente en builds free-threaded.

Registra versión, tipo de build, sistema operativo, arquitectura e imagen del container junto con el dump.

Limitaciones de la salida

El módulo depende de operaciones seguras para señales y no puede usar la asignación normal del heap. La salida usa ASCII con sustitución, limita strings a 500 caracteres y muestra como máximo 100 frames y 100 threads. No incluye líneas completas del código.

El orden también difiere del traceback normal: la llamada más reciente aparece primero.

Watchdogs en tests

Usa un timeout alrededor de pruebas que pueden congelarse.

def test_procesamiento():
    faulthandler.dump_traceback_later(10)
    try:
        resultado = procesar_lote()
        assert resultado.ok
    finally:
        faulthandler.cancel_dump_traceback_later()

Evita plazos demasiado cortos en integración continua, donde los runners pueden estar sobrecargados. La intención es detectar un bloqueo real, no crear ruido.

Containers y gestores de servicios

En containers, conecta stderr al sistema de logs o utiliza almacenamiento persistente. Comprueba tamaño, rotación y retención. Un informe con muchas threads todavía puede ser grande.

Con Kubernetes, systemd u otro supervisor, combina exit=True con políticas de reinicio únicamente después de verificar que las operaciones interrumpidas son idempotentes y recuperables.

Seguridad operativa

Los dumps normalmente no incluyen variables locales, pero exponen rutas, nombres de funciones, arquitectura interna y actividad de threads. Restringe el acceso y nunca los incluyas en respuestas HTTP públicas.

No provoques un segmentation fault en producción solo para probar la configuración. Valida el comportamiento en un proceso aislado, container de prueba o staging.

faulthandler frente a traceback

traceback ofrece formato rico para excepciones normales, incluyendo cadenas y resúmenes estructurados. faulthandler es minimalista y sigue funcionando cuando el proceso está congelado o falla en código nativo. Ambos se complementan.

faulthandler frente a pdb

pdb permite pausar, inspeccionar variables y avanzar por el código, pero necesita un proceso suficientemente sano e interacción. faulthandler crea un snapshot pasivo adecuado para servidores sin terminal y errores que terminan el intérprete.

Errores frecuentes

  • Cerrar el archivo utilizado por el handler.
  • Rotar logs sin reconfigurar el descriptor.
  • Olvidar cancelar un dump programado.
  • Usar exit=True sin supervisión ni recuperación.
  • Esperar variables locales y código fuente completo.
  • Ignorar diferencias entre Unix y Windows.
  • Tratar la ausencia de pila C como fallo del programa.
  • Publicar dumps sin control de acceso.

Buenas prácticas

  • Habilita el módulo al iniciar el proceso.
  • Escribe en un destino persistente.
  • Reconfigura después de rotar logs.
  • Usa watchdogs en tests y operaciones críticas.
  • Registra una señal bajo demanda en Unix.
  • Guarda detalles de intérprete y plataforma.
  • Combina dumps con logging, métricas y tracebacks normales.
  • Protege y conserva los informes según la política de seguridad.

Conclusión

El módulo faulthandler en Python proporciona una última capa de observabilidad para crashes, deadlocks, timeouts, stack overflows y fallos de código nativo. Puede habilitarse en el código, con una variable de entorno o mediante -X, y permite dumps manuales, programados o activados por señales.

Su fortaleza proviene de la simplicidad. Incluso sin variables locales ni formato avanzado, una lista de threads y frames puede identificar el lock, la extensión o la función en la que el proceso se detuvo. Con una gestión disciplinada de descriptores, límites operativos e integración con supervisores, faulthandler convierte bloqueos silenciosos en diagnósticos útiles.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Portátil con código que representa análisis de traceback y depuración en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    traceback en Python: errores y pila

    Aprende traceback en Python para capturar, formatear y registrar pilas de error sin filtrar datos sensibles ni retener memoria.

    Ler mais

    Tempo de leitura: 6 minutos
    03/08/2026
    Análisis de software que representa introspección de objetos con inspect en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    inspect en Python: introspección de objetos

    Aprende inspect en Python para analizar funciones, clases, firmas, código fuente, decorators, generators, coroutines y frames con seguridad.

    Ler mais

    Tempo de leitura: 6 minutos
    02/08/2026
    Módulo de memoria que representa referencias débiles y cachés en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    weakref en Python: referencias débiles

    Aprende weakref en Python para crear referencias débiles, cachés automáticas, observadores y finalizadores sin retener objetos en memoria.

    Ler mais

    Tempo de leitura: 9 minutos
    28/07/2026
    Icono de archivo ZIP para un artículo sobre zipfile en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    zipfile en Python: archivos ZIP seguros

    Aprende a crear, leer, validar y extraer archivos ZIP con zipfile en Python de forma predecible y segura.

    Ler mais

    Tempo de leitura: 5 minutos
    27/07/2026
    Grafo de dependencias y flujo de tareas en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    graphlib en Python: ordenación topológica

    Aprende graphlib en Python para ordenar dependencias, detectar ciclos y coordinar tareas independientes en paralelo.

    Ler mais

    Tempo de leitura: 6 minutos
    27/07/2026
    Código Python para contexto seguro en aplicaciones asíncronas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    contextvars en Python: contexto seguro

    Aprende a usar contextvars en Python para aislar solicitudes, registros, hilos y tareas asyncio sin variables globales inseguras.

    Ler mais

    Tempo de leitura: 6 minutos
    26/07/2026