8208715: Conversion of milliseconds to nanoseconds in UNIXProcess contains bug

Reviewed-by: martin
This commit is contained in:
Roger Riggs 2018-08-15 10:38:27 -04:00
parent 8cf153fbd5
commit 63b1edb7b7
4 changed files with 42 additions and 7 deletions

View file

@ -507,8 +507,7 @@ final class ProcessImpl extends Process {
long deadline = System.nanoTime() + remainingNanos; long deadline = System.nanoTime() + remainingNanos;
do { do {
// Round up to next millisecond TimeUnit.NANOSECONDS.timedWait(this, remainingNanos);
wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L));
if (hasExited) { if (hasExited) {
return true; return true;
} }

View file

@ -497,10 +497,14 @@ final class ProcessImpl extends Process {
if (getExitCodeProcess(handle) != STILL_ACTIVE) return true; if (getExitCodeProcess(handle) != STILL_ACTIVE) return true;
if (timeout <= 0) return false; if (timeout <= 0) return false;
long deadline = System.nanoTime() + remainingNanos ; long deadline = System.nanoTime() + remainingNanos;
do { do {
// Round up to next millisecond // Round up to next millisecond
long msTimeout = TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L); 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); waitForTimeoutInterruptibly(handle, msTimeout);
if (Thread.interrupted()) if (Thread.interrupted())
throw new InterruptedException(); throw new InterruptedException();
@ -514,7 +518,7 @@ final class ProcessImpl extends Process {
} }
private static native void waitForTimeoutInterruptibly( private static native void waitForTimeoutInterruptibly(
long handle, long timeout); long handle, long timeoutMillis);
@Override @Override
public void destroy() { public void destroy() {

View file

@ -433,10 +433,10 @@ JNIEXPORT void JNICALL
Java_java_lang_ProcessImpl_waitForTimeoutInterruptibly(JNIEnv *env, Java_java_lang_ProcessImpl_waitForTimeoutInterruptibly(JNIEnv *env,
jclass ignored, jclass ignored,
jlong handle, jlong handle,
jlong timeout) jlong timeoutMillis)
{ {
HANDLE events[2]; HANDLE events[2];
DWORD dwTimeout = (DWORD)timeout; DWORD dwTimeout = (DWORD)timeoutMillis;
DWORD result; DWORD result;
events[0] = (HANDLE) handle; events[0] = (HANDLE) handle;
events[1] = JVM_GetThreadInterruptEvent(); events[1] = JVM_GetThreadInterruptEvent();

View file

@ -2421,6 +2421,7 @@ public class Basic {
public void run() { public void run() {
try { try {
aboutToWaitFor.countDown(); aboutToWaitFor.countDown();
Thread.currentThread().interrupt();
boolean result = p.waitFor(30L * 1000L, TimeUnit.MILLISECONDS); boolean result = p.waitFor(30L * 1000L, TimeUnit.MILLISECONDS);
fail("waitFor() wasn't interrupted, its return value was: " + result); fail("waitFor() wasn't interrupted, its return value was: " + result);
} catch (InterruptedException success) { } catch (InterruptedException success) {
@ -2430,7 +2431,38 @@ public class Basic {
thread.start(); thread.start();
aboutToWaitFor.await(); 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.interrupt();
thread.join(10L * 1000L); thread.join(10L * 1000L);
check(millisElapsedSince(start) < 10L * 1000L); check(millisElapsedSince(start) < 10L * 1000L);