Commit e23806f3 authored by Kirill Tkhai's avatar Kirill Tkhai Committed by Andrei Vagin

restore: Split restore_one_helper() and wait exiting zombie children

Zombie is also can be choosen as a parent for task helper like
any other task.

If the task helper exits between restore_finish_stage(CR_STATE_RESTORE)
and zombie_prepare_signals()->SIG_UNBLOCK, the standard criu SIGCHLD
handler is called, and the restore fails:

(00.057762)     41: Error (criu/cr-restore.c:1557): 40 exited, status=0
(00.057815) Error (criu/cr-restore.c:2465): Restoring FAILED.

This patch makes restore_one_zombie() behave as restore_one_helper()
and to wait children exits before allowing SIGCHLD. This makes us
safe against races with exiting children.

See next patch for test details.
Signed-off-by: 's avatarKirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent ec761499
...@@ -957,6 +957,8 @@ static int wait_on_helpers_zombies(void) ...@@ -957,6 +957,8 @@ static int wait_on_helpers_zombies(void)
return 0; return 0;
} }
static int wait_exiting_children(void);
static int restore_one_zombie(CoreEntry *core) static int restore_one_zombie(CoreEntry *core)
{ {
int exit_code = core->tc->exit_code; int exit_code = core->tc->exit_code;
...@@ -975,7 +977,7 @@ static int restore_one_zombie(CoreEntry *core) ...@@ -975,7 +977,7 @@ static int restore_one_zombie(CoreEntry *core)
prctl(PR_SET_NAME, (long)(void *)core->tc->comm, 0, 0, 0); prctl(PR_SET_NAME, (long)(void *)core->tc->comm, 0, 0, 0);
if (task_entries != NULL) { if (task_entries != NULL) {
restore_finish_stage(task_entries, CR_STATE_RESTORE); wait_exiting_children();
zombie_prepare_signals(); zombie_prepare_signals();
} }
...@@ -1079,21 +1081,10 @@ static bool child_death_expected(void) ...@@ -1079,21 +1081,10 @@ static bool child_death_expected(void)
return false; return false;
} }
/* static int wait_exiting_children(void)
* Restore a helper process - artificially created by criu
* to restore attributes of process tree.
* - sessions for each leaders are dead
* - process groups with dead leaders
* - dead tasks for which /proc/<pid>/... is opened by restoring task
* - whatnot
*/
static int restore_one_helper(void)
{ {
siginfo_t info; siginfo_t info;
if (prepare_fds(current))
return -1;
if (!child_death_expected()) { if (!child_death_expected()) {
/* /*
* Restoree has no children that should die, during restore, * Restoree has no children that should die, during restore,
...@@ -1136,6 +1127,22 @@ static int restore_one_helper(void) ...@@ -1136,6 +1127,22 @@ static int restore_one_helper(void)
return 0; return 0;
} }
/*
* Restore a helper process - artificially created by criu
* to restore attributes of process tree.
* - sessions for each leaders are dead
* - process groups with dead leaders
* - dead tasks for which /proc/<pid>/... is opened by restoring task
* - whatnot
*/
static int restore_one_helper(void)
{
if (prepare_fds(current))
return -1;
return wait_exiting_children();
}
static int restore_one_task(int pid, CoreEntry *core) static int restore_one_task(int pid, CoreEntry *core)
{ {
int i, ret; int i, ret;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment