- Subject: libc/1320: pthread_cond_timedwait returns EINTR in multithreaded processes when gdb is attached to them
- From: greg at surety dot com
- Date: Fri Sep 24 13:59:33 1999
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
***************************