]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/exit.c
r8169: multicast register update (sync with Realtek's 8.004.00 8168 driver)
[linux-2.6-omap-h63xx.git] / kernel / exit.c
index 4035d391a0d3f8ec12e3b545515ab16585a4456e..8f6185e69b691265746f81a1ca4ce9de9fd8a640 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/acct.h>
 #include <linux/tsacct_kern.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/binfmts.h>
 #include <linux/nsproxy.h>
 #include <linux/pid_namespace.h>
@@ -125,6 +126,12 @@ static void __exit_signal(struct task_struct *tsk)
 
        __unhash_process(tsk);
 
+       /*
+        * Do this under ->siglock, we can race with another thread
+        * doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals.
+        */
+       flush_sigqueue(&tsk->pending);
+
        tsk->signal = NULL;
        tsk->sighand = NULL;
        spin_unlock(&sighand->siglock);
@@ -132,7 +139,6 @@ static void __exit_signal(struct task_struct *tsk)
 
        __cleanup_sighand(sighand);
        clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
-       flush_sigqueue(&tsk->pending);
        if (sig) {
                flush_sigqueue(&sig->shared_pending);
                taskstats_tgid_free(sig);
@@ -334,13 +340,11 @@ void __set_special_pids(struct pid *pid)
        pid_t nr = pid_nr(pid);
 
        if (task_session(curr) != pid) {
-               detach_pid(curr, PIDTYPE_SID);
-               attach_pid(curr, PIDTYPE_SID, pid);
+               change_pid(curr, PIDTYPE_SID, pid);
                set_task_session(curr, nr);
        }
        if (task_pgrp(curr) != pid) {
-               detach_pid(curr, PIDTYPE_PGID);
-               attach_pid(curr, PIDTYPE_PGID, pid);
+               change_pid(curr, PIDTYPE_PGID, pid);
                set_task_pgrp(curr, nr);
        }
 }
@@ -698,7 +702,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
        if (unlikely(traced)) {
                /* Preserve ptrace links if someone else is tracing this child.  */
                list_del_init(&p->ptrace_list);
-               if (p->parent != p->real_parent)
+               if (ptrace_reparented(p))
                        list_add(&p->ptrace_list, &p->real_parent->ptrace_children);
        } else {
                /* If this child is being traced, then we're the one tracing it
@@ -722,7 +726,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
        /* If this is a threaded reparent there is no need to
         * notify anyone anything has happened.
         */
-       if (p->real_parent->group_leader == father->group_leader)
+       if (same_thread_group(p->real_parent, father))
                return;
 
        /* We don't want people slaying init.  */
@@ -865,8 +869,8 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
         * only has special meaning to our real parent.
         */
        if (!task_detached(tsk) && thread_group_empty(tsk)) {
-               int signal = (tsk->parent == tsk->real_parent)
-                               ? tsk->exit_signal : SIGCHLD;
+               int signal = ptrace_reparented(tsk) ?
+                               SIGCHLD : tsk->exit_signal;
                do_notify_parent(tsk, signal);
        } else if (tsk->ptrace) {
                do_notify_parent(tsk, SIGCHLD);
@@ -877,6 +881,7 @@ static void exit_notify(struct task_struct *tsk, int group_dead)
                state = EXIT_DEAD;
        tsk->exit_state = state;
 
+       /* mt-exec, de_thread() is waiting for us */
        if (thread_group_leader(tsk) &&
            tsk->signal->notify_count < 0 &&
            tsk->signal->group_exit_task)
@@ -1268,8 +1273,7 @@ static int wait_task_zombie(struct task_struct *p, int noreap,
                return 0;
        }
 
-       /* traced means p->ptrace, but not vice versa */
-       traced = (p->real_parent != p->parent);
+       traced = ptrace_reparented(p);
 
        if (likely(!traced)) {
                struct signal_struct *psig;