< prev index next >

src/java.base/share/classes/java/lang/Process.java

Print this page
rev 54134 : [mq]: 8220684-Process-waitFor-long-TimeUnit-can-return-false-for-a-process-that-exited-within-the-timeout

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -204,24 +204,20 @@
      * @since 1.8
      */
     public boolean waitFor(long timeout, TimeUnit unit)
         throws InterruptedException
     {
-        long startTime = System.nanoTime();
-        long rem = unit.toNanos(timeout);
+        long remainingNanos = unit.toNanos(timeout);    // throw NPE before other conditions
+        if (hasExited()) return true;
+        if (timeout <= 0) return false;
 
+        long deadline = System.nanoTime() + remainingNanos;
         do {
-            try {
-                exitValue();
-                return true;
-            } catch(IllegalThreadStateException ex) {
-                if (rem > 0)
-                    Thread.sleep(
-                        Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
-            }
-            rem = unit.toNanos(timeout) - (System.nanoTime() - startTime);
-        } while (rem > 0);
+            Thread.sleep(Math.min(TimeUnit.NANOSECONDS.toMillis(remainingNanos) + 1, 100));
+            if (hasExited()) return true;
+            remainingNanos = deadline - System.nanoTime();
+        } while (remainingNanos > 0);
         return false;
     }
 
     /**
      * Returns the exit value for the process.

@@ -318,15 +314,24 @@
      * @return {@code true} if the process represented by this
      *         {@code Process} object has not yet terminated.
      * @since 1.8
      */
     public boolean isAlive() {
+        return !hasExited();
+    }
+
+    /**
+     * This is called from the default implementation of
+     * {@code waitFor(long, TimeUnit)}, which is specified to poll
+     * {@code exitValue()}.
+     */
+    private boolean hasExited() {
         try {
             exitValue();
-            return false;
-        } catch(IllegalThreadStateException e) {
             return true;
+        } catch (IllegalThreadStateException e) {
+            return false;
         }
     }
 
     /**
      * Returns the native process ID of the process.
< prev index next >