Stallo con Java process.waitFor()

DOMANDA:

Nell'eseguire un programma esterno con Runtime.exec(), perché se uso il metodo process.waitFor() va tutto in stallo?


package process;

import java.io.IOException;

public class ProcessTest {

    public static void main(String[] args)
                       throws IOException, InterruptedException {

        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("cmd /C C:\\ffmpeg -i C:\\input.avi C:\\output.avi");
        process.waitFor();
        System.out.println("FINE");
    }
}


RISPOSTA:

Eseguendo il codice della domanda, la stringa "FINE" non verrà mai eseguita. La causa del problema è la bufferizzazione di stdout e stderr. Infatti spesso capita che i dati in arrivo ai vari stream non siano sufficienti a riempire completamente i buffer. Quindi, finché i buffer non sono pieni, restano in attesa di input, lasciando il programma in stallo.

La soluzione è quindi forzarne lo svuotamento quando non ci sono altri dati in arrivo.

Ecco un modo per farlo (tra gli asterischi le aggiunte necessarie):

package process;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class ProcessTest {

    public static void main(String[] args)
                       throws IOException, InterruptedException {

        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("cmd /C C:\\ffmpeg -i C:\\input.avi C:\\output.avi");

// **************************************************************
        // prendiamo l'error stream
        InputStream is = process.getErrorStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        System.out.println(br.readLine()); // lo svuotiamo
        br.close(); // e lo chiudiamo
        process.getOutputStream().flush(); // svuotiamo anche l'output stream
// **************************************************************

        process.waitFor();
        System.out.println("FINE");
    }
}

In questo caso riusciremo nel nostro intento e la stringa "FINE" verrà finalmente visualizzata.


Commenti

Post popolari in questo blog

Arrotondamento e troncamento in Java

Eclipse: Shortcuts (scorciatoie) da tastiera

Strutture dati: List, Set, Map

Creare un eseguibile Java