Merge branch 'for-3.1' of git://linux-nfs.org/~bfields/linux
[pandora-kernel.git] / kernel / exit.c
index f2b321b..9ee58bb 100644 (file)
@@ -85,7 +85,6 @@ static void __exit_signal(struct task_struct *tsk)
        struct tty_struct *uninitialized_var(tty);
 
        sighand = rcu_dereference_check(tsk->sighand,
-                                       rcu_read_lock_held() ||
                                        lockdep_tasklist_lock_is_held());
        spin_lock(&sighand->siglock);
 
@@ -169,7 +168,6 @@ void release_task(struct task_struct * p)
        struct task_struct *leader;
        int zap_leader;
 repeat:
-       tracehook_prepare_release_task(p);
        /* don't need to get the RCU readlock here - the process is dead and
         * can't be modifying its own credentials. But shut RCU-lockdep up */
        rcu_read_lock();
@@ -179,7 +177,7 @@ repeat:
        proc_flush_task(p);
 
        write_lock_irq(&tasklist_lock);
-       tracehook_finish_release_task(p);
+       ptrace_release_task(p);
        __exit_signal(p);
 
        /*
@@ -190,22 +188,12 @@ repeat:
        zap_leader = 0;
        leader = p->group_leader;
        if (leader != p && thread_group_empty(leader) && leader->exit_state == EXIT_ZOMBIE) {
-               BUG_ON(task_detached(leader));
-               do_notify_parent(leader, leader->exit_signal);
                /*
                 * If we were the last child thread and the leader has
                 * exited already, and the leader's parent ignores SIGCHLD,
                 * then we are the one who should release the leader.
-                *
-                * do_notify_parent() will have marked it self-reaping in
-                * that case.
-                */
-               zap_leader = task_detached(leader);
-
-               /*
-                * This maintains the invariant that release_task()
-                * only runs on a task in EXIT_DEAD, just for sanity.
                 */
+               zap_leader = do_notify_parent(leader, leader->exit_signal);
                if (zap_leader)
                        leader->exit_state = EXIT_DEAD;
        }
@@ -277,18 +265,16 @@ int is_current_pgrp_orphaned(void)
        return retval;
 }
 
-static int has_stopped_jobs(struct pid *pgrp)
+static bool has_stopped_jobs(struct pid *pgrp)
 {
-       int retval = 0;
        struct task_struct *p;
 
        do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
-               if (!task_is_stopped(p))
-                       continue;
-               retval = 1;
-               break;
+               if (p->signal->flags & SIGNAL_STOP_STOPPED)
+                       return true;
        } while_each_pid_task(pgrp, PIDTYPE_PGID, p);
-       return retval;
+
+       return false;
 }
 
 /*
@@ -751,7 +737,7 @@ static void reparent_leader(struct task_struct *father, struct task_struct *p,
 {
        list_move_tail(&p->sibling, &p->real_parent->children);
 
-       if (task_detached(p))
+       if (p->exit_state == EXIT_DEAD)
                return;
        /*
         * If this is a threaded reparent there is no need to
@@ -764,10 +750,9 @@ static void reparent_leader(struct task_struct *father, struct task_struct *p,
        p->exit_signal = SIGCHLD;
 
        /* If it has exited notify the new parent about this child's death. */
-       if (!task_ptrace(p) &&
+       if (!p->ptrace &&
            p->exit_state == EXIT_ZOMBIE && thread_group_empty(p)) {
-               do_notify_parent(p, p->exit_signal);
-               if (task_detached(p)) {
+               if (do_notify_parent(p, p->exit_signal)) {
                        p->exit_state = EXIT_DEAD;
                        list_move_tail(&p->sibling, dead);
                }
@@ -794,7 +779,7 @@ static void forget_original_parent(struct task_struct *father)
                do {
                        t->real_parent = reaper;
                        if (t->parent == father) {
-                               BUG_ON(task_ptrace(t));
+                               BUG_ON(t->ptrace);
                                t->parent = t->real_parent;
                        }
                        if (t->pdeath_signal)
@@ -819,8 +804,7 @@ static void forget_original_parent(struct task_struct *father)
  */
 static void exit_notify(struct task_struct *tsk, int group_dead)
 {
-       int signal;
-       void *cookie;
+       bool autoreap;
 
        /*
         * This does two things:
@@ -851,26 +835,33 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
         * we have changed execution domain as these two values started
         * the same after a fork.
         */
-       if (tsk->exit_signal != SIGCHLD && !task_detached(tsk) &&
+       if (thread_group_leader(tsk) && tsk->exit_signal != SIGCHLD &&
            (tsk->parent_exec_id != tsk->real_parent->self_exec_id ||
             tsk->self_exec_id != tsk->parent_exec_id))
                tsk->exit_signal = SIGCHLD;
 
-       signal = tracehook_notify_death(tsk, &cookie, group_dead);
-       if (signal >= 0)
-               signal = do_notify_parent(tsk, signal);
+       if (unlikely(tsk->ptrace)) {
+               int sig = thread_group_leader(tsk) &&
+                               thread_group_empty(tsk) &&
+                               !ptrace_reparented(tsk) ?
+                       tsk->exit_signal : SIGCHLD;
+               autoreap = do_notify_parent(tsk, sig);
+       } else if (thread_group_leader(tsk)) {
+               autoreap = thread_group_empty(tsk) &&
+                       do_notify_parent(tsk, tsk->exit_signal);
+       } else {
+               autoreap = true;
+       }
 
-       tsk->exit_state = signal == DEATH_REAP ? EXIT_DEAD : EXIT_ZOMBIE;
+       tsk->exit_state = autoreap ? EXIT_DEAD : EXIT_ZOMBIE;
 
        /* mt-exec, de_thread() is waiting for group leader */
        if (unlikely(tsk->signal->notify_count < 0))
                wake_up_process(tsk->signal->group_exit_task);
        write_unlock_irq(&tasklist_lock);
 
-       tracehook_report_death(tsk, signal, cookie, group_dead);
-
        /* If the process is dead, release it - nobody will wait for it */
-       if (signal == DEATH_REAP)
+       if (autoreap)
                release_task(tsk);
 }
 
@@ -906,7 +897,6 @@ NORET_TYPE void do_exit(long code)
 
        profile_task_exit(tsk);
 
-       WARN_ON(atomic_read(&tsk->fs_excl));
        WARN_ON(blk_needs_flush_plug(tsk));
 
        if (unlikely(in_interrupt()))
@@ -923,7 +913,7 @@ NORET_TYPE void do_exit(long code)
         */
        set_fs(USER_DS);
 
-       tracehook_report_exit(&code);
+       ptrace_event(PTRACE_EVENT_EXIT, code);
 
        validate_creds_for_do_exit(tsk);
 
@@ -1235,9 +1225,9 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
        traced = ptrace_reparented(p);
        /*
         * It can be ptraced but not reparented, check
-        * !task_detached() to filter out sub-threads.
+        * thread_group_leader() to filter out sub-threads.
         */
-       if (likely(!traced) && likely(!task_detached(p))) {
+       if (likely(!traced) && thread_group_leader(p)) {
                struct signal_struct *psig;
                struct signal_struct *sig;
                unsigned long maxrss;
@@ -1345,16 +1335,13 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
                /* We dropped tasklist, ptracer could die and untrace */
                ptrace_unlink(p);
                /*
-                * If this is not a detached task, notify the parent.
-                * If it's still not detached after that, don't release
-                * it now.
+                * If this is not a sub-thread, notify the parent.
+                * If parent wants a zombie, don't release it now.
                 */
-               if (!task_detached(p)) {
-                       do_notify_parent(p, p->exit_signal);
-                       if (!task_detached(p)) {
-                               p->exit_state = EXIT_ZOMBIE;
-                               p = NULL;
-                       }
+               if (thread_group_leader(p) &&
+                   !do_notify_parent(p, p->exit_signal)) {
+                       p->exit_state = EXIT_ZOMBIE;
+                       p = NULL;
                }
                write_unlock_irq(&tasklist_lock);
        }
@@ -1367,7 +1354,8 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
 static int *task_stopped_code(struct task_struct *p, bool ptrace)
 {
        if (ptrace) {
-               if (task_is_stopped_or_traced(p))
+               if (task_is_stopped_or_traced(p) &&
+                   !(p->jobctl & JOBCTL_LISTENING))
                        return &p->exit_code;
        } else {
                if (p->signal->flags & SIGNAL_STOP_STOPPED)
@@ -1563,7 +1551,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
                 * Notification and reaping will be cascaded to the real
                 * parent when the ptracer detaches.
                 */
-               if (likely(!ptrace) && unlikely(task_ptrace(p))) {
+               if (likely(!ptrace) && unlikely(p->ptrace)) {
                        /* it will become visible, clear notask_error */
                        wo->notask_error = 0;
                        return 0;
@@ -1606,8 +1594,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
                 * own children, it should create a separate process which
                 * takes the role of real parent.
                 */
-               if (likely(!ptrace) && task_ptrace(p) &&
-                   same_thread_group(p->parent, p->real_parent))
+               if (likely(!ptrace) && p->ptrace && !ptrace_reparented(p))
                        return 0;
 
                /*