* Daniel, thread vs. fork question.
@ 2004-03-11 1:08 Michael Snyder
2004-03-19 0:09 ` Daniel Jacobowitz
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Michael Snyder @ 2004-03-11 1:08 UTC (permalink / raw)
To: Daniel Jacobowitz, gdb-patches
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.
Michael
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: Daniel, thread vs. fork question. 2004-03-11 1:08 Daniel, thread vs. fork question Michael Snyder @ 2004-03-19 0:09 ` Daniel Jacobowitz 2004-03-11 1:51 ` Daniel Jacobowitz 2004-03-19 0:09 ` Michael Snyder 2004-03-19 0:09 ` Michael Snyder 2004-03-22 17:12 ` Daniel Jacobowitz 2 siblings, 2 replies; 11+ messages in thread From: Daniel Jacobowitz @ 2004-03-19 0:09 UTC (permalink / raw) To: Michael Snyder; +Cc: gdb-patches 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? Also, what glibc/nptl version are you using. 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. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Daniel, thread vs. fork question. 2004-03-19 0:09 ` Daniel Jacobowitz @ 2004-03-11 1:51 ` Daniel Jacobowitz 2004-03-19 0:09 ` Michael Snyder 1 sibling, 0 replies; 11+ messages in thread From: Daniel Jacobowitz @ 2004-03-11 1:51 UTC (permalink / raw) To: Michael Snyder; +Cc: gdb-patches 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? Also, what glibc/nptl version are you using. 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. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Daniel, thread vs. fork question. 2004-03-19 0:09 ` Daniel Jacobowitz 2004-03-11 1:51 ` Daniel Jacobowitz @ 2004-03-19 0:09 ` Michael Snyder 2004-03-11 2:22 ` Michael Snyder 2004-03-19 19:29 ` Michael Snyder 1 sibling, 2 replies; 11+ messages in thread From: Michael Snyder @ 2004-03-19 0:09 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 1560 bytes --] 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. [-- Attachment #2: pthreads.c --] [-- Type: text/plain, Size: 4410 bytes --] /* 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 <stdio.h> #include <pthread.h> /* 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); } ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Daniel, thread vs. fork question. 2004-03-19 0:09 ` Michael Snyder @ 2004-03-11 2:22 ` Michael Snyder 2004-03-19 19:29 ` Michael Snyder 1 sibling, 0 replies; 11+ messages in thread From: Michael Snyder @ 2004-03-11 2:22 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: gdb-patches [-- Attachment #1: Type: text/plain, Size: 1560 bytes --] 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. [-- Attachment #2: pthreads.c --] [-- Type: text/plain, Size: 4410 bytes --] /* 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 <stdio.h> #include <pthread.h> /* 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); } ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Daniel, thread vs. fork question. 2004-03-19 0:09 ` Michael Snyder 2004-03-11 2:22 ` Michael Snyder @ 2004-03-19 19:29 ` Michael Snyder 2004-03-19 19:39 ` Daniel Jacobowitz 1 sibling, 1 reply; 11+ messages in thread From: Michael Snyder @ 2004-03-19 19:29 UTC (permalink / raw) To: Michael Snyder; +Cc: Daniel Jacobowitz, gdb-patches 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 <stdio.h> > #include <pthread.h> > > /* 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); > } > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Daniel, thread vs. fork question. 2004-03-19 19:29 ` Michael Snyder @ 2004-03-19 19:39 ` Daniel Jacobowitz 0 siblings, 0 replies; 11+ messages in thread From: Daniel Jacobowitz @ 2004-03-19 19:39 UTC (permalink / raw) To: Michael Snyder; +Cc: gdb-patches On Fri, Mar 19, 2004 at 07:29:47PM +0000, Michael Snyder wrote: > 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. Sorry, I haven't - but I did see something similar from another source internally this week. Go figure. I'm traveling right now - will try to look at this Monday or Tuesday. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 11+ messages in thread
* Daniel, thread vs. fork question. 2004-03-11 1:08 Daniel, thread vs. fork question Michael Snyder 2004-03-19 0:09 ` Daniel Jacobowitz @ 2004-03-19 0:09 ` Michael Snyder 2004-03-22 17:12 ` Daniel Jacobowitz 2 siblings, 0 replies; 11+ messages in thread From: Michael Snyder @ 2004-03-19 0:09 UTC (permalink / raw) To: Daniel Jacobowitz, gdb-patches 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. Michael ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: Daniel, thread vs. fork question. 2004-03-11 1:08 Daniel, thread vs. fork question Michael Snyder 2004-03-19 0:09 ` Daniel Jacobowitz 2004-03-19 0:09 ` Michael Snyder @ 2004-03-22 17:12 ` Daniel Jacobowitz 2004-03-22 20:20 ` [patch] Fix threads vs. fork following Daniel Jacobowitz 2 siblings, 1 reply; 11+ messages in thread From: Daniel Jacobowitz @ 2004-03-22 17:12 UTC (permalink / raw) To: Michael Snyder; +Cc: gdb-patches 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. Actually, what happens is GDB tries to wait on pid 0. Here's why: errno = 0; ret = ptrace (PTRACE_GETEVENTMSG, pid, 0, &new_pid); printf ("getevent: ret %d, errno %d, new_pid %d\n", ret, errno, new_pid); getevent: ret 0, errno 0, new_pid 0 waiting for new child: No child processes. So PTRACE_GETEVENTMSG did not return the correct message. I can't see why it doesn't. My guess is that I overlooked something big in the kernel-side implementation but I'm going to have to go digging to figure out what it is. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 11+ messages in thread
* [patch] Fix threads vs. fork following 2004-03-22 17:12 ` Daniel Jacobowitz @ 2004-03-22 20:20 ` Daniel Jacobowitz 2004-03-23 20:17 ` Michael Snyder 0 siblings, 1 reply; 11+ messages in thread From: Daniel Jacobowitz @ 2004-03-22 20:20 UTC (permalink / raw) To: Michael Snyder, gdb-patches On Mon, Mar 22, 2004 at 12:12:18PM -0500, 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. Here's what happened: I was using ptid_get_pid, which gave me the _process_ ID rather than the _lwp_ ID. I've committed this fix for HEAD. Should I fix this on the 6.1 branch also? -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer 2004-03-22 Daniel Jacobowitz <drow@mvista.com> * lin-lwp.c (lin_lwp_wait): Pass the LWP ID to linux_handle_extended_wait. Index: lin-lwp.c =================================================================== RCS file: /cvs/src/src/gdb/lin-lwp.c,v retrieving revision 1.52 diff -u -p -r1.52 lin-lwp.c --- lin-lwp.c 8 Oct 2003 20:05:56 -0000 1.52 +++ lin-lwp.c 22 Mar 2004 20:02:30 -0000 @@ -1591,8 +1591,7 @@ retry: /* Handle GNU/Linux's extended waitstatus for trace events. */ if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0) { - linux_handle_extended_wait (ptid_get_pid (trap_ptid), - status, ourstatus); + linux_handle_extended_wait (GET_LWP (lp->ptid), status, ourstatus); return trap_ptid; } ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [patch] Fix threads vs. fork following 2004-03-22 20:20 ` [patch] Fix threads vs. fork following Daniel Jacobowitz @ 2004-03-23 20:17 ` Michael Snyder 0 siblings, 0 replies; 11+ messages in thread From: Michael Snyder @ 2004-03-23 20:17 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: gdb-patches Daniel Jacobowitz wrote: > On Mon, Mar 22, 2004 at 12:12:18PM -0500, 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. > > > Here's what happened: I was using ptid_get_pid, which gave me the > _process_ ID rather than the _lwp_ ID. I've committed this fix for > HEAD. Should I fix this on the 6.1 branch also? > I don't see why not. FYI, I've had feedback from one user who says this patch helped get him past the point at which he was stuck before -- but he's seeing a new problem which may or may not be related. He has one thread which calls system("/bin/ls"), and system ("cd <...>"). He can now get past at least the first few such calls under GDB, but eventually (and non-deterministically), he sees something like: Detaching after fork from child process 22087. ---Type <return> to continue, or q <return> to quit--- And then for some unknown percent of the times when the above occurs, it goes more like this: Detaching after fork from child process 21502. Suspended (tty output) [msnyder@reddwarf gdb]$ fg /export/msnyder/03r1-2/bin/gdb ... ---Type <return> to continue, or q <return> to quit--- Detaching after fork from child process 21510. Any thoughts? ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2004-03-23 20:17 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2004-03-11 1:08 Daniel, thread vs. fork question Michael Snyder 2004-03-19 0:09 ` Daniel Jacobowitz 2004-03-11 1:51 ` Daniel Jacobowitz 2004-03-19 0:09 ` Michael Snyder 2004-03-11 2:22 ` Michael Snyder 2004-03-19 19:29 ` Michael Snyder 2004-03-19 19:39 ` Daniel Jacobowitz 2004-03-19 0:09 ` Michael Snyder 2004-03-22 17:12 ` Daniel Jacobowitz 2004-03-22 20:20 ` [patch] Fix threads vs. fork following Daniel Jacobowitz 2004-03-23 20:17 ` Michael Snyder
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox