Commit fd8e5884 authored by Andrew Vagin's avatar Andrew Vagin Committed by Pavel Emelyanov

restore: block SIGCHILD for sub-processes (v2)

Otherwise sigchld_handler() will call waitpid()
and worries about unknown process.

(00.333012)      1: kernel/hostname nr 15
(00.333120)      1: kernel/domainname nr 6
(00.335243)      1: Error (cr-restore.c:1225): BUG at cr-restore.c:1225

v2: don't use unitialized oldmask

Cc: Tycho Andersen <tycho.andersen@canonical.com>
Reported-by: Mr Jenkins
Signed-off-by: 's avatarAndrew Vagin <avagin@openvz.org>
Acked-by: 's avatarTycho Andersen <tycho.andersen@canonical.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 6a51c7ec
...@@ -196,6 +196,7 @@ static int __userns_sysctl_op(void *arg, int unused, pid_t pid) ...@@ -196,6 +196,7 @@ static int __userns_sysctl_op(void *arg, int unused, pid_t pid)
struct sysctl_userns_req *userns_req = arg; struct sysctl_userns_req *userns_req = arg;
int op = userns_req->op; int op = userns_req->op;
struct sysctl_req *req, **reqs = NULL; struct sysctl_req *req, **reqs = NULL;
sigset_t blockmask, oldmask;
pid_t worker; pid_t worker;
// fix up the pointer // fix up the pointer
...@@ -266,6 +267,16 @@ static int __userns_sysctl_op(void *arg, int unused, pid_t pid) ...@@ -266,6 +267,16 @@ static int __userns_sysctl_op(void *arg, int unused, pid_t pid)
req = (struct sysctl_req *) (((char *) req) + total_len); req = (struct sysctl_req *) (((char *) req) + total_len);
} }
/*
* Don't let the sigchld_handler() mess with us
* calling waitpid() on the exited worker. The
* same is done in cr_system().
*/
sigemptyset(&blockmask);
sigaddset(&blockmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
worker = fork(); worker = fork();
if (worker < 0) if (worker < 0)
goto out; goto out;
...@@ -297,10 +308,11 @@ static int __userns_sysctl_op(void *arg, int unused, pid_t pid) ...@@ -297,10 +308,11 @@ static int __userns_sysctl_op(void *arg, int unused, pid_t pid)
} }
if (waitpid(worker, &status, 0) != worker) { if (waitpid(worker, &status, 0) != worker) {
pr_err("worker didn't die?"); pr_perror("worker didn't die?");
kill(worker, SIGKILL); kill(worker, SIGKILL);
goto out; goto out;
} }
sigprocmask(SIG_BLOCK, &oldmask, NULL);
if (!WIFEXITED(status) || WEXITSTATUS(status)) { if (!WIFEXITED(status) || WEXITSTATUS(status)) {
pr_err("worker failed: %d\n", status); pr_err("worker failed: %d\n", status);
......
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