Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/aod/ProcessExecutor.java
41161 views
/*1* Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/22package nsk.share.aod;2324import java.io.*;25import java.util.*;26import nsk.share.*;2728public class ProcessExecutor {2930private String[] cmdLine;3132private long timeout;3334private boolean printProcessOutput;3536private String processOutputPrefix;3738private InputStreamReaderThread outReader;3940private InputStreamReaderThread errReader;4142private Process startedProcess;4344private ProcessWaiterThread processWaiter;4546private long expectedFinishTime;4748private volatile boolean executionCompleted;4950private int exitCode;5152private class InputStreamReaderThread extends Thread {53private BufferedReader in;5455private String outputPrefix;5657private List<String> output = new ArrayList<String>();5859private volatile boolean streamWasAbruptlyClosed;6061private Throwable unexpectedException;6263public InputStreamReaderThread(InputStream in, String prefix) {64this.in = new BufferedReader(new InputStreamReader(in));65this.outputPrefix = prefix;66setDaemon(true);67}6869public void streamWasAbruptlyClosed(boolean newValue) {70streamWasAbruptlyClosed = newValue;71}7273public void run() {74try {75while (true) {76String line = in.readLine();77if (line == null)78return;7980output.add(line);8182if (printProcessOutput)83System.out.println(outputPrefix + line);84}85} catch (IOException e) {86if (!streamWasAbruptlyClosed) {87unexpectedException = e;88e.printStackTrace( );89}90} catch (Throwable t) {91unexpectedException = t;92t.printStackTrace( );93}94}9596void checkStatus() {97if (unexpectedException != null)98throw new Failure("Exception was thrown during InputStreamReaderThread work: " + unexpectedException,99unexpectedException);100}101}102103private class ProcessWaiterThread extends Thread {104105private Throwable unexpectedException;106107private Process process;108109private InputStreamReaderThread outReader;110111private InputStreamReaderThread errReader;112113ProcessWaiterThread(Process process, InputStreamReaderThread outReader, InputStreamReaderThread errReader) {114this.process = process;115this.outReader = outReader;116this.errReader = errReader;117118setDaemon(true);119}120121public void run() {122try {123exitCode = process.waitFor();124outReader.join();125errReader.join();126127synchronized (ProcessWaiterThread.this) {128executionCompleted = true;129ProcessWaiterThread.this.notify();130}131} catch (InterruptedException e) {132/*133* ProcessWaiterThread is interrupted if started process134* didn't finish in expected time135*/136} catch (Throwable t) {137unexpectedException = t;138t.printStackTrace();139}140}141142void checkStatus() {143if (unexpectedException != null)144throw new Failure("Exception was thrown during ProcessWaiterThread work: "145+ unexpectedException, unexpectedException);146}147}148149public ProcessExecutor(String cmdLine, long timeout) {150this.cmdLine = new String[]{cmdLine};151this.timeout = timeout;152}153154public ProcessExecutor(String cmdLine, long timeout, String outputPrefix) {155this(cmdLine, timeout);156this.printProcessOutput = true;157this.processOutputPrefix = outputPrefix;158}159160public void startProcess() throws IOException {161if (cmdLine.length == 1)162startedProcess = Runtime.getRuntime().exec(cmdLine[0]);163else164startedProcess = Runtime.getRuntime().exec(cmdLine);165166expectedFinishTime = System.currentTimeMillis() + timeout;167168outReader = new InputStreamReaderThread(startedProcess.getInputStream(),169processOutputPrefix == null ? "" : processOutputPrefix + " (stdout): ");170errReader = new InputStreamReaderThread(startedProcess.getErrorStream(),171processOutputPrefix == null ? "" : processOutputPrefix + " (stderr): ");172173outReader.start();174errReader.start();175176processWaiter = new ProcessWaiterThread(startedProcess, outReader, errReader);177processWaiter.start();178}179180181public void waitForProcess() throws InterruptedException {182synchronized (processWaiter) {183while ((System.currentTimeMillis() < expectedFinishTime) && !executionCompleted) {184processWaiter.wait(expectedFinishTime - System.currentTimeMillis());185}186}187188if (!executionCompleted) {189destroyProcessAndWaitThreads();190191executionCompleted = true;192193throw new Failure("Execution timed out (timeout: " + timeout + "ms)");194}195}196197private void destroyProcessAndWaitThreads() {198outReader.streamWasAbruptlyClosed(true);199errReader.streamWasAbruptlyClosed(true);200201processWaiter.interrupt();202startedProcess.destroy();203204try {205outReader.join();206errReader.join();207processWaiter.join();208209outReader.checkStatus();210errReader.checkStatus();211processWaiter.checkStatus();212} catch (InterruptedException e) {213throw new Failure("Unexpected InterruptedException", e);214}215}216217private void checkProcessState() {218if (!executionCompleted)219throw new IllegalStateException("Process didn't finish execution");220}221222public void destroyProcess() {223if (executionCompleted)224return;225226destroyProcessAndWaitThreads();227}228229public long pid() {230return startedProcess.pid();231}232233public int getExitCode() {234checkProcessState();235236return exitCode;237}238239public List<String> getProcessOut() {240checkProcessState();241242return outReader.output;243}244245public List<String> getProcessErr() {246checkProcessState();247248return errReader.output;249}250}251252253