blob: 200c47548bbc8765cec609e94ba53fa83610afb3 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.test.process;
import java.util.concurrent.TimeUnit;
/**
* Starts the stdout and stderr reader threads for a running process. Provides a mechanism to
* waitFor the process to terminate.
* </p>
* Extracted from ProcessWrapper.
*
*/
public class ProcessOutputReader {
private boolean started;
private final Process process;
private final ProcessStreamReader stdout;
private final ProcessStreamReader stderr;
public ProcessOutputReader(final Process process, final ProcessStreamReader stdout,
final ProcessStreamReader stderr) {
this.process = process;
this.stdout = stdout;
this.stderr = stderr;
}
public void start() {
synchronized (this) {
this.stdout.start();
this.stderr.start();
this.started = true;
}
}
public boolean waitFor(final long timeout, final TimeUnit unit) throws InterruptedException {
synchronized (this) {
if (!this.started) {
throw new IllegalStateException("Must be started before waitFor");
}
}
final long startTime = System.nanoTime();
long millisToJoin = unit.toMillis(timeout);
this.stderr.join(millisToJoin);
long nanosRemaining = unit.toNanos(timeout) - (System.nanoTime() - startTime);
millisToJoin = unit.toMillis(nanosRemaining);
this.stdout.join(millisToJoin);
nanosRemaining = unit.toNanos(timeout) - (System.nanoTime() - startTime);
return waitForProcess(nanosRemaining, unit);
}
private boolean waitForProcess(final long timeout, final TimeUnit unit)
throws InterruptedException {
long startTime = System.nanoTime();
long nanosRemaining = unit.toNanos(timeout);
while (nanosRemaining > 0) {
try {
this.process.exitValue();
return true;
} catch (IllegalThreadStateException ex) {
if (nanosRemaining > 0) {
long millisToSleep = Math.min(TimeUnit.NANOSECONDS.toMillis(nanosRemaining) + 1, 100);
Thread.sleep(millisToSleep);
}
}
nanosRemaining = unit.toNanos(timeout) - (System.nanoTime() - startTime);
}
return false;
}
}