diff options
Diffstat (limited to 'kernel/pid_namespace.c')
| -rw-r--r-- | kernel/pid_namespace.c | 28 | 
1 files changed, 24 insertions, 4 deletions
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index db95d8eb761b..bc6d6a89b6e6 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -190,7 +190,11 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)  	/* Don't allow any more processes into the pid namespace */  	disable_pid_allocation(pid_ns); -	/* Ignore SIGCHLD causing any terminated children to autoreap */ +	/* +	 * Ignore SIGCHLD causing any terminated children to autoreap. +	 * This speeds up the namespace shutdown, plus see the comment +	 * below. +	 */  	spin_lock_irq(&me->sighand->siglock);  	me->sighand->action[SIGCHLD - 1].sa.sa_handler = SIG_IGN;  	spin_unlock_irq(&me->sighand->siglock); @@ -223,15 +227,31 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)  	}  	read_unlock(&tasklist_lock); -	/* Firstly reap the EXIT_ZOMBIE children we may have. */ +	/* +	 * Reap the EXIT_ZOMBIE children we had before we ignored SIGCHLD. +	 * sys_wait4() will also block until our children traced from the +	 * parent namespace are detached and become EXIT_DEAD. +	 */  	do {  		clear_thread_flag(TIF_SIGPENDING);  		rc = sys_wait4(-1, NULL, __WALL, NULL);  	} while (rc != -ECHILD);  	/* -	 * sys_wait4() above can't reap the TASK_DEAD children. -	 * Make sure they all go away, see free_pid(). +	 * sys_wait4() above can't reap the EXIT_DEAD children but we do not +	 * really care, we could reparent them to the global init. We could +	 * exit and reap ->child_reaper even if it is not the last thread in +	 * this pid_ns, free_pid(nr_hashed == 0) calls proc_cleanup_work(), +	 * pid_ns can not go away until proc_kill_sb() drops the reference. +	 * +	 * But this ns can also have other tasks injected by setns()+fork(). +	 * Again, ignoring the user visible semantics we do not really need +	 * to wait until they are all reaped, but they can be reparented to +	 * us and thus we need to ensure that pid->child_reaper stays valid +	 * until they all go away. See free_pid()->wake_up_process(). +	 * +	 * We rely on ignored SIGCHLD, an injected zombie must be autoreaped +	 * if reparented.  	 */  	for (;;) {  		set_current_state(TASK_UNINTERRUPTIBLE);  |