简体   繁体   中英

Java - kill external process with TimerTask

I implemented a method, where an external program is called with a processBuilder. If the external process takes longer than 5 seconds (for test reasons) I want to stop that task.

The implementation works fine when I use process.exec(). but not with processBuilder.start()

I have read some posts but it does not seem to work, since I can't not figure out what I'm missing.

Method:

ProcessBuilder processBuilder = new ProcessBuilder("/.../test.bat -a -b -c").redirectErrorStream(true);
Process process = processBuilder.start();

Timer t = new Timer();
TimerTask killer = new TimeoutProcessKiller(process);
t.schedule(killer, 5 * 1000);

BufferedReader lineReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

lineReader.lines().forEach(str -> LOGGER.log(Level.INFO, str));

int lExitCode = process.waitFor();
if (lExitCode == 0) {
    LOGGER.log(Level.INFO, "Process finished successful.");
} else {
    LOGGER.log(Level.INFO, "Process finished not successful.");
}
killer.cancel();

TimeoutProcessKiller

public class TimeoutProcessKiller extends TimerTask {
    private Process p;

    public TimeoutProcessKiller(Process p) {
        this.p = p;
    }

    public void run() {
        p.destroy();
    }
}

Thank you for any advise.

Your problem is most likely because your batch script has kicked off sub-processes which are still running after your task has destroyed the parent. Change the TimeoutProcessKiller.run() method to print off the descendants (child process and all their children) and then kill them as well.

The following will print the PID of each one as it tries to kill them:

public void run() {
    System.out.println("destroying "+p);
    p.destroy();
    System.out.println("destroying descendants");
    p.descendants().peek(System.out::println).forEach(ProcessHandle::destroy);
    System.out.println("destroyed  "+p);
}

The change you made from Runtime.exec() to ProcessBuilder is not the cause - as Runtime.exec() is a call to ProcessBuilder . The issue with descendants goes away if you don't consume the STDOUT stream ( NOT a sensible thing to ignore as this can freeze the process), so you most likely added the BufferedReader lineReader... after swapping from Runtime.exec() ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM