[CRIU] [PATCH] libcriu: add CRIU_COMM_BIN mode
Ruslan Kuprieiev
kupruser at gmail.com
Thu Jul 23 05:23:07 PDT 2015
Ok
On 07/23/2015 03:21 PM, Pavel Emelyanov wrote:
> 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