[lxc-devel] [lxc/master] c/r: save dump stdout too
tych0 on Github
lxc-bot at linuxcontainers.org
Wed Nov 2 15:22:26 UTC 2016
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20161102/2addd949/attachment.bin>
-------------- next part --------------
From 5af85cb1447fec6f05513c0e34991ccd0f5a6560 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at 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.andersen at 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.andersen at 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.andersen at 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;
}
More information about the lxc-devel
mailing list