diff options
author | 2016-02-18 13:34:51 +0000 | |
---|---|---|
committer | 2016-02-19 08:56:39 +0000 | |
commit | 40ee9de052e3bb8cf5a59eeff3936148e1f55e69 (patch) | |
tree | 6695f29de93b67dcee0be703057184ee9462b46e /src | |
parent | 9f93673c4ffca8c2288600a8163cfa7c8e75fe79 (diff) |
sandbox: Easier debugging of sandbox failures, when using both --verbose_failures and --sandbox_debug.
RELNOTES:
- When using both --verbose_failures and --sandbox_debug, Bazel prints instructions how to spawn a debugging shell inside the sandbox.
- When namespace-sandbox is run with the -D (debug) flag and inside a terminal, it spawns a shell inside the sandbox to aid in debugging when the sandboxed command fails.
--
MOS_MIGRATED_REVID=114953983
Diffstat (limited to 'src')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/sandbox/NamespaceSandboxRunner.java | 12 | ||||
-rw-r--r-- | src/main/tools/namespace-sandbox.c | 38 |
2 files changed, 44 insertions, 6 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/NamespaceSandboxRunner.java b/src/main/java/com/google/devtools/build/lib/sandbox/NamespaceSandboxRunner.java index ed6f714d33..c6069bdb71 100644 --- a/src/main/java/com/google/devtools/build/lib/sandbox/NamespaceSandboxRunner.java +++ b/src/main/java/com/google/devtools/build/lib/sandbox/NamespaceSandboxRunner.java @@ -47,6 +47,11 @@ import java.util.List; public class NamespaceSandboxRunner { private static final String NAMESPACE_SANDBOX = "namespace-sandbox" + OsUtils.executableExtension(); + private static final String SANDBOX_TIP = + "\n\nSandboxed execution failed, which may be legitimate (e.g. a compiler error), " + + "or due to missing dependencies. To enter the sandbox environment for easier debugging," + + " run the following command in brackets. On command failure, " + + "a bash shell running inside the sandbox will then automatically be spawned\n\n"; private final Path execRoot; private final Path sandboxPath; private final Path sandboxExecRoot; @@ -198,8 +203,9 @@ public class NamespaceSandboxRunner { } String message = CommandFailureUtils.describeCommandFailure( - verboseFailures, spawnArguments, env, cwd.getPath()); - throw new UserExecException(message, e, timedOut); + verboseFailures, commandLineArgs, env, cwd.getPath()); + String finalMsg = (sandboxDebug && verboseFailures) ? SANDBOX_TIP + message : message; + throw new UserExecException(finalMsg, e, timedOut); } finally { copyOutputs(outputs); } @@ -230,7 +236,7 @@ public class NamespaceSandboxRunner { if (sandboxPath.exists()) { FileSystemUtils.deleteTree(sandboxPath); } - if (argumentsFilePath.exists()) { + if (!sandboxDebug && argumentsFilePath.exists()) { argumentsFilePath.delete(); } } diff --git a/src/main/tools/namespace-sandbox.c b/src/main/tools/namespace-sandbox.c index ce81d57907..04f1c9c734 100644 --- a/src/main/tools/namespace-sandbox.c +++ b/src/main/tools/namespace-sandbox.c @@ -16,6 +16,7 @@ #include <errno.h> #include <fcntl.h> +#include <ftw.h> #include <libgen.h> #include <limits.h> #include <pwd.h> @@ -476,7 +477,31 @@ static void SetupDevices() { CHECK_CALL(symlink("/proc/self/fd", "dev/fd")); } +static int rmrf(const char *fpath, const struct stat *sb, int typeflag, + struct FTW *ftwbuf) { + if (typeflag == FTW_DP) { + return rmdir(fpath); + } else { + return unlink(fpath); + } +} + static void SetupDirectories(struct Options *opt) { + // If in sandbox_debug mode and debugging, create the sandbox root dir first + if (global_debug && isatty(fileno(stdin))) { + // Enter sandbox_debug mode a second time, delete old sandbox + struct stat sb; + int err = stat(opt->sandbox_root, &sb); + if (err == 0) { + CHECK_CALL(nftw(opt->sandbox_root, *rmrf, sysconf(_SC_OPEN_MAX), + FTW_DEPTH | FTW_PHYS)); + } else if (errno != ENOENT) { + CHECK_CALL(err); + } + + CHECK_CALL(mkdir(opt->sandbox_root, 0755)); + } + // Mount the sandbox and go there. CHECK_CALL(mount(opt->sandbox_root, opt->sandbox_root, NULL, MS_BIND | MS_NOSUID, NULL)); @@ -653,11 +678,11 @@ void OnSignal(int sig) { // Run the command specified by the argv array and kill it after timeout // seconds. -static void SpawnCommand(char *const *argv, double timeout_secs) { +static void SpawnCommand(char *const *argv, double timeout_secs, + bool isFallback) { for (int i = 0; argv[i] != NULL; i++) { PRINT_DEBUG("arg: %s\n", argv[i]); } - CHECK_CALL(global_child_pid = fork()); if (global_child_pid == 0) { // In child. @@ -691,6 +716,13 @@ static void SpawnCommand(char *const *argv, double timeout_secs) { UnHandle(global_signal); raise(global_signal); } else if (WIFEXITED(status)) { + if (global_debug && !isFallback && isatty(fileno(stdin)) && + WEXITSTATUS(status) > 0) { + char **cmdList = calloc(2, sizeof(char *)); + cmdList[0] = "/bin/bash"; + cmdList[1] = NULL; + SpawnCommand(cmdList, 0, true); + } exit(WEXITSTATUS(status)); } else { int sig = WTERMSIG(status); @@ -749,7 +781,7 @@ int main(int argc, char *const argv[]) { } ChangeRoot(&opt); - SpawnCommand(opt.args, opt.timeout_secs); + SpawnCommand(opt.args, opt.timeout_secs, false); free(opt.create_dirs); free(opt.mount_sources); |