2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-09-02 07:15:31 +00:00

restore: fix race with helpers' kids dying too early

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>
Acked-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This commit is contained in:
Tycho Andersen
2016-07-13 15:10:56 +00:00
committed by Pavel Emelyanov
parent dfe5f4e586
commit ced9c529f6

View File

@@ -639,15 +639,6 @@ static unsigned long task_entries_pos;
static int wait_on_helpers_zombies(void) static int wait_on_helpers_zombies(void)
{ {
struct pstree_item *pi; 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) { list_for_each_entry(pi, &current->children, sibling) {
pid_t pid = pi->pid.virt; pid_t pid = pi->pid.virt;
@@ -669,11 +660,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; return 0;
} }
@@ -761,6 +747,16 @@ static int restore_one_task(int pid, CoreEntry *core)
else if (current->pid.state == TASK_DEAD) else if (current->pid.state == TASK_DEAD)
ret = restore_one_zombie(core); ret = restore_one_zombie(core);
else if (current->pid.state == TASK_HELPER) { 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); restore_finish_stage(CR_STATE_RESTORE);
if (wait_on_helpers_zombies()) { if (wait_on_helpers_zombies()) {
pr_err("failed to wait on helpers and zombies\n"); pr_err("failed to wait on helpers and zombies\n");