ptrace: reintroduce __ptrace_detach() as a callee of ptrace_exit()
Oleg Nesterov [Thu, 2 Apr 2009 23:58:13 +0000 (16:58 -0700)]
No functional changes, preparation for the next patch.

Move the "should we release this child" logic into the separate handler,
__ptrace_detach().

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Jerome Marchand <jmarchan@redhat.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

kernel/exit.c

index 7a83114..576eae2 100644 (file)
@@ -744,6 +744,38 @@ static int ignoring_children(struct sighand_struct *sigh)
        return ret;
 }
 
+/* Returns nonzero if the tracee should be released. */
+int __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
+{
+       __ptrace_unlink(p);
+
+       if (p->exit_state != EXIT_ZOMBIE)
+               return 0;
+       /*
+        * If it's a zombie, our attachedness prevented normal
+        * parent notification or self-reaping.  Do notification
+        * now if it would have happened earlier.  If it should
+        * reap itself we return true.
+        *
+        * If it's our own child, there is no notification to do.
+        * But if our normal children self-reap, then this child
+        * was prevented by ptrace and we must reap it now.
+        */
+       if (!task_detached(p) && thread_group_empty(p)) {
+               if (!same_thread_group(p->real_parent, tracer))
+                       do_notify_parent(p, p->exit_signal);
+               else if (ignoring_children(tracer->sighand))
+                       p->exit_signal = -1;
+       }
+
+       if (!task_detached(p))
+               return 0;
+
+       /* Mark it as in the process of being reaped. */
+       p->exit_state = EXIT_DEAD;
+       return 1;
+}
+
 /*
  * Detach all tasks we were using ptrace on.
  * Any that need to be release_task'd are put on the @dead list.
@@ -755,36 +787,8 @@ static void ptrace_exit(struct task_struct *parent, struct list_head *dead)
        struct task_struct *p, *n;
 
        list_for_each_entry_safe(p, n, &parent->ptraced, ptrace_entry) {
-               __ptrace_unlink(p);
-
-               if (p->exit_state != EXIT_ZOMBIE)
-                       continue;
-
-               /*
-                * If it's a zombie, our attachedness prevented normal
-                * parent notification or self-reaping.  Do notification
-                * now if it would have happened earlier.  If it should
-                * reap itself, add it to the @dead list.  We can't call
-                * release_task() here because we already hold tasklist_lock.
-                *
-                * If it's our own child, there is no notification to do.
-                * But if our normal children self-reap, then this child
-                * was prevented by ptrace and we must reap it now.
-                */
-               if (!task_detached(p) && thread_group_empty(p)) {
-                       if (!same_thread_group(p->real_parent, parent))
-                               do_notify_parent(p, p->exit_signal);
-                       else if (ignoring_children(parent->sighand))
-                               p->exit_signal = -1;
-               }
-
-               if (task_detached(p)) {
-                       /*
-                        * Mark it as in the process of being reaped.
-                        */
-                       p->exit_state = EXIT_DEAD;
+               if (__ptrace_detach(parent, p))
                        list_add(&p->ptrace_entry, dead);
-               }
        }
 }