2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-22 09:58:09 +00:00

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 <b.sachdev1904@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This commit is contained in:
Bhavik Sachdev 2024-10-09 09:50:28 +01:00 committed by Andrei Vagin
parent e6ce8f4054
commit d8be857b4b

View File

@ -145,6 +145,20 @@ static int create_tmp_process(void)
static int free_dead_pidfd(struct dead_pidfd *dead)
{
int status;
sigset_t blockmask, oldmask;
/*
* Block SIGCHLD to prevent interfering from sigchld_handler()
* and to properly handle the tmp process termination without
* a race condition. A similar approach is used in cr_system().
*/
sigemptyset(&oldmask);
sigemptyset(&blockmask);
sigaddset(&blockmask, SIGCHLD);
if (sigprocmask(SIG_BLOCK, &blockmask, &oldmask) == -1) {
pr_perror("Cannot set mask of blocked signals");
goto err;
}
if (kill(dead->pid, SIGKILL) < 0) {
pr_perror("Could not kill temporary process with pid: %d",
@ -158,6 +172,12 @@ static int free_dead_pidfd(struct dead_pidfd *dead)
goto err;
}
/* Restore the original signal mask after tmp process has terminated */
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {
pr_perror("Cannot clear blocked signals");
goto err;
}
if (!WIFSIGNALED(status)) {
pr_err("Expected temporary process to be terminated by a signal\n");
goto err;