2004-10-19  Roland McGrath  <roland@redhat.com>

	* strace.c (trace): Use handle_group_exit for non-TCB_ATTACHED child
	taking signal when it has nclone_threads > 0.
	* strace.c (handle_group_exit): Don't detach leader that wasn't
	TCB_ATTACHED.
	* strace.c (handle_group_exit, trace): Mark leader with
	TCB_GROUP_EXITING and don't be surprised at child deaths when their
	leader has it set.
	Fixes RH#132150.
diff --git a/strace.c b/strace.c
index 02441fc..ce7701e 100644
--- a/strace.c
+++ b/strace.c
@@ -1926,9 +1926,12 @@
 			      ? tcp->parent
 			      : tcp->nclone_detached > 0
 			      ? tcp : NULL);
+	fprintf(stderr,"handle_group_exit (%d [%d], %d)\n", tcp->pid,
+		leader? leader->pid:-1, sig);
 
 	if (sig < 0) {
-		if (leader != NULL && leader != tcp)
+		if (leader != NULL && leader != tcp &&
+		    !(leader->flags & TCB_GROUP_EXITING))
 			fprintf(stderr,
 				"PANIC: handle_group_exit: %d leader %d\n",
 				tcp->pid, leader ? leader->pid : -1);
@@ -1936,7 +1939,8 @@
 	}
 	else {
 		if (tcp->flags & TCB_ATTACHED) {
-			if (leader != NULL && leader != tcp) {
+			if (leader != NULL && leader != tcp &&
+				(leader->flags & TCB_ATTACHED)) {
 				/* We need to detach the leader so that the
 				   process death will be reported to its real
 				   parent.  But we kill it first to prevent
@@ -1961,6 +1965,8 @@
 			return -1;
 		}
 		else {
+			if (leader != NULL)
+				leader->flags |= TCB_GROUP_EXITING;
 			if (leader != NULL && leader != tcp)
 				droptcb(tcp);
 			/* The leader will report to us as parent now,
@@ -2140,7 +2146,12 @@
 		if (WIFEXITED(status)) {
 			if (debug)
 				fprintf(stderr, "pid %u exited\n", pid);
-			if (tcp->flags & TCB_ATTACHED)
+			if ((tcp->flags & TCB_ATTACHED)
+#ifdef TCB_GROUP_EXITING
+			    && !(tcp->parent && (tcp->parent->flags &
+						 TCB_GROUP_EXITING))
+#endif
+				)
 				fprintf(stderr,
 					"PANIC: attached pid %u exited\n",
 					pid);
@@ -2242,7 +2253,8 @@
 					strsignal(WSTOPSIG(status)), pc, addr);
 				printtrailer(tcp);
 			}
-			if ((tcp->flags & TCB_ATTACHED) &&
+			if (((tcp->flags & TCB_ATTACHED) ||
+			     tcp->nclone_threads > 0) &&
 				!sigishandled(tcp, WSTOPSIG(status))) {
 #ifdef TCB_GROUP_EXITING
 				handle_group_exit(tcp, WSTOPSIG(status));