Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
naotoj committed Jul 16, 2024
1 parent c8a95a7 commit 96d001d
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 3 deletions.
47 changes: 44 additions & 3 deletions src/java.base/share/classes/java/lang/Process.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import java.lang.ProcessBuilder.Redirect;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;
Expand Down Expand Up @@ -456,14 +457,54 @@ public final BufferedWriter outputWriter(Charset charset) {
* @since 1.8
*/
public boolean waitFor(long timeout, TimeUnit unit)
throws InterruptedException
{
long remainingNanos = unit.toNanos(timeout); // throw NPE before other conditions
throws InterruptedException {
Objects.requireNonNull(unit, "unit"); // throw NPE before other conditions

if (hasExited())
return true;
if (timeout <= 0)
return false;

return waitForNanos(unit.toNanos(timeout));
}

/**
* Causes the current thread to wait, if necessary, until the
* process represented by this {@code Process} object has
* terminated, or the specified waiting duration elapses.
*
* <p>If the process has already terminated then this method returns
* immediately with the value {@code true}. If the process has not
* terminated and the duration is not positive, then
* this method returns immediately with the value {@code false}.
*
* <p>The default implementation of this method polls the {@code exitValue}
* to check if the process has terminated. Concrete implementations of this
* class are strongly encouraged to override this method with a more
* efficient implementation.
*
* @param duration the maximum duration to wait; if not positive,
* this method returns immediately.
* @return {@code true} if the process has exited and {@code false} if
* the waiting duration elapsed before the process has exited.
* @throws InterruptedException if the current thread is interrupted
* while waiting.
* @throws NullPointerException if duration is null
* @since 24
*/
public boolean waitFor(Duration duration)
throws InterruptedException {
Objects.requireNonNull(duration, "duration"); // throw NPE before other conditions

if (hasExited())
return true;
if (duration.isZero() || duration.isNegative())
return false;

return waitForNanos(TimeUnit.NANOSECONDS.convert(duration));
}

private boolean waitForNanos(long remainingNanos) throws InterruptedException {
long deadline = System.nanoTime() + remainingNanos;
do {
Thread.sleep(Math.min(TimeUnit.NANOSECONDS.toMillis(remainingNanos) + 1, 100));
Expand Down
63 changes: 63 additions & 0 deletions test/jdk/java/lang/Process/WaitForDuration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2024, 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.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* @test
* @bug 8336479
* @summary Tests for Process.waitFor(Duration)
* @run junit WaitForDuration
*/

import java.io.IOException;
import java.time.Duration;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.*;

public class WaitForDuration {
static Stream<Arguments> durations() {
return Stream.of(
Arguments.of(Duration.ZERO, false),
Arguments.of(Duration.ofSeconds(-100), false),
Arguments.of(Duration.ofSeconds(100), true),
Arguments.of(Duration.ofSeconds(Long.MAX_VALUE), true), // nano overflow
Arguments.of(Duration.ofSeconds(Long.MIN_VALUE), false) // nano underflow
);
}

@ParameterizedTest
@MethodSource("durations")
void testEdgeDurations(Duration d, boolean expected) throws IOException, InterruptedException {
assertEquals(expected, new ProcessBuilder("sleep", "3").start().waitFor(d));
}

@Test
void testNullDuration() throws IOException, InterruptedException {
assertThrows(NullPointerException.class, () ->
new ProcessBuilder("sleep", "3").start().waitFor(null));
}
}

0 comments on commit 96d001d

Please sign in to comment.