|
@@ -687,11 +687,11 @@ static void exit_mm(struct task_struct * tsk)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * When we die, we re-parent all our children.
|
|
|
- * Try to give them to another thread in our thread
|
|
|
- * group, and if no such member exists, give it to
|
|
|
- * the child reaper process (ie "init") in our pid
|
|
|
- * space.
|
|
|
+ * When we die, we re-parent all our children, and try to:
|
|
|
+ * 1. give them to another thread in our thread group, if such a member exists
|
|
|
+ * 2. give it to the first ancestor process which prctl'd itself as a
|
|
|
+ * child_subreaper for its children (like a service manager)
|
|
|
+ * 3. give it to the init process (PID 1) in our pid namespace
|
|
|
*/
|
|
|
static struct task_struct *find_new_reaper(struct task_struct *father)
|
|
|
__releases(&tasklist_lock)
|
|
@@ -722,6 +722,29 @@ static struct task_struct *find_new_reaper(struct task_struct *father)
|
|
|
* forget_original_parent() must move them somewhere.
|
|
|
*/
|
|
|
pid_ns->child_reaper = init_pid_ns.child_reaper;
|
|
|
+ } else if (father->signal->has_child_subreaper) {
|
|
|
+ struct task_struct *reaper;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Find the first ancestor marked as child_subreaper.
|
|
|
+ * Note that the code below checks same_thread_group(reaper,
|
|
|
+ * pid_ns->child_reaper). This is what we need to DTRT in a
|
|
|
+ * PID namespace. However we still need the check above, see
|
|
|
+ * http://marc.info/?l=linux-kernel&m=131385460420380
|
|
|
+ */
|
|
|
+ for (reaper = father->real_parent;
|
|
|
+ reaper != &init_task;
|
|
|
+ reaper = reaper->real_parent) {
|
|
|
+ if (same_thread_group(reaper, pid_ns->child_reaper))
|
|
|
+ break;
|
|
|
+ if (!reaper->signal->is_child_subreaper)
|
|
|
+ continue;
|
|
|
+ thread = reaper;
|
|
|
+ do {
|
|
|
+ if (!(thread->flags & PF_EXITING))
|
|
|
+ return reaper;
|
|
|
+ } while_each_thread(reaper, thread);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return pid_ns->child_reaper;
|