Skip to content

Commit d8be857

Browse files
bsach64avagin
authored andcommitted
pidfd: block SIGCHLD during tmp process creation
This patch blocks SIGCHLD during temporary process creation to prevent a race condition between kill() and waitpid() where sigchld_handler() causes `criu restore` to fail with an error. Fixes: #2490 Signed-off-by: Bhavik Sachdev <[email protected]> Signed-off-by: Radostin Stoyanov <[email protected]>
1 parent e6ce8f4 commit d8be857

File tree

1 file changed

+20
-0
lines changed

1 file changed

+20
-0
lines changed

criu/pidfd.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,20 @@ static int create_tmp_process(void)
145145
static int free_dead_pidfd(struct dead_pidfd *dead)
146146
{
147147
int status;
148+
sigset_t blockmask, oldmask;
149+
150+
/*
151+
* Block SIGCHLD to prevent interfering from sigchld_handler()
152+
* and to properly handle the tmp process termination without
153+
* a race condition. A similar approach is used in cr_system().
154+
*/
155+
sigemptyset(&oldmask);
156+
sigemptyset(&blockmask);
157+
sigaddset(&blockmask, SIGCHLD);
158+
if (sigprocmask(SIG_BLOCK, &blockmask, &oldmask) == -1) {
159+
pr_perror("Cannot set mask of blocked signals");
160+
goto err;
161+
}
148162

149163
if (kill(dead->pid, SIGKILL) < 0) {
150164
pr_perror("Could not kill temporary process with pid: %d",
@@ -158,6 +172,12 @@ static int free_dead_pidfd(struct dead_pidfd *dead)
158172
goto err;
159173
}
160174

175+
/* Restore the original signal mask after tmp process has terminated */
176+
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {
177+
pr_perror("Cannot clear blocked signals");
178+
goto err;
179+
}
180+
161181
if (!WIFSIGNALED(status)) {
162182
pr_err("Expected temporary process to be terminated by a signal\n");
163183
goto err;

0 commit comments

Comments
 (0)