Skip to content

Commit

Permalink
sandbox: Easier debugging of sandbox failures, when using both --verb…
Browse files Browse the repository at this point in the history
…ose_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
  • Loading branch information
hermione521 authored and damienmg committed Feb 19, 2016
1 parent 9f93673 commit 40ee9de
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
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;
Expand Down Expand Up @@ -198,8 +203,9 @@ public void run(
}
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);
}
Expand Down Expand Up @@ -230,7 +236,7 @@ public void cleanup() throws IOException {
if (sandboxPath.exists()) {
FileSystemUtils.deleteTree(sandboxPath);
}
if (argumentsFilePath.exists()) {
if (!sandboxDebug && argumentsFilePath.exists()) {
argumentsFilePath.delete();
}
}
Expand Down
38 changes: 35 additions & 3 deletions src/main/tools/namespace-sandbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <errno.h>
#include <fcntl.h>
#include <ftw.h>
#include <libgen.h>
#include <limits.h>
#include <pwd.h>
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 40ee9de

Please sign in to comment.