Process.waitFor(), corrigindo o deadlock no Windows

Escrito por paulovittor23, 6 de Fevereiro de 2008 01:09

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:


package org.paulovittor23.fixing.waitfor;

import java.io.IOException;

/**
 *
 * @author Paulo Vitor Rendeiro
 * @mail paulovittor23@gmail.com
 * @site http://paulovittor23.org
 *
 * FixingWaitForOnWindows.java
 *
 */
public class FixingWaitForOnWindows {

  public static void main(String[] args) {

    Runtime runtime = Runtime.getRuntime();
    Process process = null;
    try {

      process = runtime.exec( "ipconfig /all" );

      /* instância a classe da MS
       * passando como parâmetro a stream de
       * entrada do sub-processo */
      new PrintStream( process.getInputStream() ).start();

      /* agora podemos fazer a chamada ao waitFor
       * sem que o mesmo cause deadlock */
      process.waitFor();

    }catch(IOException e) {
      e.printStackTrace();
    }catch(InterruptedException e) {
      e.printStackTrace();
    }

  }

}

class PrintStream extends Thread {
  java.io.InputStream __is = null;

  public PrintStream(java.io.InputStream is) {
    __is = is;
  }

  public void run() {
    try {
      while (this != null) {
        int _ch = __is.read();
        if (_ch != -1)
          System.out.print((char) _ch);
        else
          break;
      }
    }catch(Exception e) {
      e.printStackTrace();
    }
  }
}

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()!

3 Comentários “Process.waitFor(), corrigindo o deadlock no Windows”

  1. Oi estava mesmo com problema com o waitFor() no windows, boa dica.

    Gostaria de saber se tem como armazenar essa saida em uma String por exemplo?

    Grato

  2. paulovittor23 diz:

    Boa noite Keps, tem como se fazer isso sim.
    Montei um projetinho exemplo e te enviei por e-mail.
    Espero que ajude.

  3. Andre diz:

    Tentei executar este código em uma jsp, mas o processo não abre,
    Tenho um contexto no tomcat que fica na pasta
    c:\Arquivos de Programas\aplicacao
    estou tentando executar um arquivo.bat para fazer backup do postgres
    mas o mesmo aparece nos processos e nunca conclui
    Agradeço anteciapadamente

Deixe o seu comentário!

Panorama Theme by Themocracy