[CRIU] [PATCH v2 3/3] ns: Make pid_ns helpers as children of criu main process
Kirill Tkhai
ktkhai at virtuozzo.com
Fri Jul 14 15:40:32 MSK 2017
If a task, holding userns_sync_lock unexpectedly exits,
criu will hang on error path in restore_root_task(),
because it can't use usernsd to destroy them.
Lets remove the intermediary: we'll create pid_ns helpers
as children of criu main task, and criu main task will
be able to use simple kill() to stop them.
v2: Make code more compact, add a comment.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/cr-restore.c | 4 ++++
criu/namespaces.c | 32 +++-----------------------------
2 files changed, 7 insertions(+), 29 deletions(-)
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index e14fa0694..08a40b40c 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -1490,6 +1490,10 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
break;
}
+ /* criu destroys pid_ns helpers under blocked SIGCHLD, we mustn't catch them here */
+ if (!current)
+ warn_if_pid_ns_helper_exited(pid);
+
if (exit)
pr_err("%d exited, status=%d\n", pid, status);
else
diff --git a/criu/namespaces.c b/criu/namespaces.c
index 38235e6d7..9579fccef 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -1604,23 +1604,6 @@ void warn_if_pid_ns_helper_exited(pid_t real_pid)
pr_err("Spurious pid ns helper: pid=%d\n", real_pid);
}
-static void usernsd_handler(int signal, siginfo_t *siginfo, void *data)
-{
- pid_t pid = siginfo->si_pid;
- int status;
-
- while (pid) {
- pid = waitpid(-1, &status, WNOHANG);
- if (pid <= 0)
- return;
-
- warn_if_pid_ns_helper_exited(pid);
-
- pr_err("%d finished unexpected: status=%d\n", pid, status);
- futex_abort_and_wake(&task_entries->nr_in_progress);
- }
-}
-
static int usernsd_recv_transport(void *arg, int fd, pid_t pid)
{
if (install_service_fd(TRANSPORT_FD_OFF, fd) < 0) {
@@ -1664,11 +1647,6 @@ static int usernsd(int sk)
{
pr_info("uns: Daemon started\n");
- if (criu_signals_setup(usernsd_handler) < 0) {
- pr_err("Can't setup handler\n");
- return -1;
- }
-
while (1) {
struct unsc_msg um;
static char msg[MAX_UNSFD_MSG_SIZE];
@@ -2723,7 +2701,7 @@ static int do_create_pid_ns_helper(void *arg, int sk, pid_t unused_pid)
unlock_last_pid();
goto restore_ns;
}
- child = fork();
+ child = sys_clone_unified(CLONE_PARENT|SIGCHLD, NULL, NULL, NULL, 0);
if (!child)
exit(pid_ns_helper(ns, sk));
saved_errno = errno;
@@ -2785,7 +2763,7 @@ int create_pid_ns_helper(struct ns_id *ns)
return 0;
}
-static int do_destroy_pid_ns_helpers(void *arg, int fd, pid_t unused)
+static int do_destroy_pid_ns_helpers(void)
{
int status, sig_blocked = true, ret = 0;
sigset_t sig_mask;
@@ -2834,11 +2812,7 @@ int destroy_pid_ns_helpers(void)
if (!(root_ns_mask & CLONE_NEWPID))
return 0;
- if (userns_call(do_destroy_pid_ns_helpers, 0, NULL, 0, -1) < 0) {
- pr_err("Can't create pid_ns helper\n");
- return -1;
- }
- return 0;
+ return do_destroy_pid_ns_helpers();
}
struct ns_desc pid_ns_desc = NS_DESC_ENTRY(CLONE_NEWPID, "pid", "pid_for_children");
More information about the CRIU
mailing list