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

    Componentes de servidor que representan intérpretes Python aislados ejecutándose en paralelo
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    InterpreterPoolExecutor: paralelismo real en Python

    Aprende InterpreterPoolExecutor en Python para tareas CPU-bound, intérpretes aislados, paralelismo real y concurrencia segura.

    Ler mais

    Tempo de leitura: 6 minutos
    13/09/2026
    Microprocesador que representa las CPU disponibles para un proceso Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    os.process_cpu_count: cuenta CPUs disponibles

    Aprende os.process_cpu_count en Python para dimensionar workers según las CPU disponibles para el proceso.

    Ler mais

    Tempo de leitura: 4 minutos
    12/09/2026
    Portátil con código digital que representa datos BLOB en SQLite
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    sqlite3.Blob: lee BLOBs sin cargar todo en memoria

    Aprende sqlite3.Blob en Python para leer y escribir BLOBs por partes, reducir memoria y manejar datos binarios en SQLite.

    Ler mais

    Tempo de leitura: 5 minutos
    12/09/2026
    Análisis estadístico para random.binomialvariate en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    random.binomialvariate: simula resultados binomiales

    Aprende random.binomialvariate en Python para simular éxitos, validar probabilidades y analizar escenarios binomiales con ejemplos.

    Ler mais

    Tempo de leitura: 5 minutos
    11/09/2026
    Código Python y análisis de firmas de funciones
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    inspect.signature.bind: valida argumentos de funciones

    Aprende inspect.signature.bind en Python para validar argumentos, aplicar valores predeterminados y crear APIs dinámicas seguras.

    Ler mais

    Tempo de leitura: 5 minutos
    11/09/2026
    Código Python para limpieza segura de directorios con shutil.rmtree
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    shutil.rmtree onexc: maneja errores al borrar carpetas

    Aprende shutil.rmtree con onexc en Python para eliminar directorios, tratar permisos, registrar fallos y crear limpiezas seguras.

    Ler mais

    Tempo de leitura: 7 minutos
    10/09/2026