> Because it's also needed for non-CLONE_DETACH processes.  I added it
> earlier down by the release_task, remember?  I deleted it in this patch
> originally, and the change got lost somewhere; my intent is to check for
> this only in release_task and nowhere else.  When I have a clear point
> to resync with Linus again then I'll make sure this is right.
Linus' tree is at http://linux.bkbits.net/linux-2.5/, and i've done the
attached patch to collect & clean up all the things that happened since
yesterday. It's basically what was your tree this morning - i'd suggest
for you to base subsequent patches on BK-curr + this patch. (To reduce
confusion i wont send any new patches for this area from now on.)
	Ingo
diff -rNu linux.orig/kernel/exit.c linux/kernel/exit.c
--- linux.orig/kernel/exit.c	Fri Sep  6 11:37:53 2002
+++ linux/kernel/exit.c	Fri Sep  6 11:39:47 2002
@@ -66,8 +66,12 @@
 	atomic_dec(&p->user->processes);
 	security_ops->task_free_security(p);
 	free_uid(p->user);
-	BUG_ON(p->ptrace || !list_empty(&p->ptrace_list) ||
-					!list_empty(&p->ptrace_children));
+	if (unlikely(p->ptrace)) {
+		write_lock_irq(&tasklist_lock);
+		__ptrace_unlink(p);
+		write_unlock_irq(&tasklist_lock);
+	}
+	BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
 	unhash_process(p);
 
 	release_thread(p);
@@ -428,7 +432,7 @@
 	 * There are only two places where our children can be:
 	 *
 	 * - in our child list
-	 * - in the global ptrace list
+	 * - in our ptraced child list
 	 *
 	 * Search them and reparent children.
 	 */
@@ -443,14 +447,22 @@
 	read_unlock(&tasklist_lock);
 }
 
-static inline void zap_thread(task_t *p, task_t *father)
+static inline void zap_thread(task_t *p, task_t *father, int traced)
 {
-	ptrace_unlink(p);
-	list_del_init(&p->sibling);
-	p->ptrace = 0;
+	/* If we were tracing the thread, release it; otherwise preserve the
+	   ptrace links.  */
+	if (unlikely(traced)) {
+		task_t *trace_task = p->parent;
+		__ptrace_unlink(p);
+		p->ptrace = 1;
+		__ptrace_link(p, trace_task);
+	} else {
+		p->ptrace = 0;
+		list_del_init(&p->sibling);
+		p->parent = p->real_parent;
+		list_add_tail(&p->sibling, &p->parent->children);
+	}
 
-	p->parent = p->real_parent;
-	list_add_tail(&p->sibling, &p->parent->children);
 	if (p->state == TASK_ZOMBIE && p->exit_signal != -1)
 		do_notify_parent(p, p->exit_signal);
 	/*
@@ -541,11 +553,11 @@
 
 zap_again:
 	list_for_each_safe(_p, _n, ¤t->children)
-		zap_thread(list_entry(_p,struct task_struct,sibling), current);
+		zap_thread(list_entry(_p,struct task_struct,sibling), current, 0);
 	list_for_each_safe(_p, _n, ¤t->ptrace_children)
-		zap_thread(list_entry(_p,struct task_struct,ptrace_list), current);
+		zap_thread(list_entry(_p,struct task_struct,ptrace_list), current, 1);
 	/*
-	 * reparent_thread might drop the tasklist lock, thus we could
+	 * zap_thread might drop the tasklist lock, thus we could
 	 * have new children queued back from the ptrace list into the
 	 * child list:
 	 */
@@ -716,17 +728,11 @@
 				retval = p->pid;
 				if (p->real_parent != p->parent) {
 					write_lock_irq(&tasklist_lock);
-					ptrace_unlink(p);
+					__ptrace_unlink(p);
 					do_notify_parent(p, SIGCHLD);
 					write_unlock_irq(&tasklist_lock);
-				} else {
-					if (p->ptrace) {
-						write_lock_irq(&tasklist_lock);
-						ptrace_unlink(p);
-						write_unlock_irq(&tasklist_lock);
-					}
+				} else
 					release_task(p);
-				}
 				goto end_wait4;
 			default:
 				continue;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/