Commit 24d2f56f authored by Pavel Emelyanov's avatar Pavel Emelyanov

lib: Implement the criu_restore_child() call v2

It fully uses the swrk action of criu. The problems, that caller may
have is that the restored tasks die _before_ libcriu's call returns.

v2:
* rename _sub to _child
* unblock sigchild before execl-ing criu
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent b6f6426b
#include "version.h" #include "version.h"
#include <sys/prctl.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <limits.h> #include <limits.h>
...@@ -6,6 +9,7 @@ ...@@ -6,6 +9,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <signal.h>
#include "criu.h" #include "criu.h"
#include "rpc.pb-c.h" #include "rpc.pb-c.h"
...@@ -450,3 +454,80 @@ exit: ...@@ -450,3 +454,80 @@ exit:
return ret; return ret;
} }
int criu_restore_child(void)
{
int sks[2], pid, ret = -1;
CriuReq req = CRIU_REQ__INIT;
CriuResp *resp = NULL;
if (socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sks))
goto out;
/*
* Set us as child subreaper so that after the swrk
* finishes restore and exits the restored subtree
* gets reparented to us.
*/
if (prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0))
goto err;
pid = fork();
if (pid < 0)
goto err;
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("criu", "criu", "swrk", fds, NULL);
exit(1);
}
close(sks[1]);
req.type = CRIU_REQ_TYPE__RESTORE;
req.opts = opts;
ret = send_req_and_recv_resp_sk(sks[0], &req, &resp);
close(sks[0]);
waitpid(pid, NULL, 0);
/* Drop the subreaper role _after_ swrk exits */
prctl(PR_SET_CHILD_SUBREAPER, 0, 0, 0);
if (!ret) {
ret = resp->success ? resp->restore->pid : -EBADE;
criu_resp__free_unpacked(resp, NULL);
}
out:
return ret;
err:
close(sks[1]);
close(sks[0]);
goto out;
}
...@@ -75,5 +75,6 @@ int criu_add_veth_pair(char *in, char *out); ...@@ -75,5 +75,6 @@ int criu_add_veth_pair(char *in, char *out);
int criu_check(void); int criu_check(void);
int criu_dump(void); int criu_dump(void);
int criu_restore(void); int criu_restore(void);
int criu_restore_child(void);
#endif /* __CRIU_LIB_H__ */ #endif /* __CRIU_LIB_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment