[CRIU] [PATCH] restore: block SIGCHILD for sub-processes (v2)

Andrey Vagin avagin at openvz.org
Mon Oct 5 06:11:14 PDT 2015


From: Andrew Vagin <avagin at openvz.org>

Otherwise sigchld_handler() will call waitpid()
and worries about unknown process.

(00.333012)      1: kernel/hostname nr 15
(00.333120)      1: kernel/domainname nr 6
(00.335243)      1: Error (cr-restore.c:1225): BUG at cr-restore.c:1225

v2: don't use unitialized oldmask

Cc: Tycho Andersen <tycho.andersen at canonical.com>
Reported-by: Mr Jenkins
Signed-off-by: Andrew Vagin <avagin at openvz.org>
---
 sysctl.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/sysctl.c b/sysctl.c
index f074cca..f68dbe5 100644
--- a/sysctl.c
+++ b/sysctl.c
@@ -198,6 +198,7 @@ static int __userns_sysctl_op(void *arg, int unused, pid_t pid)
 	struct sysctl_userns_req *userns_req = arg;
 	int op = userns_req->op;
 	struct sysctl_req *req, **reqs = NULL;
+	sigset_t blockmask, oldmask;
 	pid_t worker;
 
 	// fix up the pointer
@@ -268,6 +269,16 @@ static int __userns_sysctl_op(void *arg, int unused, pid_t pid)
 		req = (struct sysctl_req *) (((char *) req) + total_len);
 	}
 
+	/*
+	 * Don't let the sigchld_handler() mess with us
+	 * calling waitpid() on the exited worker. The
+	 * same is done in cr_system().
+	 */
+
+	sigemptyset(&blockmask);
+	sigaddset(&blockmask, SIGCHLD);
+	sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
+
 	worker = fork();
 	if (worker < 0)
 		goto out;
@@ -299,10 +310,11 @@ static int __userns_sysctl_op(void *arg, int unused, pid_t pid)
 	}
 
 	if (waitpid(worker, &status, 0) != worker) {
-		pr_err("worker didn't die?");
+		pr_perror("worker didn't die?");
 		kill(worker, SIGKILL);
 		goto out;
 	}
+	sigprocmask(SIG_BLOCK, &oldmask, NULL);
 
 	if (!WIFEXITED(status) || WEXITSTATUS(status)) {
 		pr_err("worker failed: %d\n", status);
-- 
2.4.3



More information about the CRIU mailing list