private CommandResult waitForProcessToComplete( final Process process, final KillableObserver observer, final Killable processKillable, final Consumers.OutErrConsumers outErr, final boolean killSubprocessOnInterrupt) throws AbnormalTerminationException { log.finer("Waiting for process..."); TerminationStatus status = waitForProcess(process, killSubprocessOnInterrupt); observer.stopObserving(processKillable); log.finer(status.toString()); try { outErr.waitForCompletion(); } catch (IOException ioe) { CommandResult noOutputResult = new CommandResult(CommandResult.EMPTY_OUTPUT, CommandResult.EMPTY_OUTPUT, status); if (status.success()) { // If command was otherwise successful, throw an exception about this throw new AbnormalTerminationException(this, noOutputResult, ioe); } else { // Otherwise, throw the more important exception -- command // was not successful String message = status + "; also encountered an error while attempting to retrieve output"; throw status.exited() ? new BadExitStatusException(this, noOutputResult, message, ioe) : new AbnormalTerminationException(this, noOutputResult, message, ioe); } } CommandResult result = new CommandResult(outErr.getAccumulatedOut(), outErr.getAccumulatedErr(), status); result.logThis(); if (status.success()) { return result; } else if (status.exited()) { throw new BadExitStatusException(this, result, status.toString()); } else { throw new AbnormalTerminationException(this, result, status.toString()); } }
private FutureCommandResult doExecute( final InputSource stdinInput, final KillableObserver observer, final Consumers.OutErrConsumers outErrConsumers, final boolean killSubprocessOnInterrupt, final boolean closeOutputStreams) throws CommandException { logCommand(); final Process process = startProcess(); outErrConsumers.logConsumptionStrategy(); outErrConsumers.registerInputs( process.getInputStream(), process.getErrorStream(), closeOutputStreams); processInput(stdinInput, process); // TODO(bazel-team): if the input stream is unbounded, observers will not get start // notification in a timely manner! final Killable processKillable = observeProcess(process, observer); return new FutureCommandResult() { @Override public CommandResult get() throws AbnormalTerminationException { return waitForProcessToComplete( process, observer, processKillable, outErrConsumers, killSubprocessOnInterrupt); } @Override public boolean isDone() { try { // exitValue seems to be the only non-blocking call for // checking process liveness. process.exitValue(); return true; } catch (IllegalThreadStateException e) { return false; } } }; }