sexta-feira, 3 de junho de 2011

Novo módulo de detecção de falhas (faulthandler) do Python 3.3 ajuda no debugging

Quando um usuário relata que seu programa "dá pau", congela, às vezes você só pode tentar ajudar, obter maiores informações e tentar reproduzir o problema. Mesmo com informações detalhadas do usuário, programadores normalmente não são capazes de reproduzir o problema devido à diferenças de sistemas, tais como sistema operacional e compilador. Com sorte, o usuário pode instalar algumas ferramentas de debugging, mas na maioria das vezes você tem de esperar outras pessoas encontrarem o mesmo problema e dar maiores informações.

Erros Fatais

Um novo módulo, introduzido em Python 3.3, deve ajudar em situações semelhantes: faulthandler. faulthandler permite que um "traceback" seja salvo quando um erro fatal (fatal error) ocorrer, tais como "segmentation fault", divisão por zero, mensagens abortadas ou erro no "bus". Você pode ativá-lo dentro de um aplicativo usando o faulthandler.enable(), ou colocando a opção -X faulthandler no executável do Python, ou com a variável de sistema PYTHONFAULTHANDLER=1. Exemplo:

Fatal Python error: Segmentation fault

Current thread 0x00007f7babc6b700:
 File "Lib/test/crashers/gc_inspection.py", line 29 in g
 File "Lib/test/crashers/gc_inspection.py", line 32 in <module>
Segmentation fault

Timeout

faulthandler pode também salvar um "traceback" após algum tempo com faulthandler.dump_tracebacks_later(timeout). Ative-o novamente para reiniciar a contagem ou use faulthandler.cancel_dump_tracebacks_later() para parar a contagem. Exemplo:

Timeout (0:01:00)!
Current thread 0x00007f987d459700:
 File "Lib/test/crashers/infinite_loop_re.py", line 20 in <module>

Use a opção repeat=True para salvar um "tracebakc" a cada n segundos de timeout, ou exit=True para sair do programa imediatamente, de forma não segura, e.g. sem arquivos de saída.

Sinal do Usuário

Se você tem acesso ao computador que esteja rodando o programa, você ainda pode usar o faulthandler.register(signal) para instalar o gerente de sinais que salva o "traceback" quando o sinal é recebido. Em UNIX, por exemplo, você pode usar o sinal SIGUSR1: kill -USR1 <pid> salva o "traceback" atual. Este recurso não está disponível em Windows. Exemplo:

Current thread 0x00007fdc3da74700:
 File "Lib/test/crashers/infinite_loop_re.py", line 19 in <module>

Outra possibilidade é ativa explicitamente faulthandler.dump_traceback() no seu programa.

Problemas de segurança e o arquivo de saída

faulthandler é desativado por padrão, por razões de segurança, sobretudo porque ele arquiva a descrição do arquivo sys.stderr e salva os "tracebacks" no seu arquivo de descrição. Se o sys.stderr é fechado e o arquivo de descrição é reutilizado, o arquivo de descrição pode ser um "socket", um "pipe" ou arquivo crítico ou algo mais. Por padrão, faulthandler escreve "tracebacks" em sys.stderr, mas outro arquivo pode ser especificado. Para maiores informações, leia a documentação do faulthandler.

Módulos terceirizados para versões antigas de Python

faulthandler também mantido como um módulo terceirizado para Python 2.5 até 3.2 em PyPI. A maior diferença entre o Python 3.3 e o módulo terceirizado é a implementação do dump_tracebacks_later(): Python 3.3 usa uma "thread" com um alarme de tempo em um "lock", enquanto o módulo terceirizado usa SIGALRM e alarm().

O alarme de tempo do "lock" é uma novo recurso de Python 3.3, tem uma resolução de microssegundos. O contador de alarm() usado é usado em versões mais antigas, e o sinal do SIGALRM pode interromper a chamada de sistema atual, a qual falhará com um erro EINTR.

Sucesso Inicial

O novo módulo faulthandler já ajudou a localizar "race conditions" nos "buildbots". Esperamos que possam ajudar vocês com seus programas.

Nenhum comentário:

Postar um comentário