[CRIU] [PATCH 3/4] lib: Implement the criu_restore_child() call (v2)
Pavel Emelyanov
xemul at parallels.com
Tue Jun 24 12:36:25 PDT 2014
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.
Should we return with blocked CHLD signal or require the caller to
handle it himself?
v2:
* rename _sub to _child
* unblock sigchild before execl-ing criu
Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
lib/criu.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/criu.h | 1 +
2 files changed, 82 insertions(+)
diff --git a/lib/criu.c b/lib/criu.c
index 8d06ada..4b1be8a 100644
--- a/lib/criu.c
+++ b/lib/criu.c
@@ -1,4 +1,7 @@
#include "version.h"
+#include <sys/prctl.h>
+#include <sys/wait.h>
+#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <limits.h>
@@ -6,6 +9,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
+#include <signal.h>
#include "criu.h"
#include "rpc.pb-c.h"
@@ -351,3 +355,80 @@ exit:
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;
+}
diff --git a/lib/criu.h b/lib/criu.h
index f879029..7c33897 100644
--- a/lib/criu.h
+++ b/lib/criu.h
@@ -67,5 +67,6 @@ int criu_set_exec_cmd(int argc, char *argv[]);
int criu_check(void);
int criu_dump(void);
int criu_restore(void);
+int criu_restore_child(void);
#endif /* __CRIU_LIB_H__ */
--
1.8.4.2
More information about the CRIU
mailing list