faulthandler no Python: diagnostique travamentos

Publicado em: 03/08/2026
Tempo de leitura: 8 minutos
Tela de erro representando diagnóstico de crashes e deadlocks com faulthandler no Python

Exceções comuns passam pelo mecanismo normal do Python e podem ser registradas com logging ou traceback. Porém, um processo também pode travar em código nativo, sofrer segmentation fault, entrar em deadlock ou permanecer bloqueado por tempo indefinido. O módulo faulthandler no Python foi criado para produzir pilhas mínimas mesmo em situações catastróficas nas quais o interpretador já não consegue executar o tratamento convencional.

Neste guia, você aprenderá a habilitar o módulo, gerar dumps manuais, diagnosticar timeouts, registrar sinais Unix e compreender as pilhas C adicionadas ao Python 3.14. O conteúdo complementa nossos artigos sobre traceback no Python, depuração com pdb, introspecção com inspect e vazamentos de memória.

Quando faulthandler é útil

O módulo atende situações em que uma exceção normal pode nunca ser criada. Exemplos incluem falhas em extensões C, stack overflow, aborts, operações bloqueadas e deadlocks entre threads. Ele instala handlers para sinais fatais como SIGSEGV, SIGFPE, SIGABRT, SIGBUS e SIGILL, dependendo da plataforma.

Como o handler pode executar em um estado instável, sua saída é deliberadamente simples: nomes de arquivos, funções e linhas, com limites de frames e threads. Esse formato sacrifica detalhes para aumentar a chance de produzir algum diagnóstico antes do término do processo.

Habilitar no código

A maneira direta é chamar faulthandler.enable() no início da aplicação.

import faulthandler

faulthandler.enable()

Por padrão, a saída vai para sys.stderr e inclui todas as threads. Em serviços persistentes, habilite antes de iniciar workers e bibliotecas que criam threads.

Habilitar pela linha de comando

Quando não é possível alterar o código, use a opção -X faulthandler.

python -X faulthandler app.py

Também é possível definir a variável de ambiente:

PYTHONFAULTHANDLER=1 python app.py

O modo de desenvolvimento do Python habilita o módulo automaticamente. A opção de linha de comando é especialmente útil para reproduzir falhas em ferramentas de terceiros.

Verificar o estado

is_enabled() informa se o handler fatal está ativo.

import faulthandler

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

disable() remove os handlers instalados por enable(). Normalmente um serviço mantém o recurso ativo durante toda a execução.

Gerar um dump manual

dump_traceback() imprime a pilha atual de todas as threads sem causar uma falha.

import faulthandler

faulthandler.dump_traceback()

Isso ajuda a investigar um processo que parece lento ou bloqueado. Com all_threads=False, somente a thread atual é mostrada.

faulthandler.dump_traceback(all_threads=False)

Para diagnósticos de deadlock, a visão de todas as threads costuma ser a informação mais valiosa.

Enviar para um arquivo

O destino deve permanecer aberto enquanto o handler estiver configurado.

import faulthandler

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

A documentação oficial de faulthandler alerta que o módulo mantém o descritor de arquivo. Se o arquivo for fechado e o número do descritor for reutilizado, o dump pode acabar em outro destino.

Rotação de logs e descritores

Quando um sistema de rotação substitui o arquivo, chame novamente enable() com o novo objeto. O mesmo cuidado vale para dump_traceback_later() e register().

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

Não dependa apenas de handlers de alto nível que trocam arquivos silenciosamente. Verifique como o processo é reiniciado ou notificado após a rotação.

Diagnosticar timeouts

dump_traceback_later() agenda um dump após determinado número de segundos.

faulthandler.dump_traceback_later(
    30,
    repeat=False,
)

Se a operação terminar antes do prazo, cancele:

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

Esse padrão identifica testes congelados, chamadas nativas bloqueadas e deadlocks que não produzem exceção.

Dumps repetidos

Com repeat=True, o módulo gera pilhas periodicamente.

faulthandler.dump_traceback_later(
    60,
    repeat=True,
)

Dumps repetidos mostram se as threads permanecem exatamente nos mesmos frames ou continuam avançando lentamente. Cancele o timer ao concluir o diagnóstico para evitar crescimento desnecessário do log.

Encerrar depois do timeout

O argumento exit=True chama _exit(1) após gerar o dump.

faulthandler.dump_traceback_later(
    120,
    exit=True,
)

_exit() encerra imediatamente, sem executar blocos finally, handlers de atexit ou flush normal de buffers. Use somente quando continuar executando seria pior que uma parada abrupta e quando um supervisor reiniciará o processo.

Diagnóstico sob demanda com sinais

Em sistemas Unix, register() associa um sinal de usuário à geração de pilhas.

import signal

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

Depois, outro terminal pode solicitar o dump sem interromper o serviço:

kill -USR1 PID_DO_PROCESSO

A documentação oficial de signal ajuda a escolher sinais e entender diferenças de plataforma. Esse recurso não está disponível no Windows.

chain=True

Se já existe um handler para o sinal, chain=True chama o handler anterior depois do dump.

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

Use com cautela, pois o handler anterior pode encerrar o processo ou executar uma ação incompatível. unregister() remove o registro instalado.

Pilha C no Python 3.14

O Python 3.14 adicionou dump_c_stack() e a opção c_stack em enable(). Quando a compilação e o sistema operacional oferecem suporte, o relatório inclui frames nativos além da pilha Python.

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

Essa informação é valiosa em extensões C, bibliotecas de ciência de dados, drivers e bindings. Porém, símbolos podem estar ausentes e o dump pode ser lento dependendo das informações DWARF do binário.

Compatibilidade da pilha C

Nem toda plataforma fornece backtrace(), dladdr1() ou suporte adequado no compilador. Nesses casos, o módulo imprime um erro no lugar da pilha C. Trate esse resultado como limitação do ambiente, não como falha da aplicação.

GIL desabilitado

No Python 3.14, quando o GIL está desabilitado, o handler fatal mostra somente a thread atual para reduzir risco de data races. Portanto, a configuração all_threads=True pode produzir um resultado diferente em builds free-threaded.

Registre a versão, o tipo de build e a plataforma junto do dump. Sem essas informações, comparar relatórios entre servidores pode gerar conclusões erradas.

Limitações da saída

O módulo utiliza operações seguras para sinais e não pode depender de alocação normal. A saída aceita somente ASCII com substituição de caracteres, limita strings a 500 caracteres, mostra no máximo 100 frames e 100 threads e não inclui a linha completa do código.

A ordem também é invertida em relação ao traceback normal: a chamada mais recente aparece primeiro. Treine a equipe para ler esse formato.

Testes automatizados

Use o watchdog em testes que podem congelar.

def test_processamento():
    faulthandler.dump_traceback_later(10)
    try:
        resultado = processar_lote()
        assert resultado.ok
    finally:
        faulthandler.cancel_dump_traceback_later()

Evite prazos excessivamente curtos em integração contínua, onde a máquina pode estar sobrecarregada. O objetivo é diagnosticar um bloqueio real, não transformar lentidão ocasional em ruído.

Containers e serviços

Em containers, mantenha stderr conectado ao coletor de logs ou use um arquivo persistente. Verifique limites de tamanho, rotação e retenção. Um dump de muitas threads pode ser grande, embora o módulo imponha limites.

Em Kubernetes ou systemd, combine exit=True com políticas de reinício apenas após validar que o serviço é idempotente e que operações interrompidas podem ser retomadas com segurança.

Segurança operacional

Os dumps normalmente não exibem variáveis locais, mas revelam caminhos, funções, arquitetura interna e atividade das threads. Restrinja acesso aos logs e evite publicá-los em respostas HTTP.

Não provoque segmentation faults deliberadamente em produção para testar a configuração. Valide o comportamento em um processo isolado, container de teste ou ambiente de homologação.

faulthandler versus traceback

traceback é mais rico para exceções normais e permite formatação, cadeias e dados estruturados. faulthandler é minimalista e continua útil quando o processo está travado ou sofreu uma falha nativa. Em uma aplicação madura, os dois módulos se complementam.

faulthandler versus pdb

pdb permite pausar, inspecionar variáveis e avançar pelo código. Ele exige um processo suficientemente saudável e interação. faulthandler produz um snapshot passivo, adequado a ambientes sem terminal ou a falhas que derrubam o interpretador.

Erros frequentes

  • Fechar o arquivo usado pelo handler.
  • Rotacionar logs sem reconfigurar o descritor.
  • Esquecer de cancelar um dump agendado.
  • Usar exit=True sem supervisor ou recuperação.
  • Esperar variáveis locais e código-fonte completo.
  • Ignorar diferenças entre Unix e Windows.
  • Tratar ausência da pilha C como erro do programa.
  • Expor dumps publicamente.

Boas práticas

  • Habilite no início do processo.
  • Direcione a saída para um destino persistente.
  • Reabra o handler após rotação de logs.
  • Use timeouts em testes e operações críticas.
  • Registre um sinal de diagnóstico em Unix.
  • Documente versão, build e sistema operacional.
  • Combine com logging, traceback e métricas.
  • Proteja e retenha os dumps de acordo com a política de segurança.

Conclusão

O módulo faulthandler no Python fornece um último recurso de observabilidade para crashes, deadlocks, timeouts e falhas em código nativo. Ele pode ser ativado no código, por variável de ambiente ou pela opção -X, além de gerar dumps manuais, programados ou acionados por sinais.

Seu valor vem justamente da simplicidade. Mesmo sem variáveis locais ou formatação detalhada, uma lista de threads e frames pode revelar o lock, a extensão ou a função em que o processo parou. Com descritores de arquivo bem administrados, limites operacionais e integração com supervisores, faulthandler transforma travamentos silenciosos em diagnósticos acionáveis.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Notebook com código representando análise de traceback e depuração no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    traceback no Python: erros e pilha

    Aprenda traceback no Python para capturar, formatar e registrar pilhas de erro com segurança, sem vazar dados ou reter memória.

    Ler mais

    Tempo de leitura: 6 minutos
    03/08/2026
    Análise de software representando introspecção de objetos com inspect no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    inspect no Python: introspecção de objetos

    Aprenda inspect no Python para analisar funções, classes, assinaturas, código-fonte, decorators, generators e frames com segurança.

    Ler mais

    Tempo de leitura: 8 minutos
    02/08/2026
    Módulo de memória representando referências fracas e caches no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    weakref no Python: referências fracas

    Aprenda weakref no Python para criar referências fracas, caches automáticos, observadores e finalizadores sem reter objetos na memória.

    Ler mais

    Tempo de leitura: 9 minutos
    28/07/2026
    Ícone de arquivo ZIP para artigo sobre zipfile no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    zipfile no Python: arquivos ZIP seguros

    Aprenda a criar, ler, validar e extrair arquivos ZIP com zipfile no Python de forma previsível e segura.

    Ler mais

    Tempo de leitura: 5 minutos
    27/07/2026
    Grafo de dependências e fluxo de tarefas em Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    graphlib no Python: ordenação topológica

    Aprenda graphlib no Python para ordenar dependências, detectar ciclos e executar tarefas independentes em paralelo.

    Ler mais

    Tempo de leitura: 6 minutos
    27/07/2026
    Código Python para contexto seguro em aplicações assíncronas
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    contextvars no Python: contexto seguro

    Aprenda a usar contextvars no Python para isolar contexto em asyncio, logs, threads e testes sem depender de variáveis globais.

    Ler mais

    Tempo de leitura: 7 minutos
    26/07/2026