Process.waitFor(), corrigindo o deadlock no Windows

Process.waitFor(), corrigindo o deadlock no Windows

Há um tempo atrás eu estava desenvolvendo uma mini biblioteca para trabalhar a execução de comandos no SO de uma forma mais amigável, uma espécie de DSL. Criada a biblioteca realizei alguns testes em ambiente Linux. Tudo funcionamento dentro do planejado, hora de utilizá-la…

Bom, na primeira real utilização da biblioteca, em ambiente Win32 executei um “ipconfig /all”, e para minha surpresa, após todos os testes que havia realizado o comando simplesmente não respondeu.

Voltei ao Linux, mudei o comando para “ifconfig” e o comando executou sem problemas…

Comecei a debugar a biblioteca afim de descobrir o que estava causando o congelamento na execução do comando no SO… Após alguns minutos, cheguei finalmente ao método “waitFor()” da classe “Process”… pela definição esse método faz com que a thread corrente espere, caso necessário, até o processo representado pelo objeto Process terminar.

A questão é que o método “Runtime.exec()” (que devolve a instância do processo criado) cria um pipe para a saída padrão e quando um processo filho escreve uma quantidade grande de dados neste pipe, de modo a deixar o buffer cheio, o pipe é bloqueado pelo Windows até que o processo pai leia esse buffer. Logo, caso o processo pai nunca leia a saída padrão do processo filho teremos um deadlock.

Segundo a documentação da Microsoft para prevenir este bloqueio devemos garantir que o processo pai sempre leia a saída padrão do processo filho… Mas será que o Windows não deveria fazer isso por padrão ao invés de transferir essa responsabilidade aos utilizadores do SO? Enfim…

E como fazer para utilizar o waitFor() no Windows?

A própria Microsoft desenvolveu uma classe que deve ser utilizada antes da chamada ao waitFor…

Um exemplo de utilização dessa classe:

Já realizei testes utilizando essa classe no Linux e o funcionamento permanece normal.
Sempre que for executar algum comando no Windows é bom atentar para utilização do método waitFor()!