Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Michael Snyder <msnyder@redhat.com>
To: Michael Snyder <msnyder@redhat.com>
Cc: Daniel Jacobowitz <drow@mvista.com>, gdb-patches@sources.redhat.com
Subject: Re: Daniel, thread vs. fork question.
Date: Fri, 19 Mar 2004 19:29:00 -0000	[thread overview]
Message-ID: <405B4A2B.3050204@redhat.com> (raw)
In-Reply-To: <404FCD75.4080606@redhat.com>

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);
> }
> 



  parent reply	other threads:[~2004-03-19 19:29 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-03-11  1:08 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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=405B4A2B.3050204@redhat.com \
    --to=msnyder@redhat.com \
    --cc=drow@mvista.com \
    --cc=gdb-patches@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox