diff options
Diffstat (limited to 'kernel/pid_namespace.c')
| -rw-r--r-- | kernel/pid_namespace.c | 33 | 
1 files changed, 31 insertions, 2 deletions
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 57bc1fd35b3..b3c7fd55425 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -149,7 +149,12 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)  {  	int nr;  	int rc; -	struct task_struct *task; +	struct task_struct *task, *me = current; + +	/* Ignore SIGCHLD causing any terminated children to autoreap */ +	spin_lock_irq(&me->sighand->siglock); +	me->sighand->action[SIGCHLD - 1].sa.sa_handler = SIG_IGN; +	spin_unlock_irq(&me->sighand->siglock);  	/*  	 * The last thread in the cgroup-init thread group is terminating. @@ -179,11 +184,31 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)  	}  	read_unlock(&tasklist_lock); +	/* Firstly reap the EXIT_ZOMBIE children we may have. */  	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 __unhash_process(). +	 */ +	for (;;) { +		bool need_wait = false; + +		read_lock(&tasklist_lock); +		if (!list_empty(¤t->children)) { +			__set_current_state(TASK_UNINTERRUPTIBLE); +			need_wait = true; +		} +		read_unlock(&tasklist_lock); + +		if (!need_wait) +			break; +		schedule(); +	} +  	if (pid_ns->reboot)  		current->signal->group_exit_code = pid_ns->reboot; @@ -191,6 +216,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)  	return;  } +#ifdef CONFIG_CHECKPOINT_RESTORE  static int pid_ns_ctl_handler(struct ctl_table *table, int write,  		void __user *buffer, size_t *lenp, loff_t *ppos)  { @@ -218,8 +244,8 @@ static struct ctl_table pid_ns_ctl_table[] = {  	},  	{ }  }; -  static struct ctl_path kern_path[] = { { .procname = "kernel", }, { } }; +#endif	/* CONFIG_CHECKPOINT_RESTORE */  int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)  { @@ -253,7 +279,10 @@ int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd)  static __init int pid_namespaces_init(void)  {  	pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC); + +#ifdef CONFIG_CHECKPOINT_RESTORE  	register_sysctl_paths(kern_path, pid_ns_ctl_table); +#endif  	return 0;  }  |