Como Automaticamente coletar Hang Dumps de Hangs Intermitentes?

 

 

Por: Roberto Alexis Farah

 

Acredito que muitos já se depararam com a difícil tarefa de coletar um Hang Dump de uma aplicação onde o sintoma de hang era intermitente.

Monitorar a aplicação de modo a manualmente coletar os dumps com WinDbg, DebugDiag ou ADPlus definitivamente não é a melhor abordagem pois além do tempo dispensado monitorando a aplicação pode ser que o sintoma leve horas ou mesmo dias para ocorrer. Talvez ocorra uma vez por mês! (o que? Você já passou por isso? J )

 

O ideal é usar uma abordagem automatizada. O DebugDiag faz isso para Hang Dumps de processos do IIS. Na verdade, ele consegue identificar o sintoma de hang pela url do website. Se o acesso demora mais do que “n” segundos ele coleta um Hang Dump.

Entretanto, quando nos referimos a processos que não os do IIS devemos usar outros parâmetros para saber se um processo está ou não em hang.

Um processo em hang não responde a requisições (seja por interface visual ou não) ou demora para respondê-las.

Por exemplo, uma aplicação em loop infinito vai consumir alta CPU e provavelmente terá um tempo de resposta lento se houver outras threads atendendo requisições, do contrário ficará irresponsável. Uma aplicação em deadlock apresentará um baixíssimo consumo de CPU mas dependendo do número de threads bloqueadas talvez deixe de responder a qualquer requisição.

 

Note que para um Crash Dump nada disso é necessário porque um Crash Dump pode ser facilmente coletado ainda que o sintoma de Crash seja intermitente. Explico, no caso de um Crash uma exceção é disparada, portanto, se o depurador estiver conectado ao processo ele identifica a exceção, congela as threads do processo, cria um dump e devolve o controle para o processo, tanto para exceções tratadas pela aplicação (1st chance exception) ou não (2nd chance exception). Basta apenas configurar o depurador para o correto tipo de exceção a ser diagnosticada: fatal ou tratada pela aplicação.

 

De volta ao sintoma de Hang, há casos em que a CPU continua normal e a memória também, afinal, o sintoma de hang pode ser mais discreto, diferente do sintoma de Crash que é diretamente relacionado com exceções.

Entretanto, por mais discreto que o sintoma seja, os contadores de Performance Monitor vão, por certo, indicar uma mudança em alguns contadores quando comparando a execução normal da aplicação com a mesma aplicação em estado de hang.

Pois bem, tendo esse conceito em mente apresentarei uma solução que criei anos atrás quando me deparei com uma situação desse tipo, onde precisei automatizar o processo de coleta de Hang Dump.

 

 

ESTRATÉGIA

 

A estratégia apresentada baseia-se em utilizar o Performance Monitor, mais especificamente o Alerts:

 

 

 

E a ferramenta ADPlus que é parte do pacote Debugging Tools For Windows:

 

http://www.microsoft.com/whdc/devtools/debugging/default.mspx

 

A idéia é criar um Alert de Performance Monitor com base em um objeto e contador que é visivelmente alterado durante o sintoma de hang. Então se coloca uma condição como, por exemplo, se o uso de CPU for maior que 90%. Em seguida, associa-se uma ação a essa condição.

A ação será executar um arquivo .BAT que chama o ADPlus e coleta um Hang Dump do processo sendo monitorado.

 

 

SOLUÇÃO

 

1-   Primeiramente use ADPlus para coletar um dump manual apenas para ter certeza que a chamada do script é permitida e funciona corretamente. (esse passo é crucial para impedir que a Lei de Murphy se manifeste J)

 

2-   Crie um arquivo .BAT para rodar o ADPlus. Por exemplo, GETDUMP.BAT e dentro coloque:

c:\debuggers\adplus -quiet -hang -pn process.exe -o c:\dumps

 

Note que você deve especificar o path onde o ADPlus foi instalado e usar o modo –quiet.

E o diretório de dumps, no caso c:\dumps deve ser previamente criado.

Em process.exe você coloca o nome do executável que você quer monitorar. Alternativamente use –p PID.

 

3-   Abra o Performance Monitor, clique em Alerts e New Alert Settings...

 

4-     Escolha um contador (ou mais de um) usado para definir o estado de Hang. Como exemplo usarei objeto Processor e contador  % Processor Time. Você pode usar qualquer objeto e contador que ajude a definir o sintoma de hang da sua aplicação!

 

5-     Coloque um valor em “Alert When the Value is:”   Como exemplo usarei 90. (Over 90)

 

 

6-     Clique no tab Action e no marcador para “Run this program”, em seguida selecione o arquivo GETDUMP.BAT que foi criado.

 

 

7-   Save o Alert mas não rode ele ainda.

 

8-   Em seguida, vá em Administrative Tools e abra o Services. Vá em Performance Logs and Alerts:

 

 

 

 

 

9-   Depois disso, usando o botão direito do mouse vá em Properties e no tab “Log on”. Em seguida clique na opção “Allow service to interact with desktop” para versões do Windows referidas nesse artigo: http://support.microsoft.com/default.aspx?scid=kb;en-us;277806

 

 

 

 

10-                     Agora você pode iniciar o Alert a partir do Performance Monitor. Sempre que a CPU passar de 90% um Hang Dump será automaticamente gerado!

 

 

Eis alguns artigos de referência:

 

HOW TO: Run a Program Interactively When an Alert Is Set by Using System Monitor

http://support.microsoft.com/default.aspx?scid=kb;en-us;277806

 

HOW TO: Configure Performance Counters and Logs to Monitor Unauthorized Attempts to Access Your Computer in Windows 2000 Server

http://support.microsoft.com/default.aspx?scid=kb;en-us;300504

 

Setting Performance Monitor Alert to Run Program May Not Work  (NT only)

http://support.microsoft.com/default.aspx?scid=kb;en-us;117371

 

 

Algum tempo atrás abordei, em outro artigo, o tema de análise automatizada de dumps usando o DebugDiag. O DebugDiag pode ser usado para analisar o dump coletado via ADPlus (ou coletado por outros depuradores).

Com essa combinação você consegue coletar dumps de hangs intermitentes e fazer uma análise automatizada. Na maioria dos cenários isso poderá ser suficiente para isolar o problema ocasionando o sintoma de hang ou, no mínimo, para dar uma boa idéia de onde o problema pode estar localizado!