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:
committed by
Pavel Emelyanov
parent
dfe5f4e586
commit
ced9c529f6
@@ -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, ¤t->children, sibling) {
|
list_for_each_entry(pi, ¤t->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");
|
||||||
|
Reference in New Issue
Block a user