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;