I have been experimenting with Process
and ProcessBuilder
and come with this SSCCE.
import java.io.IOException;
public class TestProcess {
public static void main(String[] args) {
Process process = null;
ProcessBuilder pb = new ProcessBuilder("notepad.exe");
try {
process = pb.start();
} catch (IOException e) {e.printStackTrace();}
//have some time to close notepad
try {
Thread.sleep(10*1000);
} catch (InterruptedException ignored) {}
try {
System.out.println(process.exitValue());
} catch (IllegalThreadStateException e) {
System.out.println(e);
}
if (process != null)
process.destroy();
/*try {
Thread.sleep(0, 1);
} catch (InterruptedException ignored) {}*/
System.out.println(process.exitValue());
}
}
destroy()
call does not show any problem on attempt to stop already terminated process. Why?
It seems that destroy is asynchronous call (just sending a signal?) which results in exception in second exitValue()
java.lang.IllegalThreadStateException: process has not exited
Exception in thread "main" java.lang.IllegalThreadStateException: process has not exited
at java.lang.ProcessImpl.exitValue(ProcessImpl.java:246)
at TestProcess.main(TestProcess.java:30)
exitValue
never throws Exception, even though sleep value is just 1ms. Is it because of sleep()
overhead itself?
Second exitValue
would return 1. PS. I run it from Windows 7 and Eclipse.
ProcessImpl.java
on destroy
method call native function terminateProcess
:
public void destroy() { terminateProcess(handle); }
private static native void terminateProcess(long handle);
terminateProcess
is platform dependent and for Windows you can find sources here. It's just call Windows TerminateProcess function (link to this function was in previously answer or you can google it) with uExitCode=1
- thats why exit code of destroyed process is 1
.
In linux looks like is used something similar to this. And as proof next code return 143
in ubuntu, that correspond to SIGTERM
(https://stackoverflow.com/a/4192488/3181901):
public static void main(final String[] args) throws IOException, InterruptedException {
final Process process = Runtime.getRuntime().exec(args[0]);
process.destroy();
Thread.sleep(1000);
System.out.println(process.exitValue());
}
Why would it show a problem? You're trying to destroy a process that was already destroyed. The specification of Process.destroy()
doesn't say what happens if there was nothing to destroy, so it is logical (I suppose) to assume that if there's nothing to destroy, then there's nothing to complain about. Compare with Thread.join()
, which doesn't just die if the thread has already ended.
The only way to kill a process is to send it a signal. On some OS's, there are other, more "violent" ways (on some platforms, for example, it is possible to simply remove the process from the OS's list of running processes. Results are undefined and it usually ends ugly), but at least with platforms that I know of, it's really all about sending signals.
Possible, indeed, that it's because it takes time to invoke Thread.sleep()
. Try increasing the timeout value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With