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 57bc1fd35b3c..b3c7fd554250 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) | |||
149 | { | 149 | { |
150 | int nr; | 150 | int nr; |
151 | int rc; | 151 | int rc; |
152 | struct task_struct *task; | 152 | struct task_struct *task, *me = current; |
153 | |||
154 | /* Ignore SIGCHLD causing any terminated children to autoreap */ | ||
155 | spin_lock_irq(&me->sighand->siglock); | ||
156 | me->sighand->action[SIGCHLD - 1].sa.sa_handler = SIG_IGN; | ||
157 | spin_unlock_irq(&me->sighand->siglock); | ||
153 | 158 | ||
154 | /* | 159 | /* |
155 | * The last thread in the cgroup-init thread group is terminating. | 160 | * 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) | |||
179 | } | 184 | } |
180 | read_unlock(&tasklist_lock); | 185 | read_unlock(&tasklist_lock); |
181 | 186 | ||
187 | /* Firstly reap the EXIT_ZOMBIE children we may have. */ | ||
182 | do { | 188 | do { |
183 | clear_thread_flag(TIF_SIGPENDING); | 189 | clear_thread_flag(TIF_SIGPENDING); |
184 | rc = sys_wait4(-1, NULL, __WALL, NULL); | 190 | rc = sys_wait4(-1, NULL, __WALL, NULL); |
185 | } while (rc != -ECHILD); | 191 | } while (rc != -ECHILD); |
186 | 192 | ||
193 | /* | ||
194 | * sys_wait4() above can't reap the TASK_DEAD children. | ||
195 | * Make sure they all go away, see __unhash_process(). | ||
196 | */ | ||
197 | for (;;) { | ||
198 | bool need_wait = false; | ||
199 | |||
200 | read_lock(&tasklist_lock); | ||
201 | if (!list_empty(¤t->children)) { | ||
202 | __set_current_state(TASK_UNINTERRUPTIBLE); | ||
203 | need_wait = true; | ||
204 | } | ||
205 | read_unlock(&tasklist_lock); | ||
206 | |||
207 | if (!need_wait) | ||
208 | break; | ||
209 | schedule(); | ||
210 | } | ||
211 | |||
187 | if (pid_ns->reboot) | 212 | if (pid_ns->reboot) |
188 | current->signal->group_exit_code = pid_ns->reboot; | 213 | current->signal->group_exit_code = pid_ns->reboot; |
189 | 214 | ||
@@ -191,6 +216,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns) | |||
191 | return; | 216 | return; |
192 | } | 217 | } |
193 | 218 | ||
219 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
194 | static int pid_ns_ctl_handler(struct ctl_table *table, int write, | 220 | static int pid_ns_ctl_handler(struct ctl_table *table, int write, |
195 | void __user *buffer, size_t *lenp, loff_t *ppos) | 221 | void __user *buffer, size_t *lenp, loff_t *ppos) |
196 | { | 222 | { |
@@ -218,8 +244,8 @@ static struct ctl_table pid_ns_ctl_table[] = { | |||
218 | }, | 244 | }, |
219 | { } | 245 | { } |
220 | }; | 246 | }; |
221 | |||
222 | static struct ctl_path kern_path[] = { { .procname = "kernel", }, { } }; | 247 | static struct ctl_path kern_path[] = { { .procname = "kernel", }, { } }; |
248 | #endif /* CONFIG_CHECKPOINT_RESTORE */ | ||
223 | 249 | ||
224 | int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd) | 250 | int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd) |
225 | { | 251 | { |
@@ -253,7 +279,10 @@ int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd) | |||
253 | static __init int pid_namespaces_init(void) | 279 | static __init int pid_namespaces_init(void) |
254 | { | 280 | { |
255 | pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC); | 281 | pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC); |
282 | |||
283 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
256 | register_sysctl_paths(kern_path, pid_ns_ctl_table); | 284 | register_sysctl_paths(kern_path, pid_ns_ctl_table); |
285 | #endif | ||
257 | return 0; | 286 | return 0; |
258 | } | 287 | } |
259 | 288 | ||