[CRIU] [PATCH] libcriu: add CRIU_COMM_BIN mode
Ruslan Kuprieiev
kupruser at gmail.com
Sat Jul 18 19:20:31 PDT 2015
In this mode libcriu will execute criu binary in swrk
mode, so users are not always obliged to run criu service
daemon.
Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
---
lib/criu.c | 153 ++++++++++++++++++++++++++++++++++++++++++++-----------------
lib/criu.h | 7 ++-
2 files changed, 117 insertions(+), 43 deletions(-)
diff --git a/lib/criu.c b/lib/criu.c
index da6288a..8008981 100644
--- a/lib/criu.c
+++ b/lib/criu.c
@@ -16,6 +16,8 @@
#include "criu.h"
#include "cr-service-const.h"
+#define CR_DEFAULT_SERVICE_BIN "criu"
+
const char *criu_lib_version = CRIU_VERSION;
static criu_opts *global_opts;
@@ -54,6 +56,19 @@ void criu_set_service_fd(int fd)
criu_local_set_service_fd(global_opts, fd);
}
+void criu_local_set_service_bin(criu_opts *opts, char *path)
+{
+ if (path)
+ opts->service_bin = path;
+ else
+ opts->service_bin = CR_DEFAULT_SERVICE_BIN;
+}
+
+void criu_set_service_bin(char *path)
+{
+ criu_local_set_service_bin(global_opts, path);
+}
+
int criu_local_init_opts(criu_opts **o)
{
criu_opts *opts = NULL;
@@ -663,6 +678,63 @@ static int send_notify_ack(int socket_fd, int ret)
return ret ? : send_ret;
}
+static int swrk_connect(criu_opts *opts)
+{
+ int pid;
+ int sks[2];
+
+ if (socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sks)) {
+ perror("Failed to create socket pair");
+ return -1;
+ }
+
+ /*
+ * Can't setup a SIGCHLD handler here, as it
+ * would alter signal handlers of the caller.
+ */
+
+ pid = fork();
+ if (pid < 0) {
+ perror("Failed to fork");
+ return -1;
+ }
+
+ if (pid == 0) {
+ sigset_t mask;
+ char fds[11];
+
+ /*
+ * Unblock SIGCHLD.
+ *
+ * The caller of this function is supposed to have
+ * this signal blocked. Otherwise it risks to get
+ * into situation, when this routine is not yet
+ * returned, but the restore subtree exits and
+ * emits the SIGCHLD.
+ *
+ * In turn, unblocked SIGCHLD is required to make
+ * criu restoration process work -- it catches
+ * subtasks restore errors in this handler.
+ */
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_UNBLOCK, &mask, NULL);
+
+ close(sks[0]);
+ sprintf(fds, "%d", sks[1]);
+
+ execlp(opts->service_bin, opts->service_bin, "swrk", fds, NULL);
+ perror("Can't exec criu swrk");
+ exit(1);
+ }
+
+ close(sks[1]);
+ opts->swrk_pid = pid;
+
+ return sks[0];
+}
+
static int criu_connect(criu_opts *opts)
{
int fd, ret;
@@ -671,6 +743,8 @@ static int criu_connect(criu_opts *opts)
if (opts->service_comm == CRIU_COMM_FD)
return opts->service_fd;
+ else if (opts->service_comm == CRIU_COMM_BIN)
+ return swrk_connect(opts);
fd = socket(AF_LOCAL, SOCK_SEQPACKET, 0);
if (fd < 0) {
@@ -759,6 +833,11 @@ static int send_req_and_recv_resp(criu_opts *opts, CriuReq *req, CriuResp **resp
return ret;
}
+static void swrk_wait(criu_opts *opts)
+{
+ waitpid(opts->swrk_pid, NULL, 0);
+}
+
int criu_local_check(criu_opts *opts)
{
int ret = -1;
@@ -779,6 +858,8 @@ exit:
if (resp)
criu_resp__free_unpacked(resp, NULL);
+ swrk_wait(opts);
+
errno = saved_errno;
return ret;
@@ -816,6 +897,8 @@ exit:
if (resp)
criu_resp__free_unpacked(resp, NULL);
+ swrk_wait(opts);
+
errno = saved_errno;
return ret;
@@ -885,6 +968,8 @@ exit:
if (resp)
criu_resp__free_unpacked(resp, NULL);
+ swrk_wait(opts);
+
errno = saved_errno;
return ret;
@@ -919,6 +1004,8 @@ exit:
if (resp)
criu_resp__free_unpacked(resp, NULL);
+ swrk_wait(opts);
+
errno = saved_errno;
return ret;
@@ -931,59 +1018,44 @@ int criu_restore(void)
int criu_local_restore_child(criu_opts *opts)
{
- int sks[2], pid, ret = -1;
+ int fd, ret = -1;
+ enum criu_service_comm saved_comm;
+ char *saved_comm_data;
+ bool save_comm;
CriuReq req = CRIU_REQ__INIT;
CriuResp *resp = NULL;
- if (socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sks))
- goto out;
-
- pid = fork();
- if (pid < 0)
- goto err;
-
- if (pid == 0) {
- sigset_t mask;
- char fds[11];
+ saved_errno = 0;
- /*
- * Unblock SIGCHLD.
- *
- * The caller of this function is supposed to have
- * this signal blocked. Otherwise it risks to get
- * into situation, when this routine is not yet
- * returned, but the restore subtree exits and
- * emits the SIGCHLD.
- *
- * In turn, unblocked SIGCHLD is required to make
- * criu restoration process work -- it catches
- * subtasks restore errors in this handler.
- */
+ save_comm = opts->service_comm != CRIU_COMM_BIN;
+ if (save_comm) {
+ /* Save comm data */
+ saved_comm = opts->service_comm;
+ saved_comm_data = opts->service_address;
- sigemptyset(&mask);
- sigaddset(&mask, SIGCHLD);
- sigprocmask(SIG_UNBLOCK, &mask, NULL);
+ opts->service_comm = CRIU_COMM_BIN;
+ opts->service_bin = CR_DEFAULT_SERVICE_BIN;
+ }
- close(sks[0]);
- sprintf(fds, "%d", sks[1]);
+ fd = swrk_connect(opts);
+ if (fd < 0)
+ goto out;
- execlp("criu", "criu", "swrk", fds, NULL);
- perror("Can't exec criu swrk");
- exit(1);
+ if (save_comm) {
+ /* Restore comm data */
+ opts->service_comm = saved_comm;
+ opts->service_address = saved_comm_data;
}
- close(sks[1]);
-
req.type = CRIU_REQ_TYPE__RESTORE;
req.opts = opts->rpc;
req.opts->has_rst_sibling = true;
req.opts->rst_sibling = true;
- ret = send_req_and_recv_resp_sk(sks[0], opts, &req, &resp);
+ ret = send_req_and_recv_resp_sk(fd, opts, &req, &resp);
- close(sks[0]);
- waitpid(pid, NULL, 0);
+ swrk_wait(opts);
if (!ret) {
ret = resp->success ? resp->restore->pid : -EBADE;
@@ -991,12 +1063,9 @@ int criu_local_restore_child(criu_opts *opts)
}
out:
- return ret;
+ errno = saved_errno;
-err:
- close(sks[1]);
- close(sks[0]);
- goto out;
+ return ret;
}
int criu_restore_child(void)
diff --git a/lib/criu.h b/lib/criu.h
index 81d3396..ef3a886 100644
--- a/lib/criu.h
+++ b/lib/criu.h
@@ -23,11 +23,13 @@
enum criu_service_comm {
CRIU_COMM_SK,
- CRIU_COMM_FD
+ CRIU_COMM_FD,
+ CRIU_COMM_BIN
};
void criu_set_service_address(char *path);
void criu_set_service_fd(int fd);
+void criu_set_service_bin(char *path);
/*
* You can choose if you want libcriu to connect to service socket
@@ -141,13 +143,16 @@ typedef struct {
union {
char *service_address;
int service_fd;
+ char *service_bin;
};
+ int swrk_pid;
} criu_opts;
int criu_local_init_opts(criu_opts **opts);
void criu_local_set_service_address(criu_opts *opts, char *path);
void criu_local_set_service_fd(criu_opts *opts, int fd);
+void criu_local_set_service_bin(criu_opts *opts, char *path);
void criu_local_set_service_comm(criu_opts *opts, enum criu_service_comm);
void criu_local_set_service_fd(criu_opts *opts, int fd);
--
2.1.0
More information about the CRIU
mailing list