Encode remaining environmental execution failures with FailureDetails
EnvironmentalExecException now always has details. Applicable failure
modes in SymlinkTree management, include scanning, remote execution, and
CPP actions now use FailureDetails.
RELNOTES: None.
PiperOrigin-RevId: 315833077
diff --git a/src/main/java/com/google/devtools/build/lib/actions/EnvironmentalExecException.java b/src/main/java/com/google/devtools/build/lib/actions/EnvironmentalExecException.java
index 82a64ed..1c0f7c6 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/EnvironmentalExecException.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/EnvironmentalExecException.java
@@ -19,12 +19,10 @@
import com.google.devtools.build.lib.server.FailureDetails.Execution;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.util.DetailedExitCode;
-import com.google.devtools.build.lib.util.ExitCode;
import java.io.IOException;
-import javax.annotation.Nullable;
/**
- * An ExecException which is reports an issue executing an action due to an external problem on the
+ * An ExecException which reports an issue executing an action due to an external problem on the
* local system.
*
* <p>This exception will result in an exit code regarded as a system error; avoid using this for
@@ -37,8 +35,7 @@
* directory or denied file system access.
*/
public class EnvironmentalExecException extends ExecException {
- // TODO(b/138456686): Make this not nullable.
- @Nullable private final FailureDetail failureDetail;
+ private final FailureDetail failureDetail;
public EnvironmentalExecException(IOException cause, FailureDetails.Execution.Code code) {
super("unexpected I/O exception", cause);
@@ -46,16 +43,11 @@
FailureDetail.newBuilder().setExecution(Execution.newBuilder().setCode(code)).build();
}
- public EnvironmentalExecException(IOException cause, FailureDetail failureDetail) {
+ public EnvironmentalExecException(Exception cause, FailureDetail failureDetail) {
super(failureDetail.getMessage(), cause);
this.failureDetail = failureDetail;
}
- public EnvironmentalExecException(String message, Throwable cause) {
- super(message, cause);
- failureDetail = null;
- }
-
public EnvironmentalExecException(FailureDetail failureDetail) {
super(failureDetail.getMessage());
this.failureDetail = failureDetail;
@@ -70,10 +62,8 @@
messagePrefix,
getMessage(),
getCause() == null ? "" : ("\n" + Throwables.getStackTraceAsString(getCause())));
- DetailedExitCode detailedExitCode =
- failureDetail == null
- ? DetailedExitCode.justExitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR)
- : DetailedExitCode.of(failureDetail.toBuilder().setMessage(message).build());
- return new ActionExecutionException(message, action, isCatastrophic(), detailedExitCode);
+ FailureDetail failureDetailWithPrefix = failureDetail.toBuilder().setMessage(message).build();
+ return new ActionExecutionException(
+ message, action, isCatastrophic(), DetailedExitCode.of(failureDetailWithPrefix));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeHelper.java b/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeHelper.java
index c8aeb0b..fab0276 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeHelper.java
@@ -23,7 +23,9 @@
import com.google.devtools.build.lib.actions.EnvironmentalExecException;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
+import com.google.devtools.build.lib.server.FailureDetails.Execution;
import com.google.devtools.build.lib.server.FailureDetails.Execution.Code;
+import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.shell.Command;
import com.google.devtools.build.lib.shell.CommandException;
import com.google.devtools.build.lib.util.CommandBuilder;
@@ -163,7 +165,13 @@
command.execute();
}
} catch (CommandException e) {
- throw new EnvironmentalExecException(CommandUtils.describeCommandFailure(true, e), e);
+ throw new EnvironmentalExecException(
+ e,
+ FailureDetail.newBuilder()
+ .setMessage(CommandUtils.describeCommandFailure(true, e))
+ .setExecution(
+ Execution.newBuilder().setCode(Code.SYMLINK_TREE_CREATION_COMMAND_EXCEPTION))
+ .build());
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeStrategy.java b/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeStrategy.java
index 5ff0a40..31a924f 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/SymlinkTreeStrategy.java
@@ -27,7 +27,9 @@
import com.google.devtools.build.lib.analysis.actions.SymlinkTreeActionContext;
import com.google.devtools.build.lib.profiler.AutoProfiler;
import com.google.devtools.build.lib.profiler.GoogleAutoProfilerUtils;
+import com.google.devtools.build.lib.server.FailureDetails.Execution;
import com.google.devtools.build.lib.server.FailureDetails.Execution.Code;
+import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.OutputService;
@@ -155,8 +157,7 @@
try {
FileSystemUtils.writeContentAsLatin1(outputManifest, hexDigest);
} catch (IOException e) {
- throw new EnvironmentalExecException(
- "Failed to link output manifest '" + outputManifest.getPathString() + "'", e);
+ throw createLinkFailureException(outputManifest, e);
}
} else {
// Link output manifest on success. We avoid a file copy as these manifests may be
@@ -165,8 +166,7 @@
try {
outputManifest.createSymbolicLink(inputManifest);
} catch (IOException e) {
- throw new EnvironmentalExecException(
- "Failed to link output manifest '" + outputManifest.getPathString() + "'", e);
+ throw createLinkFailureException(outputManifest, e);
}
}
}
@@ -178,4 +178,15 @@
actionExecutionContext.getInputPath(action.getOutputManifest()).getParentDirectory(),
action.isFilesetTree());
}
+
+ private static EnvironmentalExecException createLinkFailureException(
+ Path outputManifest, IOException e) {
+ return new EnvironmentalExecException(
+ e,
+ FailureDetail.newBuilder()
+ .setMessage("Failed to link output manifest '" + outputManifest.getPathString() + "'")
+ .setExecution(
+ Execution.newBuilder().setCode(Code.SYMLINK_TREE_MANIFEST_LINK_IO_EXCEPTION))
+ .build());
+ }
}
diff --git a/src/main/java/com/google/devtools/build/lib/includescanning/IncludeHintsFunction.java b/src/main/java/com/google/devtools/build/lib/includescanning/IncludeHintsFunction.java
index 63bcfdd..a9f50d3 100644
--- a/src/main/java/com/google/devtools/build/lib/includescanning/IncludeHintsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/includescanning/IncludeHintsFunction.java
@@ -77,8 +77,11 @@
env.getValueOrThrow(FileValue.key(RootedPath.toRootedPath(hintsPackageRoot, hintsFile)),
IOException.class);
} catch (IOException | BuildFileNotFoundException e) {
- throw new IncludeHintsFunctionException(new EnvironmentalExecException(
- "could not read INCLUDE_HINTS file", e));
+ throw new IncludeHintsFunctionException(
+ new EnvironmentalExecException(
+ e,
+ createFailureDetail(
+ "could not read INCLUDE_HINTS file", Code.INCLUDE_HINTS_READ_FAILURE)));
}
if (env.valuesMissing()) {
return null;
@@ -86,8 +89,11 @@
try {
return Hints.getRules(hintsPackageRoot.getRelative(hintsFile));
} catch (IOException e) {
- throw new IncludeHintsFunctionException(new EnvironmentalExecException(
- "could not read INCLUDE_HINTS file", e));
+ throw new IncludeHintsFunctionException(
+ new EnvironmentalExecException(
+ e,
+ createFailureDetail(
+ "could not read INCLUDE_HINTS file", Code.INCLUDE_HINTS_READ_FAILURE)));
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java
index 0c881f4..92d1e32 100644
--- a/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java
+++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteCache.java
@@ -60,6 +60,9 @@
import com.google.devtools.build.lib.remote.options.RemoteOptions;
import com.google.devtools.build.lib.remote.util.DigestUtil;
import com.google.devtools.build.lib.remote.util.Utils.InMemoryOutput;
+import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
+import com.google.devtools.build.lib.server.FailureDetails.RemoteExecution;
+import com.google.devtools.build.lib.server.FailureDetails.RemoteExecution.Code;
import com.google.devtools.build.lib.util.io.FileOutErr;
import com.google.devtools.build.lib.util.io.OutErr;
import com.google.devtools.build.lib.vfs.Dirent;
@@ -352,7 +355,13 @@
// any subsequent local execution failure would likely be incomprehensible.
ExecException execEx =
new EnvironmentalExecException(
- "Failed to delete output files after incomplete download", ioEx);
+ ioEx,
+ FailureDetail.newBuilder()
+ .setMessage("Failed to delete output files after incomplete download")
+ .setRemoteExecution(
+ RemoteExecution.newBuilder()
+ .setCode(Code.INCOMPLETE_OUTPUT_DOWNLOAD_CLEANUP_FAILURE))
+ .build());
execEx.addSuppressed(e);
throw execEx;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
index a5fef2f..01919c5 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/cpp/CppCompileAction.java
@@ -1459,7 +1459,8 @@
try {
return ByteStreams.toByteArray(in);
} catch (IOException e) {
- throw new EnvironmentalExecException("Reading in-memory .d file failed", e);
+ throw new EnvironmentalExecException(
+ e, createFailureDetail("Reading in-memory .d file failed", Code.D_FILE_READ_FAILURE));
}
}
}
diff --git a/src/main/protobuf/failure_details.proto b/src/main/protobuf/failure_details.proto
index d53717b..58d1844 100644
--- a/src/main/protobuf/failure_details.proto
+++ b/src/main/protobuf/failure_details.proto
@@ -337,6 +337,8 @@
[(metadata) = { exit_code: 2 }];
REMOTE_DOWNLOAD_OUTPUTS_MINIMAL_WITHOUT_INMEMORY_JDEPS = 12
[(metadata) = { exit_code: 2 }];
+ INCOMPLETE_OUTPUT_DOWNLOAD_CLEANUP_FAILURE = 13
+ [(metadata) = { exit_code: 36 }];
}
Code code = 1;
@@ -364,8 +366,12 @@
TEST_OUT_ERR_IO_EXCEPTION = 14 [(metadata) = { exit_code: 36 }];
SYMLINK_TREE_MANIFEST_COPY_IO_EXCEPTION = 15
[(metadata) = { exit_code: 36 }];
- SYMLINK_TREE_CREATION_IO_EXCEPTION = 16 [(metadata) = { exit_code: 36 }];
- ACTION_INPUT_READ_IO_EXCEPTION = 17 [(metadata) = { exit_code: 36 }];
+ SYMLINK_TREE_MANIFEST_LINK_IO_EXCEPTION = 16
+ [(metadata) = { exit_code: 36 }];
+ SYMLINK_TREE_CREATION_IO_EXCEPTION = 17 [(metadata) = { exit_code: 36 }];
+ SYMLINK_TREE_CREATION_COMMAND_EXCEPTION = 18
+ [(metadata) = { exit_code: 36 }];
+ ACTION_INPUT_READ_IO_EXCEPTION = 19 [(metadata) = { exit_code: 36 }];
}
Code code = 1;
@@ -608,6 +614,7 @@
INITIALIZE_INCLUDE_HINTS_ERROR = 1 [(metadata) = { exit_code: 36 }];
SCANNING_IO_EXCEPTION = 2 [(metadata) = { exit_code: 36 }];
INCLUDE_HINTS_FILE_NOT_IN_PACKAGE = 3 [(metadata) = { exit_code: 36 }];
+ INCLUDE_HINTS_READ_FAILURE = 4 [(metadata) = { exit_code: 36 }];
}
Code code = 1;
@@ -831,6 +838,7 @@
CPP_COMPILE_UNKNOWN = 0 [(metadata) = { exit_code: 37 }];
FIND_USED_HEADERS_IO_EXCEPTION = 1 [(metadata) = { exit_code: 36 }];
COPY_OUT_ERR_FAILURE = 2 [(metadata) = { exit_code: 36 }];
+ D_FILE_READ_FAILURE = 3 [(metadata) = { exit_code: 36 }];
}
Code code = 1;