From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21160 invoked by alias); 11 Mar 2004 02:22:56 -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 21117 invoked from network); 11 Mar 2004 02:22:48 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sources.redhat.com with SMTP; 11 Mar 2004 02:22:48 -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 i2B2Ml07026718 for ; Wed, 10 Mar 2004 21:22:47 -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 i2B2MkM27023; Wed, 10 Mar 2004 21:22:46 -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 i2B2MjR32577; Wed, 10 Mar 2004 18:22:45 -0800 Message-ID: <404FCD75.4080606@redhat.com> Date: Fri, 19 Mar 2004 00:09: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: Daniel Jacobowitz CC: gdb-patches@sources.redhat.com Subject: Re: Daniel, thread vs. fork question. References: <404FBC18.4090909@redhat.com> <20040311015126.GA17829@nevyn.them.org> In-Reply-To: <20040311015126.GA17829@nevyn.them.org> Content-Type: multipart/mixed; boundary="------------080903000104000000060704" X-RedHat-Spam-Score: -4.9 X-SW-Source: 2004-03/txt/msg00264.txt.bz2 This is a multi-part message in MIME format. --------------080903000104000000060704 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1560 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. --------------080903000104000000060704 Content-Type: text/plain; name="pthreads.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="pthreads.c" Content-length: 4410 /* 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); } --------------080903000104000000060704-- From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21160 invoked by alias); 11 Mar 2004 02:22:56 -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 21117 invoked from network); 11 Mar 2004 02:22:48 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sources.redhat.com with SMTP; 11 Mar 2004 02:22:48 -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 i2B2Ml07026718 for ; Wed, 10 Mar 2004 21:22:47 -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 i2B2MkM27023; Wed, 10 Mar 2004 21:22:46 -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 i2B2MjR32577; Wed, 10 Mar 2004 18:22:45 -0800 Message-ID: <404FCD75.4080606@redhat.com> Date: Thu, 11 Mar 2004 02:22: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: Daniel Jacobowitz CC: gdb-patches@sources.redhat.com Subject: Re: Daniel, thread vs. fork question. References: <404FBC18.4090909@redhat.com> <20040311015126.GA17829@nevyn.them.org> In-Reply-To: <20040311015126.GA17829@nevyn.them.org> Content-Type: multipart/mixed; boundary="------------080903000104000000060704" X-RedHat-Spam-Score: -4.9 X-SW-Source: 2004-03.o/txt/msg00264.txt Message-ID: <20040311022200.4KhkZChPUajV91Ga-WWztWtYxsBqqiKbseyrdKmCM4o@z> This is a multi-part message in MIME format. --------------080903000104000000060704 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1560 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. --------------080903000104000000060704 Content-Type: text/plain; name="pthreads.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="pthreads.c" Content-length: 4410 /* 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); } --------------080903000104000000060704--