]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - kernel/exit.c
Merge branch 'x86-x32-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[mirror_ubuntu-artful-kernel.git] / kernel / exit.c
index 16b07bfac224d3f13960b09502fbecfba8897db0..d8bd3b425fa78413f94c9278f481672faebb999c 100644 (file)
@@ -474,7 +474,7 @@ static void close_files(struct files_struct * files)
                i = j * __NFDBITS;
                if (i >= fdt->max_fds)
                        break;
-               set = fdt->open_fds->fds_bits[j++];
+               set = fdt->open_fds[j++];
                while (set) {
                        if (set & 1) {
                                struct file * file = xchg(&fdt->fd[i], NULL);
@@ -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)
@@ -711,8 +711,11 @@ static struct task_struct *find_new_reaper(struct task_struct *father)
 
        if (unlikely(pid_ns->child_reaper == father)) {
                write_unlock_irq(&tasklist_lock);
-               if (unlikely(pid_ns == &init_pid_ns))
-                       panic("Attempted to kill init!");
+               if (unlikely(pid_ns == &init_pid_ns)) {
+                       panic("Attempted to kill init! exitcode=0x%08x\n",
+                               father->signal->group_exit_code ?:
+                                       father->exit_code);
+               }
 
                zap_pid_ns_processes(pid_ns);
                write_lock_irq(&tasklist_lock);
@@ -722,6 +725,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;