This is the mail archive of the gdb@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[greg@surety.com] libc/1320: pthread_cond_timedwait returns EINTR in multithreaded processes when gdb is attached to them



Hi,

the following bug report has been send to glibc and describes a
problem in the interaction of glibc and gdb.

I can reproduce the problem with HJ Lu's gdb 4.17.0.12 and with gdb
19990913 from CVS.

Andreas



Topics:
   libc/1320: pthread_cond_timedwait returns EINTR in multithreaded processes when gdb is attached to them


----------------------------------------------------------------------

Date: Thu, 23 Sep 1999 11:54:10 -0400
From: greg@surety.com
To: bugs@gnu.org
Subject: libc/1320: pthread_cond_timedwait returns EINTR in multithreaded processes when gdb is attached to them
Message-Id: <199909231554.LAA20017@delysid.gnu.org>


>Number:         1320
>Category:       libc
>Synopsis:       pthread_cond_timedwait returns EINTR in multithreaded processes when gdb is attached to them
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    libc-gnats
>State:          open
>Class:          sw-bug
>Submitter-Id:   unknown
>Arrival-Date:   Thu Sep 23 12:00:03 EDT 1999
>Last-Modified:
>Originator:     greg@surety.com
>Organization:
net
>Release:        2.1.1
>Environment:
glibc-2.1.1-6 and gdb-4.17.0.11-6 as shipped with redhat 6.0
>Description:
this silly little test program demonstrates a bug in the interaction between
GNU gdb 4.17.0.11 with Linux support as shipped with Red Hat Linux 6.0 and
LinuxThreads-0.8 as built into glibc 2.1.1-6 as shipped with Red Hat Linux
6.0.  when this test program is run outside of the debugger, it performs
as expected.  when it is run from within gdb (even with no breakpoints set),
the call to pthread_cond_timedwait returns immediately with EINTR.  this
seems to be a result of nanosleep(2) returning as the result of a
non-blocked signal being sent to the thread.  from nanosleep(2):

      EINTR   The  pause  has  been interrupted by a non-blocked
              signal that was  delivered  to  the  process.  The
              remaining sleep time has been written into *rem so
              that the process can easily call  nanosleep  again
              and continue with the pause.

i could throw out a guess that linuxthreads and gdb talk to each other using
signals, and this is causing nanosleep to return.  this, however, is just a
guess.

#!/bin/sh
# This is a shell archive (produced by GNU sharutils 4.2).
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
# Made on 1999-09-23 11:34 EDT by <greg@surety.com>.
# Source directory was `/home/greg/testcond'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
# This shar contains:
# length mode       name
# ------ ---------- ------------------------------------------
#    198 -rw-r--r-- Makefile
#   3019 -rw-r--r-- testcond.c
#
save_IFS="${IFS}"
IFS="${IFS}:"
gettext_dir=FAILED
locale_dir=FAILED
first_param="$1"
for dir in $PATH
do
  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
     && ($dir/gettext --version >/dev/null 2>&1)
  then
    set `$dir/gettext --version 2>&1`
    if test "$3" = GNU
    then
      gettext_dir=$dir
    fi
  fi
  if test "$locale_dir" = FAILED && test -f $dir/shar \
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
  then
    locale_dir=`$dir/shar --print-text-domain-dir`
  fi
done
IFS="$save_IFS"
if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
then
  echo=echo
else
  TEXTDOMAINDIR=$locale_dir
  export TEXTDOMAINDIR
  TEXTDOMAIN=sharutils
  export TEXTDOMAIN
  echo="$gettext_dir/gettext -s"
fi
touch -am 1231235999 $$.touch >/dev/null 2>&1
if test ! -f 1231235999 && test -f $$.touch; then
  shar_touch=touch
else
  shar_touch=:
  echo
  $echo 'WARNING: not restoring timestamps.  Consider getting and'
  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
  echo
fi
rm -f 1231235999 $$.touch
#
if mkdir _sh22314; then
  $echo 'x -' 'creating lock directory'
else
  $echo 'failed to create lock directory'
  exit 1
fi
# ============= Makefile ==============
if test -f 'Makefile' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'Makefile' '(file already exists)'
else
  $echo 'x -' extracting 'Makefile' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
# Makefile for testcond
X
CC = gcc
CFLAGS = -Wall -ggdb 
CPPFLAGS = -D_REENTRANT
X
X.PHONY : all clean
X
all : testcond
X
clean :
X	rm testcond.o testcond
X
testcond : testcond.o
X	$(CC) $^ -o $@ -lpthread
SHAR_EOF
  $shar_touch -am 0923113299 'Makefile' &&
  chmod 0644 'Makefile' ||
  $echo 'restore of' 'Makefile' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'Makefile:' 'MD5 check failed'
44277dee9de52b323807a8f210f5f8eb  Makefile
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'Makefile'`"
    test 198 -eq "$shar_count" ||
    $echo 'Makefile:' 'original size' '198,' 'current size' "$shar_count!"
  fi
fi
# ============= testcond.c ==============
if test -f 'testcond.c' && test "$first_param" != -c; then
  $echo 'x -' SKIPPING 'testcond.c' '(file already exists)'
else
  $echo 'x -' extracting 'testcond.c' '(text)'
  sed 's/^X//' << 'SHAR_EOF' > 'testcond.c' &&
/*
X * testcond.c
X *
X * this silly little test program demonstrates a bug in the interaction between
X * GNU gdb 4.17.0.11 with Linux support as shipped with Red Hat Linux 6.0 and
X * LinuxThreads-0.8 as built into glibc 2.1.1-6 as shipped with Red Hat Linux
X * 6.0.  when this test program is run outside of the debugger, it performs
X * as expected.  when it is run from within gdb (even with no breakpoints set),
X * the call to pthread_cond_timedwait returns immediately with EINTR.  this
X * seems to be a result of nanosleep(2) returning as the result of a
X * non-blocked signal being sent to the thread.  from nanosleep(2):
X *
X *       EINTR   The  pause  has  been interrupted by a non-blocked
X *               signal that was  delivered  to  the  process.  The
X *               remaining sleep time has been written into *rem so
X *               that the process can easily call  nanosleep  again
X *               and continue with the pause.
X *
X * i could throw out a guess that linuxthreads and gdb talk to each other using
X * signals, and this is causing nanosleep to return.  this, however, is just a
X * guess.
X *
X * greg thompson <greg@surety.com>
X * 1999-09-22
X */
X
#include <stdio.h>
#include <sys/time.h>
#include <pthread.h>
#include <semaphore.h>
#include <errno.h>
X
#define DUMMIES 1
X
X
static void *dummyMain(
X    void			*arg
X    )
{
X    sem_wait((sem_t *) arg);
X
X    return NULL;
}
X
X
int main(
X    int				 argc,
X    char			*argv[]
X    )
{
X    struct timeval		 v1, v2;
X    struct timespec		 t;
X    sem_t			 sem;
X    pthread_t			 threads[DUMMIES];
X    int				 i;
X    pthread_mutex_t		 m;
X    pthread_cond_t		 c;
X    int				 e;
X
X    /*
X     * first, create a semaphore for the dummy threads, then spawn off the
X     * dummies
X     */
X
X    sem_init(&sem, 0, 0);
X
X    for (i = 0; i < DUMMIES; ++i)
X	pthread_create(&threads[i], NULL, dummyMain, &sem);
X
X    /*
X     * next, setup a mutex and a condition variable and sleep for five seconds
X     * by waiting on the condition variable.
X     */
X
X    pthread_mutex_init(&m, NULL);
X
X    pthread_cond_init(&c, NULL);
X
X    pthread_mutex_lock(&m);
X
X    gettimeofday(&v1, NULL);
X
X    TIMEVAL_TO_TIMESPEC(&v1, &t);
X
X    t.tv_sec += 5;
X
X    e = pthread_cond_timedwait(&c, &m, &t);
X
X    /*
X     * display the amount of time that has past since we went to sleep
X     */
X
X    gettimeofday(&v2, NULL);
X
X    printf("%s : slept for %ld.%ld seconds\n",
X	   (e == ETIMEDOUT ? "cv timed out" :
X	    (e == 0 ? "cv signalled" :
X	     (e == EINTR ? "thread interrupted" : "unknown reason"))),
X	   v2.tv_sec - v1.tv_sec, v2.tv_usec - v1.tv_usec);
X
X    /*
X     * cleanup the mutex and condition variable
X     */
X
X    pthread_mutex_unlock(&m);
X
X    pthread_cond_destroy(&c);
X
X    pthread_mutex_destroy(&m);
X
X    /*
X     * bring the dummy threads back in and cleanup the semaphore
X     */
X
X    for (i = 0; i < DUMMIES; ++i)
X	sem_post(&sem);
X
X    for (i = DUMMIES - 1; i >= 0; --i)
X	pthread_join(threads[i], NULL);
X
X    sem_destroy(&sem);
X
X    /*
X     * get out.
X     */
X
X    return 0;
}
SHAR_EOF
  $shar_touch -am 0923113099 'testcond.c' &&
  chmod 0644 'testcond.c' ||
  $echo 'restore of' 'testcond.c' 'failed'
  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
    || $echo 'testcond.c:' 'MD5 check failed'
f7f249f4cf281eef2a4d4522775ed7f8  testcond.c
SHAR_EOF
  else
    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'testcond.c'`"
    test 3019 -eq "$shar_count" ||
    $echo 'testcond.c:' 'original size' '3019,' 'current size' "$shar_count!"
  fi
fi
rm -fr _sh22314
exit 0
>How-To-Repeat:

>Fix:
>Audit-Trail:
>Unformatted:



------------------------------

End of forward9EAWck Digest
***************************



-- 
 Andreas Jaeger   aj@suse.de	aj@arthur.rhein-neckar.de
  for pgp-key finger ajaeger@aixd1.rhrk.uni-kl.de

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]