Process.exitValue() and Process.destroy() features

Nikolay Kuznetsov picture Nikolay Kuznetsov · Dec 20, 2012 · Viewed 22.4k times · Source

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());
             }
         }
  1. If I run this code and close notepad before 10s timeout. destroy() call does not show any problem on attempt to stop already terminated process. Why?
  2. If run this code and don't close notepad at all (with commented second sleep)

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)
  1. If I run this code and don't close notepad at all (with uncommented second sleep) then second 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.

Answer

ben75 picture ben75 · Dec 20, 2012

I'm expecting that the destroy() method is calling the native windows function TerminateProcess. Looking at MSDN, I found this:

TerminateProcess is asynchronous; it initiates termination and returns immediately. If you need to be sure the process has terminated, call the WaitForSingleObject function with a handle to the process.

So I think it explain that destroy is indeed asynchronous.

Another extract from the same source:

The TerminateProcess function is used to unconditionally cause a process to exit.

I guess that "unconditionnally" can explain why the call of destroy() on a terminate process don't fail.

Hope this help. (really interesting question !)