From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27213 invoked by alias); 19 Mar 2004 19:29:55 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 27189 invoked from network); 19 Mar 2004 19:29:54 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sources.redhat.com with SMTP; 19 Mar 2004 19:29:54 -0000 Received: from int-mx2.corp.redhat.com (nat-pool-rdu-dmz.redhat.com [172.16.52.200] (may be forged)) by mx1.redhat.com (8.12.10/8.12.10) with ESMTP id i2JJToWA015323 for ; Fri, 19 Mar 2004 14:29:50 -0500 Received: from potter.sfbay.redhat.com (potter.sfbay.redhat.com [172.16.27.15]) by int-mx2.corp.redhat.com (8.11.6/8.11.6) with ESMTP id i2JJTnM06347; Fri, 19 Mar 2004 14:29:49 -0500 Received: from redhat.com (dhcp-172-16-25-160.sfbay.redhat.com [172.16.25.160]) by potter.sfbay.redhat.com (8.11.6/8.11.6) with ESMTP id i2JJTmR01031; Fri, 19 Mar 2004 11:29:48 -0800 Message-ID: <405B4A2B.3050204@redhat.com> Date: Fri, 19 Mar 2004 19:29:00 -0000 From: Michael Snyder Organization: Red Hat, Inc. User-Agent: Mozilla/5.0 (X11; U; Linux i686; es-ES; rv:1.4) Gecko/20030922 MIME-Version: 1.0 To: Michael Snyder CC: Daniel Jacobowitz , gdb-patches@sources.redhat.com Subject: Re: Daniel, thread vs. fork question. References: <404FBC18.4090909@redhat.com> <20040311015126.GA17829@nevyn.them.org> <404FCD75.4080606@redhat.com> In-Reply-To: <404FCD75.4080606@redhat.com> Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit X-RedHat-Spam-Score: 0 X-SW-Source: 2004-03/txt/msg00466.txt.bz2 Michael Snyder wrote: > Daniel Jacobowitz wrote: > >> On Thu, Mar 11, 2004 at 01:08:40AM +0000, Michael Snyder wrote: >> >>> Hey Daniel, >>> >>> Got a question concerning the code in >>> linux-nat.c::linux_handle_extended_wait. >>> >>> You've got a PTRACE_EVENT_FORK event, and now you're going to call >>> waitpid. You pull a pid out of a list of stopped pids, and wait for >>> it using waitpid. In your comment, you explain that you don't have to >>> worry about the pid being a clone, because you didn't ask for pids in >>> the event mask. >>> >>> But how is this affected by threads, especially NPTL threads? >>> I've got a fairly simple test-case (modified from pthreads.c, >>> I'll attach it), in which a child thread calls fork -- but gdb >>> apparently tries to wait on the main thread (or perhaps the most >>> recent event thread). Since that's not the thread that called >>> fork, waitpid returns -1 with "no child". Gdb reports: >>> waiting for new child: No child processes. >>> >>> FWIW, I've tried this on both a single-processor and an SMP machine. >> >> >> >> No attachment? > > > Argh. Inevitable, isn't it? See currently attached. > > > Also, what glibc/nptl version are you using. > > Well, it's RHEL3, so I believe it's glibc 2.3 and nptl > (not sure what version of nptl). > >> It's entirely possible that I didn't handle some threaded case. But we >> save the PID that we plan to wait on, which should be the child thread, >> so I don't see how what you're describing can happn. > > > It's repeatable, on at least 3 machines. Let me know (now that I've > actually provided the test case) if you can't reproduce it. Hey Daniel, have you had a chance to try and reproduce this? I've now had a second (completely unrelated) person call it to my attention. New information -- I've got two fenceposts for you. Apparently this did not happen as of 11/29/2002, but did happen as of 1/6/2004. These dates are from the internal Red Hat repository, though, so they probably lag the dates in sourceware somewhat. > > > ------------------------------------------------------------------------ > > /* Pthreads test program. > Copyright 1996, 2002, 2003 > Free Software Foundation, Inc. > > Written by Fred Fish of Cygnus Support > Contributed by Cygnus Support > > This file is part of GDB. > > This program is free software; you can redistribute it and/or modify > it under the terms of the GNU General Public License as published by > the Free Software Foundation; either version 2 of the License, or > (at your option) any later version. > > This program is distributed in the hope that it will be useful, > but WITHOUT ANY WARRANTY; without even the implied warranty of > MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > GNU General Public License for more details. > > You should have received a copy of the GNU General Public License > along with this program; if not, write to the Free Software > Foundation, Inc., 59 Temple Place - Suite 330, > Boston, MA 02111-1307, USA. */ > > #include > #include > > /* Under OSF 2.0 & 3.0 and HPUX 10, the second arg of pthread_create > is prototyped to be just a "pthread_attr_t", while under Solaris it > is a "pthread_attr_t *". Arg! */ > > #if defined (__osf__) || defined (__hpux__) > #define PTHREAD_CREATE_ARG2(arg) arg > #define PTHREAD_CREATE_NULL_ARG2 null_attr > static pthread_attr_t null_attr; > #else > #define PTHREAD_CREATE_ARG2(arg) &arg > #define PTHREAD_CREATE_NULL_ARG2 NULL > #endif > > static int verbose = 0; > > static void > common_routine (arg) > int arg; > { > static int from_thread1; > static int from_thread2; > static int from_main; > static int hits; > static int full_coverage; > > if (verbose) printf("common_routine (%d)\n", arg); > hits++; > switch (arg) > { > case 0: > from_main++; > break; > case 1: > from_thread1++; > break; > case 2: > from_thread2++; > break; > } > if (from_main && from_thread1 && from_thread2) > full_coverage = 1; > } > > static void * > thread1 (void *arg) > { > int i; > int z = 0; > > if (verbose) printf ("thread1 (%0x) ; pid = %d\n", arg, getpid ()); > for (i=1; i <= 10000000; i++) > { > if (verbose) printf("thread1 %d\n", pthread_self ()); > z += i; > common_routine (1); > sleep(1); > } > return (void *) 0; > } > > static void * > thread2 (void * arg) > { > int i; > int k = 0; > > if (verbose) printf ("thread2 (%0x) ; pid = %d\n", arg, getpid ()); > for (i=1; i <= 10000000; i++) > { > if (verbose) printf("thread2 %d\n", pthread_self ()); > k += i; > common_routine (2); > sleep(1); > } > sleep(100); > return (void *) 0; > } > > static void * > forkthread (void *arg) > { > int pid = fork (); > int ret = 0, status = 0; > > switch (pid) { > case 0: /* child */ > printf ("I'm the child, my pid = %d\n", getpid ()); > break; > case -1: /* Parent, failed to create child */ > default: /* Parent, fork succeeded. */ > printf ("I'm the parent, mypid = %d, fork returned %d\n", > getpid (), pid); > if (pid == -1) > perror ("fork failed: "); > else > waitpid (pid, &status, 0); > } > } > > void > foo (a, b, c) > int a, b, c; > { > int d, e, f; > > if (verbose) printf("a=%d\n", a); > } > > main(argc, argv) > int argc; > char **argv; > { > pthread_t tid1, tid2, forktid; > int j; > int t = 0; > void (*xxx) (); > pthread_attr_t attr; > > if (verbose) printf ("pid = %d\n", getpid()); > > foo (1, 2, 3); > > #ifndef __osf__ > if (pthread_attr_init (&attr)) > { > perror ("pthread_attr_init 1"); > exit (1); > } > #endif > > #ifdef PTHREAD_SCOPE_SYSTEM > if (pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM)) > { > perror ("pthread_attr_setscope 1"); > exit (1); > } > #endif > > if (pthread_create (&tid1, PTHREAD_CREATE_ARG2(attr), thread1, (void *) 0xfeedface)) > { > perror ("pthread_create 1"); > exit (1); > } > if (verbose) printf ("Made thread %d\n", tid1); > sleep (1); > > if (pthread_create (&tid2, PTHREAD_CREATE_NULL_ARG2, thread2, (void *) 0xdeadbeef)) > { > perror ("pthread_create 2"); > exit (1); > } > if (verbose) printf("Made thread %d\n", tid2); > sleep (1); > > if (pthread_create (&forktid, PTHREAD_CREATE_NULL_ARG2, forkthread, (void *) 0xdeadbeef)) > { > perror ("pthread_create 3 (fork)"); > exit (1); > } > if (verbose) printf("Made thread %d\n", tid2); > > for (j = 1; j <= 10000000; j++) > { > if (verbose) printf("top %d\n", pthread_self ()); > common_routine (0); > sleep(1); > t += j; > } > > exit(0); > } >