mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-22 01:51:51 +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:
parent
e6ce8f4054
commit
d8be857b4b
20
criu/pidfd.c
20
criu/pidfd.c
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user