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