[v2,4/5] restore: fix race with helpers' kids dying too early

Submitted by Tycho Andersen on June 29, 2016, 3:53 p.m.

Details

Message ID 1467215605-17604-4-git-send-email-tycho.andersen@canonical.com
State Rejected
Series "Series without cover letter"
Headers show

Commit Message

Tycho Andersen June 29, 2016, 3:53 p.m.
We masked off SIGCHLD in wait_on_helpers_zombies(), but in fact this is too
late: zombies can die any time after CR_STATE_RESTORE before this function
is called, which lead to us getting "unexpected" deaths. Instead, we should
mask off SIGCHLD before the helpers finish CR_STATE_RESTORE, since they're
explicitly going to wait on all their kids to make sure they don't die
anyway.

Signed-off-by: Tycho Andersen <tycho.andersen@canonical.com>
---
 criu/cr-restore.c | 24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 979c385..2f547bc 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -642,15 +642,6 @@  static unsigned long task_entries_pos;
 static int wait_on_helpers_zombies(void)
 {
 	struct pstree_item *pi;
-	sigset_t blockmask, oldmask;
-
-	sigemptyset(&blockmask);
-	sigaddset(&blockmask, SIGCHLD);
-
-	if (sigprocmask(SIG_BLOCK, &blockmask, &oldmask) == -1) {
-		pr_perror("Can not set mask of blocked signals");
-		return -1;
-	}
 
 	list_for_each_entry(pi, &current->children, sibling) {
 		pid_t pid = pi->pid.virt;
@@ -672,11 +663,6 @@  static int wait_on_helpers_zombies(void)
 		}
 	}
 
-	if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {
-		pr_perror("Can not unset mask of blocked signals");
-		BUG();
-	}
-
 	return 0;
 }
 
@@ -764,6 +750,16 @@  static int restore_one_task(int pid, CoreEntry *core)
 	else if (current->pid.state == TASK_DEAD)
 		ret = restore_one_zombie(core);
 	else if (current->pid.state == TASK_HELPER) {
+		sigset_t blockmask, oldmask;
+
+		sigemptyset(&blockmask);
+		sigaddset(&blockmask, SIGCHLD);
+
+		if (sigprocmask(SIG_BLOCK, &blockmask, &oldmask) == -1) {
+			pr_perror("Can not set mask of blocked signals");
+			return -1;
+		}
+
 		restore_finish_stage(CR_STATE_RESTORE);
 		if (rsti(current)->helper_cb)
 			rsti(current)->helper_cb();