[CRIU] [PATCH] parasite: handle errors while a transport socket is being created

Andrey Vagin avagin at openvz.org
Thu Jul 28 11:41:35 PDT 2016


From: Andrew Vagin <avagin at virtuozzo.com>

Currently if socket() or connect() syscall-s failed, parasite cures itself,
but criu has not got any signals and waits on accept().

This patch adds a futex to synchronize parasite and criu. The server socket
is created with SOCK_NONBLOCK and waits on the futex when a parasite
connects to it, only then criu calls accept() and it returns immediately.

Reported-by: Yohei Kamitsukasa <uhoidx at gmail.com>
Cc: Yohei Kamitsukasa <uhoidx at gmail.com>
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 criu/include/parasite.h | 3 +++
 criu/net.c              | 2 +-
 criu/parasite-syscall.c | 9 +++++++++
 criu/pie/parasite.c     | 5 ++++-
 4 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/criu/include/parasite.h b/criu/include/parasite.h
index 82f4c3f..d2a5458 100644
--- a/criu/include/parasite.h
+++ b/criu/include/parasite.h
@@ -15,6 +15,7 @@
 
 #include "image.h"
 #include "util-pie.h"
+#include "lock.h"
 
 #include "images/vma.pb-c.h"
 #include "images/tty.pb-c.h"
@@ -77,6 +78,8 @@ struct parasite_init_args {
 	u64			sigreturn_addr;
 
 	u64			sigframe; /* pointer to sigframe */
+
+	futex_t			sync;
 };
 
 struct parasite_unmap_args {
diff --git a/criu/net.c b/criu/net.c
index a03c168..8593c8a 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -1678,7 +1678,7 @@ static int prep_ns_sockets(struct ns_id *ns, bool for_dump)
 	} else
 		ns->net.nlsk = -1;
 
-	ret = ns->net.seqsk = socket(PF_UNIX, SOCK_SEQPACKET, 0);
+	ret = ns->net.seqsk = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0);
 	if (ret < 0) {
 		pr_perror("Can't create seqsk for parasite");
 		goto err_sq;
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index 824037c..2e3e150 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -515,6 +515,8 @@ static int parasite_init_daemon(struct parasite_ctl *ctl, struct ns_id *net)
 	args->sigframe = (uintptr_t)ctl->rsigframe;
 	args->log_level = log_get_loglevel();
 
+	futex_set(&args->sync, 0);
+
 	if (prepare_tsock(ctl, pid, args, net))
 		goto err;
 
@@ -526,6 +528,13 @@ static int parasite_init_daemon(struct parasite_ctl *ctl, struct ns_id *net)
 	if (parasite_run(pid, PTRACE_CONT, ctl->parasite_ip, ctl->rstack, &regs, &ctl->orig))
 		goto err;
 
+	futex_wait_while_eq(&args->sync, 0);
+	if (futex_get(&args->sync) != 1) {
+		errno = -(int)futex_get(&args->sync);
+		pr_perror("Unable to connect a transport socket");
+		goto err;
+	}
+
 	if (accept_tsock(ctl) < 0)
 		goto err;
 
diff --git a/criu/pie/parasite.c b/criu/pie/parasite.c
index b0dbafa..87a176f 100644
--- a/criu/pie/parasite.c
+++ b/criu/pie/parasite.c
@@ -737,7 +737,7 @@ static noinline __used int parasite_init_daemon(void *data)
 	args->sigreturn_addr = (u64)(uintptr_t)fini_sigreturn;
 	sigframe = (void*)(uintptr_t)args->sigframe;
 
-	tsock = sys_socket(PF_UNIX, SOCK_SEQPACKET, 0);
+	ret = tsock = sys_socket(PF_UNIX, SOCK_SEQPACKET, 0);
 	if (tsock < 0) {
 		pr_err("Can't create socket: %d\n", tsock);
 		goto err;
@@ -749,6 +749,8 @@ static noinline __used int parasite_init_daemon(void *data)
 		goto err;
 	}
 
+	futex_set_and_wake(&args->sync, 1);
+
 	ret = recv_fd(tsock);
 	if (ret >= 0) {
 		log_set_fd(ret);
@@ -760,6 +762,7 @@ static noinline __used int parasite_init_daemon(void *data)
 	parasite_daemon(data);
 
 err:
+	futex_set_and_wake(&args->sync, ret);
 	fini();
 	BUG();
 
-- 
2.7.4



More information about the CRIU mailing list