Move Subprocess.Factory to a top-level class
Also move the implementation of FutureCommandResult to a top-level class.
This is in preparation for significantly simplifying the shell library. The
plan is to remove the Subprocess abstraction, and have lower-level
implementations implement the much simpler FutureCommandResult interface
instead.
PiperOrigin-RevId: 167844736
diff --git a/src/main/java/com/google/devtools/build/lib/shell/Command.java b/src/main/java/com/google/devtools/build/lib/shell/Command.java
index 46eefee..291dd32 100644
--- a/src/main/java/com/google/devtools/build/lib/shell/Command.java
+++ b/src/main/java/com/google/devtools/build/lib/shell/Command.java
@@ -358,7 +358,7 @@
Preconditions.checkNotNull(stdinInput, "stdinInput");
logCommand();
- final Subprocess process = startProcess();
+ Subprocess process = startProcess();
outErrConsumers.logConsumptionStrategy();
outErrConsumers.registerInputs(
@@ -369,22 +369,7 @@
// enforced.
processInput(stdinInput, process);
- return new FutureCommandResult() {
- @Override
- public CommandResult get() throws AbnormalTerminationException {
- return waitForProcessToComplete(process, outErrConsumers, killSubprocessOnInterrupt);
- }
-
- @Override
- public boolean isDone() {
- return process.finished();
- }
-
- @Override
- public void cancel() {
- process.destroy();
- }
- };
+ return new FutureCommandResultImpl(this, process, outErrConsumers, killSubprocessOnInterrupt);
}
private Subprocess startProcess() throws ExecFailedException {
@@ -425,78 +410,6 @@
}
}
- private CommandResult waitForProcessToComplete(
- Subprocess process, Consumers.OutErrConsumers outErr, boolean killSubprocessOnInterrupt)
- throws AbnormalTerminationException {
- logger.finer("Waiting for process...");
-
- TerminationStatus status = waitForProcess(process, killSubprocessOnInterrupt);
-
- logger.finer(status.toString());
-
- try {
- if (Thread.currentThread().isInterrupted()) {
- outErr.cancel();
- } else {
- 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);
- }
- } finally {
- process.close();
- }
-
- 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 static TerminationStatus waitForProcess(
- Subprocess process, boolean killSubprocessOnInterrupt) {
- boolean wasInterrupted = false;
- try {
- while (true) {
- try {
- process.waitFor();
- return new TerminationStatus(process.exitValue(), process.timedout());
- } catch (InterruptedException ie) {
- wasInterrupted = true;
- if (killSubprocessOnInterrupt) {
- process.destroy();
- }
- }
- }
- } finally {
- // Read this for detailed explanation: http://www.ibm.com/developerworks/library/j-jtp05236/
- if (wasInterrupted) {
- Thread.currentThread().interrupt(); // preserve interrupted status
- }
- }
- }
-
private void logCommand() {
if (!logger.isLoggable(Level.FINE)) {
return;