The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/1270
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) ===
From 5af85cb1447fec6f05513c0e34991ccd0f5a6560 Mon Sep 17 00:00:00 2001 From: Tycho Andersen <tycho.ander...@canonical.com> Date: Tue, 1 Nov 2016 17:07:26 -0600 Subject: [PATCH 1/2] c/r: save criu's stdout during dump too This also allows us to commonize some bits of the dup2 code. Signed-off-by: Tycho Andersen <tycho.ander...@canonical.com> --- src/lxc/criu.c | 76 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/src/lxc/criu.c b/src/lxc/criu.c index 867139b..f49968b 100644 --- a/src/lxc/criu.c +++ b/src/lxc/criu.c @@ -62,6 +62,9 @@ lxc_log_define(lxc_criu, lxc); struct criu_opts { + /* the thing to hook to stdout and stderr for logging */ + int pipefd; + /* The type of criu invocation, one of "dump" or "restore" */ char *action; @@ -134,6 +137,7 @@ static void exec_criu(struct criu_opts *opts) char buf[4096], tty_info[32]; size_t pos; + /* If we are currently in a cgroup /foo/bar, and the container is in a * cgroup /lxc/foo, lxcfs will give us an ENOENT if some task in the * container has an open fd that points to one of the cgroup files @@ -541,6 +545,21 @@ static void exec_criu(struct criu_opts *opts) INFO("execing: %s", buf); + /* before criu inits its log, it sometimes prints things to stdout/err; + * let's be sure we capture that. + */ + if (dup2(opts->pipefd, STDOUT_FILENO) < 0) { + SYSERROR("dup2 stdout failed"); + goto err; + } + + if (dup2(opts->pipefd, STDERR_FILENO) < 0) { + SYSERROR("dup2 stderr failed"); + goto err; + } + + close(opts->pipefd); + #undef DECLARE_ARG execv(argv[0], argv); err: @@ -781,15 +800,6 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_ close(pipes[0]); pipes[0] = -1; - if (dup2(pipes[1], STDERR_FILENO) < 0) { - SYSERROR("dup2 failed"); - goto out_fini_handler; - } - - if (dup2(pipes[1], STDOUT_FILENO) < 0) { - SYSERROR("dup2 failed"); - goto out_fini_handler; - } if (unshare(CLONE_NEWNS)) goto out_fini_handler; @@ -816,6 +826,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_ } } + os.pipefd = pipes[1]; os.action = "restore"; os.user = opts; os.c = c; @@ -1013,29 +1024,38 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op { pid_t pid; char *criu_version = NULL; + int criuout[2]; if (!criu_ok(c, &criu_version)) return false; - if (mkdir_p(opts->directory, 0700) < 0) + if (pipe(criuout) < 0) { + SYSERROR("pipe() failed"); return false; + } + + if (mkdir_p(opts->directory, 0700) < 0) + goto fail; pid = fork(); if (pid < 0) { SYSERROR("fork failed"); - return false; + goto fail; } if (pid == 0) { struct criu_opts os; struct lxc_handler h; + close(criuout[0]); + h.name = c->name; if (!cgroup_init(&h)) { ERROR("failed to cgroup_init()"); exit(1); } + os.pipefd = criuout[1]; os.action = mode; os.user = opts; os.c = c; @@ -1050,27 +1070,51 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op exit(1); } else { int status; + ssize_t n; + char buf[4096]; + bool ret; + + close(criuout[1]); + pid_t w = waitpid(pid, &status, 0); if (w == -1) { SYSERROR("waitpid"); + close(criuout[0]); return false; } + n = read(criuout[0], buf, sizeof(buf)); + close(criuout[0]); + if (n < 0) { + SYSERROR("read"); + n = 0; + } + buf[n] = 0; + if (WIFEXITED(status)) { if (WEXITSTATUS(status)) { ERROR("dump failed with %d\n", WEXITSTATUS(status)); - return false; + ret = false; + } else { + ret = true; } - - return true; } else if (WIFSIGNALED(status)) { ERROR("dump signaled with %d\n", WTERMSIG(status)); - return false; + ret = false; } else { ERROR("unknown dump exit %d\n", status); - return false; + ret = false; } + + if (!ret) + ERROR("criu output: %s", buf); + return ret; } +fail: + close(criuout[0]); + close(criuout[1]); + rmdir(opts->directory); + return false; } bool __criu_pre_dump(struct lxc_container *c, struct migrate_opts *opts) From 9f1f54b0c5fc600cecc43d1608271dbf9b78d20b Mon Sep 17 00:00:00 2001 From: Tycho Andersen <tycho.ander...@canonical.com> Date: Wed, 2 Nov 2016 15:10:13 +0000 Subject: [PATCH 2/2] c/r: remove extra \ns from logs The macros put a \n in for us, so let's not put another one in. Signed-off-by: Tycho Andersen <tycho.ander...@canonical.com> --- src/lxc/criu.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/lxc/criu.c b/src/lxc/criu.c index f49968b..3588b00 100644 --- a/src/lxc/criu.c +++ b/src/lxc/criu.c @@ -216,7 +216,7 @@ static void exec_criu(struct criu_opts *opts) ret = snprintf(log, PATH_MAX, "%s/%s.log", opts->user->directory, opts->action); if (ret < 0 || ret >= PATH_MAX) { - ERROR("logfile name too long\n"); + ERROR("logfile name too long"); return; } @@ -239,7 +239,7 @@ static void exec_criu(struct criu_opts *opts) argv[argc++] = on_path("criu", NULL); if (!argv[argc-1]) { - ERROR("Couldn't find criu binary\n"); + ERROR("Couldn't find criu binary"); goto err; } @@ -506,7 +506,7 @@ static void exec_criu(struct criu_opts *opts) break; case LXC_NET_MACVLAN: if (!n->link) { - ERROR("no host interface for macvlan %s\n", n->name); + ERROR("no host interface for macvlan %s", n->name); goto err; } @@ -519,7 +519,7 @@ static void exec_criu(struct criu_opts *opts) break; default: /* we have screened for this earlier... */ - ERROR("unexpected network type %d\n", n->type); + ERROR("unexpected network type %d", n->type); goto err; } @@ -670,7 +670,7 @@ static bool criu_version_ok(char **version) version_error: fclose(f); free(tmp); - ERROR("must have criu " CRIU_VERSION " or greater to checkpoint/restore\n"); + ERROR("must have criu " CRIU_VERSION " or greater to checkpoint/restore"); return false; } } @@ -685,7 +685,7 @@ static bool criu_ok(struct lxc_container *c, char **criu_version) return false; if (geteuid()) { - ERROR("Must be root to checkpoint\n"); + ERROR("Must be root to checkpoint"); return false; } @@ -699,7 +699,7 @@ static bool criu_ok(struct lxc_container *c, char **criu_version) case LXC_NET_MACVLAN: break; default: - ERROR("Found un-dumpable network: %s (%s)\n", lxc_net_type_to_str(n->type), n->name); + ERROR("Found un-dumpable network: %s (%s)", lxc_net_type_to_str(n->type), n->name); return false; } } @@ -885,7 +885,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_ buf[n] = 0; - ERROR("criu process exited %d, output:\n%s\n", WEXITSTATUS(status), buf); + ERROR("criu process exited %d, output:\n%s", WEXITSTATUS(status), buf); goto out_fini_handler; } else { ret = snprintf(buf, sizeof(buf), "/proc/self/task/%lu/children", (unsigned long)syscall(__NR_gettid)); @@ -896,7 +896,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_ FILE *f = fopen(buf, "r"); if (!f) { - SYSERROR("couldn't read restore's children file %s\n", buf); + SYSERROR("couldn't read restore's children file %s", buf); goto out_fini_handler; } @@ -913,7 +913,7 @@ static void do_restore(struct lxc_container *c, int status_pipe, struct migrate_ } } } else { - ERROR("CRIU was killed with signal %d\n", WTERMSIG(status)); + ERROR("CRIU was killed with signal %d", WTERMSIG(status)); goto out_fini_handler; } @@ -1093,16 +1093,16 @@ static bool do_dump(struct lxc_container *c, char *mode, struct migrate_opts *op if (WIFEXITED(status)) { if (WEXITSTATUS(status)) { - ERROR("dump failed with %d\n", WEXITSTATUS(status)); + ERROR("dump failed with %d", WEXITSTATUS(status)); ret = false; } else { ret = true; } } else if (WIFSIGNALED(status)) { - ERROR("dump signaled with %d\n", WTERMSIG(status)); + ERROR("dump signaled with %d", WTERMSIG(status)); ret = false; } else { - ERROR("unknown dump exit %d\n", status); + ERROR("unknown dump exit %d", status); ret = false; } @@ -1132,7 +1132,7 @@ bool __criu_dump(struct lxc_container *c, struct migrate_opts *opts) return false; if (access(path, F_OK) == 0) { - ERROR("please use a fresh directory for the dump directory\n"); + ERROR("please use a fresh directory for the dump directory"); return false; } @@ -1150,7 +1150,7 @@ bool __criu_restore(struct lxc_container *c, struct migrate_opts *opts) return false; if (geteuid()) { - ERROR("Must be root to restore\n"); + ERROR("Must be root to restore"); return false; }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel