2007-11-06  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* strace.c [LINUX] (droptcb): Recurse on TCP->parent if it is a
	TCB_EXITING zombie group leader.
	* test/childthread.c: New file.
	* test/.cvsignore, test/Makefile: Add it.
	Code advisory: Roland McGrath
	Fixes RH#354261.
diff --git a/test/.cvsignore b/test/.cvsignore
index c415255..58caafe 100644
--- a/test/.cvsignore
+++ b/test/.cvsignore
@@ -4,3 +4,4 @@
 vfork
 clone
 leaderkill
+childthread
diff --git a/test/Makefile b/test/Makefile
index 2879c08..283094f 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -2,10 +2,12 @@
 # $Id$
 #
 
-all: vfork fork sig skodic clone leaderkill
+all: vfork fork sig skodic clone leaderkill childthread
 
 leaderkill: LDFLAGS += -pthread
 
+childthread: LDFLAGS += -pthread
+
 clean distclean:
 	rm -f clone vfork fork sig leaderkill *.o core
 
diff --git a/test/childthread.c b/test/childthread.c
new file mode 100644
index 0000000..bc10d3a
--- /dev/null
+++ b/test/childthread.c
@@ -0,0 +1,59 @@
+/* Test exit of a child of a TCB_EXITING child where the toplevel process starts
+ * waiting on it.  The middle one gets detached and strace must update the
+ * toplevel process'es number of attached children to 0.
+ * 
+ * gcc -o test/childthread test/childthread.c -Wall -ggdb2 -pthread;./strace -f ./test/childthread
+ * It must print: write(1, "OK\n", ...
+ */
+
+#include <pthread.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/wait.h>
+
+static void *start0 (void *arg)
+{
+  pause ();
+  /* NOTREACHED */
+  assert (0);
+}
+
+int main (void)
+{
+  pthread_t thread0;
+  int i;
+  pid_t child, got_pid;
+  int status;
+
+  child = fork ();
+  switch (child)
+    {
+    case -1:
+      assert (0);
+    case 0:
+      i = pthread_create (&thread0, NULL, start0, NULL);
+      assert (i == 0);
+      /* The thread must be initialized, it becomes thread-child of this
+	 process-child (child of a child of the toplevel process).  */
+      sleep (1);
+      /* Here the child TCB cannot be deallocated as there still exist
+       * children (the thread child in START0).  */
+      exit (42);
+      /* NOTREACHED */
+      assert (0);
+    default:
+      /* We must not be waiting in WAITPID when the child double-exits.  */
+      sleep (2);
+      /* PID must be -1.  */
+      got_pid = waitpid (-1, &status, 0);
+      assert (got_pid == child);
+      assert (WIFEXITED (status));
+      assert (WEXITSTATUS (status) == 42);
+      puts ("OK");
+      exit (0);
+    }
+  /* NOTREACHED */
+  assert (0);
+}