[CRIU] [PATCH] libcriu: add CRIU_COMM_BIN mode
Pavel Emelyanov
xemul at parallels.com
Thu Jul 23 05:21:33 PDT 2015
On 07/19/2015 05:20 AM, Ruslan Kuprieiev wrote:
> In this mode libcriu will execute criu binary in swrk
> mode, so users are not always obliged to run criu service
> daemon.
Sorry for late response. The patch looks OK, please do two things.
1. Split into two -- 1) move code from criu_local_restore_child()
into helpers swrk_connect() and swrk_wait() and 2) the rest.
2. Do s/_bin/_binary/
Thanks
> 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);
>
More information about the CRIU
mailing list