Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Process Builder and Process in Java - how to execute a process with a timeout :? [duplicate]

Tags:

java

process

I need to execute an external batch file in java with a specific timeout. which means that if the batch execution take longer than specified timeout, i need to cancel the execution.

here is a sample code that i wrote:

public static void main(String[] args) throws IOException, InterruptedException {
    ProcessBuilder p = new ProcessBuilder("c:\\wait.bat", "25");  // batch file execution will take 25 seconds.
    final long l = System.currentTimeMillis();
    System.out.println("starting..." + (System.currentTimeMillis() - l));
    final Process command = p.start();
    System.out.println("started..." + (System.currentTimeMillis() - l));

    Timer t = new Timer();
    t.schedule(new TimerTask() {

        @Override
        public void run() {
            command.destroy();
        }
    }, 5000);   // it will kill the process after 5 seconds (if it's not finished yet).
    int i = command.waitFor();
    t.cancel();
    System.out.println("done..." + (System.currentTimeMillis() - l));
    System.out.println("result : " + i);

    System.out.println("Really Done..." + (System.currentTimeMillis() - l));
}

the batch file "wait.bat" is something like this:

@echo off
echo starting the process...
@ping 127.0.0.1 -n 2 -w 1000 > nul
@ping 127.0.0.1 -n %1% -w 1000> nul
echo process finished succesfully
@echo on

As you see in the code, batch file will take 25 seconds to finish (first line in main method) and the Timer will destroy the command after 5 seconds.

here is the output of my code:

starting...0
started...0
done...5000
result : 1
Really Done...5000
BUILD SUCCESSFUL (total time: 25 seconds)

as you see in output, the last line ("Really Done...") is executed in 5th second but the application is finished after 25 seconds.

my question is that : even though i called the destroy method in my timer, why jvm still waiting for the process to be finished ?

like image 631
mhshams Avatar asked Feb 28 '11 06:02

mhshams


People also ask

How do I stop a ProcessBuilder in Java?

You can call destroy() method on it.

What does ProcessBuilder do in Java?

Class ProcessBuilder. This class is used to create operating system processes. Each ProcessBuilder instance manages a collection of process attributes. The start() method creates a new Process instance with those attributes.

What is subprocess in Java?

The subprocess is started with its IO passing up to the process that executed it. This is required to see both any stdout s and stderr s it produces. inheritIO is a convenience method and can also be achieved by calling chaining the following code instead (also configures the stdin of the subprocess): builder .


1 Answers

It is a bug in Java's Process.destroy() implementation on Windows. The problem is that the batch-script (or its executing shell) is killed, but does not kill its own child processes (the ping here). Thus, ping is still running after the .destroy(), and also after the .waitFor(). But somehow the VM still waits for the ping to finish before finishing itself.

It seems there is nothing you can do here from the Java side to really kill the ping reliably.

You may think about using start (in your batch script or outside) to invoke your ping as a separate process.

(See also this previous discussion.)

Or change to a unix-like operation system.

like image 134
Paŭlo Ebermann Avatar answered Oct 05 '22 07:10

Paŭlo Ebermann