tracing: Fix invalid function_graph entry
[safe/jmp/linux-2.6] / kernel / exit.c
index 9c6881a..869dc22 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/completion.h>
 #include <linux/personality.h>
 #include <linux/tty.h>
-#include <linux/mnt_namespace.h>
 #include <linux/iocontext.h>
 #include <linux/key.h>
 #include <linux/security.h>
@@ -1082,8 +1081,8 @@ SYSCALL_DEFINE1(exit_group, int, error_code)
 
 struct wait_opts {
        enum pid_type           wo_type;
-       struct pid              *wo_pid;
        int                     wo_flags;
+       struct pid              *wo_pid;
 
        struct siginfo __user   *wo_info;
        int __user              *wo_stat;
@@ -1197,8 +1196,11 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
        }
 
        traced = ptrace_reparented(p);
-
-       if (likely(!traced)) {
+       /*
+        * It can be ptraced but not reparented, check
+        * !task_detached() to filter out sub-threads.
+        */
+       if (likely(!traced) && likely(!task_detached(p))) {
                struct signal_struct *psig;
                struct signal_struct *sig;
 
@@ -1581,7 +1583,7 @@ repeat:
           (!wo->wo_pid || hlist_empty(&wo->wo_pid->tasks[wo->wo_type])))
                goto notask;
 
-       current->state = TASK_INTERRUPTIBLE;
+       set_current_state(TASK_INTERRUPTIBLE);
        read_lock(&tasklist_lock);
        tsk = current;
        do {
@@ -1595,9 +1597,7 @@ repeat:
 
                if (wo->wo_flags & __WNOTHREAD)
                        break;
-               tsk = next_thread(tsk);
-               BUG_ON(tsk->signal != current->signal);
-       } while (tsk != current);
+       } while_each_thread(current, tsk);
        read_unlock(&tasklist_lock);
 
 notask:
@@ -1610,7 +1610,7 @@ notask:
                }
        }
 end:
-       current->state = TASK_RUNNING;
+       __set_current_state(TASK_RUNNING);
        remove_wait_queue(&current->signal->wait_chldexit,&wait);
        if (wo->wo_info) {
                struct siginfo __user *infop = wo->wo_info;