8208715: Conversion of milliseconds to nanoseconds in UNIXProcess contains bug
Reviewed-by: martin
--- a/src/java.base/unix/classes/java/lang/ProcessImpl.java Thu Aug 16 16:06:54 2018 +0530
+++ b/src/java.base/unix/classes/java/lang/ProcessImpl.java Wed Aug 15 10:38:27 2018 -0400
@@ -507,8 +507,7 @@
long deadline = System.nanoTime() + remainingNanos;
do {
- // Round up to next millisecond
- wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L));
+ TimeUnit.NANOSECONDS.timedWait(this, remainingNanos);
if (hasExited) {
return true;
}
--- a/src/java.base/windows/classes/java/lang/ProcessImpl.java Thu Aug 16 16:06:54 2018 +0530
+++ b/src/java.base/windows/classes/java/lang/ProcessImpl.java Wed Aug 15 10:38:27 2018 -0400
@@ -497,10 +497,14 @@
if (getExitCodeProcess(handle) != STILL_ACTIVE) return true;
if (timeout <= 0) return false;
- long deadline = System.nanoTime() + remainingNanos ;
+ long deadline = System.nanoTime() + remainingNanos;
do {
// Round up to next millisecond
long msTimeout = TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L);
+ if (msTimeout < 0) {
+ // if wraps around then wait a long while
+ msTimeout = Integer.MAX_VALUE;
+ }
waitForTimeoutInterruptibly(handle, msTimeout);
if (Thread.interrupted())
throw new InterruptedException();
@@ -514,7 +518,7 @@
}
private static native void waitForTimeoutInterruptibly(
- long handle, long timeout);
+ long handle, long timeoutMillis);
@Override
public void destroy() {
--- a/src/java.base/windows/native/libjava/ProcessImpl_md.c Thu Aug 16 16:06:54 2018 +0530
+++ b/src/java.base/windows/native/libjava/ProcessImpl_md.c Wed Aug 15 10:38:27 2018 -0400
@@ -433,10 +433,10 @@
Java_java_lang_ProcessImpl_waitForTimeoutInterruptibly(JNIEnv *env,
jclass ignored,
jlong handle,
- jlong timeout)
+ jlong timeoutMillis)
{
HANDLE events[2];
- DWORD dwTimeout = (DWORD)timeout;
+ DWORD dwTimeout = (DWORD)timeoutMillis;
DWORD result;
events[0] = (HANDLE) handle;
events[1] = JVM_GetThreadInterruptEvent();
--- a/test/jdk/java/lang/ProcessBuilder/Basic.java Thu Aug 16 16:06:54 2018 +0530
+++ b/test/jdk/java/lang/ProcessBuilder/Basic.java Wed Aug 15 10:38:27 2018 -0400
@@ -2421,6 +2421,7 @@
public void run() {
try {
aboutToWaitFor.countDown();
+ Thread.currentThread().interrupt();
boolean result = p.waitFor(30L * 1000L, TimeUnit.MILLISECONDS);
fail("waitFor() wasn't interrupted, its return value was: " + result);
} catch (InterruptedException success) {
@@ -2430,7 +2431,38 @@
thread.start();
aboutToWaitFor.await();
- Thread.sleep(1000);
+ thread.interrupt();
+ thread.join(10L * 1000L);
+ check(millisElapsedSince(start) < 10L * 1000L);
+ check(!thread.isAlive());
+ p.destroy();
+ } catch (Throwable t) { unexpected(t); }
+
+ //----------------------------------------------------------------
+ // Check that Process.waitFor(Long.MAX_VALUE, TimeUnit.MILLISECONDS)
+ // interrupt works as expected, if interrupted while waiting.
+ //----------------------------------------------------------------
+ try {
+ List<String> childArgs = new ArrayList<String>(javaChildArgs);
+ childArgs.add("sleep");
+ final Process p = new ProcessBuilder(childArgs).start();
+ final long start = System.nanoTime();
+ final CountDownLatch aboutToWaitFor = new CountDownLatch(1);
+
+ final Thread thread = new Thread() {
+ public void run() {
+ try {
+ aboutToWaitFor.countDown();
+ Thread.currentThread().interrupt();
+ boolean result = p.waitFor(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
+ fail("waitFor() wasn't interrupted, its return value was: " + result);
+ } catch (InterruptedException success) {
+ } catch (Throwable t) { unexpected(t); }
+ }
+ };
+
+ thread.start();
+ aboutToWaitFor.await();
thread.interrupt();
thread.join(10L * 1000L);
check(millisElapsedSince(start) < 10L * 1000L);