From: Roland McGrath Date: Tue, 13 Nov 2007 08:12:12 +0000 (+0000) Subject: 2007-11-06 Jan Kratochvil X-Git-Tag: v4.5.18~102 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=276ceb33f20fc41403e46684e441230296f6a433;p=strace 2007-11-06 Jan Kratochvil * 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/strace.c b/strace.c index b71e093b..341ed04a 100644 --- a/strace.c +++ b/strace.c @@ -1297,6 +1297,16 @@ struct tcb *tcp; if (!(tcp->flags & TCB_CLONE_DETACHED)) #endif tcp->parent->nzombies++; +#ifdef LINUX + /* Update `tcp->parent->parent->nchildren' and the other fields + like NCLONE_DETACHED, only for zombie group leader that has + already reported and been short-circuited at the top of this + function. The same condition as at the top of DETACH. */ + if ((tcp->flags & TCB_CLONE_THREAD) && + tcp->parent->nclone_threads == 0 && + (tcp->parent->flags & TCB_EXITING)) + droptcb(tcp->parent); +#endif tcp->parent = NULL; } diff --git a/test/.cvsignore b/test/.cvsignore index c4152556..58caafe7 100644 --- a/test/.cvsignore +++ b/test/.cvsignore @@ -4,3 +4,4 @@ skodic vfork clone leaderkill +childthread diff --git a/test/Makefile b/test/Makefile index 2879c086..283094f4 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 00000000..bc10d3a0 --- /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 +#include +#include +#include +#include +#include + +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); +}