[CRIU] [PATCH 2/2] parasite: don't block if a parasite crashes

Andrey Vagin avagin at openvz.org
Wed Oct 2 08:29:24 PDT 2013


We need to detect parasite crashes to not hangs on socket operations.
CRIU ptraces parasite. So if it crashes, SIGCHLD is received.

If a parasite daemon crashed, we can to do nothing. The state of current
process can't be restored, because we can't to drop the signal. The
state of other processes are consistent. Probably the best choise in
this case is to exit.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 parasite-syscall.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/parasite-syscall.c b/parasite-syscall.c
index 03925bc..26d363d 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -330,6 +330,68 @@ int parasite_send_fd(struct parasite_ctl *ctl, int fd)
 	return 0;
 }
 
+/*
+ * We need to detect parasite crashes to not hangs on socket operations.
+ * CRIU ptraces parasite. So if it crashes, SIGCHLD is received.
+ *
+ * If someone wants to executed any process, he must use cr_system, which
+ * blocks SIGCHLD and unblocks it only after waiting the child.
+ */
+static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
+{
+	int pid, status;
+
+	pr_err("si_code=%d si_pid=%d si_status=%d\n",
+		siginfo->si_code, siginfo->si_pid, siginfo->si_status);
+
+	pid = waitpid(0, &status, WNOHANG);
+	if (pid <= 0)
+		return;
+
+	if (WIFEXITED(status))
+		pr_err("%d exited with %d unexpectedly\n", pid, WEXITSTATUS(status));
+	else if (WIFSIGNALED(status))
+		pr_err("%d was killed by %d unexpectedly\n", pid, WTERMSIG(status));
+	else if (WIFSTOPPED(status))
+		pr_err("%d was stopped by %d unexpectedly\n", pid, WSTOPSIG(status));
+
+	exit(1);
+}
+
+static int setup_child_handler()
+{
+	struct sigaction sa = {
+		.sa_sigaction	= sigchld_handler,
+		.sa_flags	= SA_SIGINFO | SA_RESTART,
+	};
+
+	sigemptyset(&sa.sa_mask);
+	sigaddset(&sa.sa_mask, SIGCHLD);
+	if (sigaction(SIGCHLD, &sa, NULL)) {
+		pr_perror("Unable to setup SIGCHLD handler");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int restore_child_handler()
+{
+	struct sigaction sa = {
+		.sa_handler	= SIG_DFL,
+		.sa_flags	= SA_SIGINFO | SA_RESTART,
+	};
+
+	sigemptyset(&sa.sa_mask);
+	sigaddset(&sa.sa_mask, SIGCHLD);
+	if (sigaction(SIGCHLD, &sa, NULL)) {
+		pr_perror("Unable to setup SIGCHLD handler");
+		return -1;
+	}
+
+	return 0;
+}
+
 static int ssock = -1;
 
 static int prepare_tsock(struct parasite_ctl *ctl, pid_t pid,
@@ -404,6 +466,9 @@ static int parasite_init_daemon(struct parasite_ctl *ctl)
 	if (prepare_tsock(ctl, pid, args))
 		goto err;;
 
+	if (setup_child_handler())
+		goto err;
+
 	regs = ctl->regs_orig;
 	if (parasite_run(pid, ctl->parasite_ip, ctl->rstack,
 				&regs, &ctl->regs_orig,
@@ -708,6 +773,9 @@ static int parasite_fini_seized(struct parasite_ctl *ctl)
 	user_regs_struct_t regs;
 	int status, ret = 0;
 
+	if (restore_child_handler())
+		return -1;
+
 	if (!ctl->daemonized)
 		return 0;
 
-- 
1.8.3.1



More information about the CRIU mailing list