Subject: lib/25961: pthread_cond_timedwait() before creating other threads
To: None <gnats-bugs@gnats.NetBSD.org>
From: J.T. Conklin <jtc@acorntoolworks.com>
List: netbsd-bugs
Date: 06/18/2004 04:23:44
>Number: 25961
>Category: lib
>Synopsis: pthread_cond_timedwait() before creating other threads
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jun 18 04:25:01 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator: J.T. Conklin
>Release: NetBSD 2.0_BETA
>Organization:
J.T. Conklin
>Environment:
System: NetBSD orac 2.0_BETA NetBSD 2.0_BETA (GENERIC.MP) #0: Fri May 7 20:39:51 PDT 2004 jtc@orac:/home/jtc/netbsd/NetBSD-2.0/obj/sys/arch/i386/compile/GENERIC.MP i386
Architecture: i386
Machine: i386
>Description:
"Message_Queue_Test" from the ACE (ADAPTIVE Communication Environment)
regression test suite fails because pthread_cond_timedwait() is called
before additional threads have been created.
pthread_cond_timedwait() is called with a timespec representing "now",
the current time, as a timeout. This timespec represents the absolute
timeout, and is converted to a timeval representing a relative timeout
in pthread_cond_wait_nothread().
If the absolute timeout has already been reached, this can result in a
negative value that is passed to select(). This causes select to fail
returning -1, which causes pthread_cond_wait_nothread to return 0
instead of ETIMEDOUT.
>How-To-Repeat:
This program demonstrates the problem. pthread_cond_timedwait()
returns different values depending on whether the pthread_create line
is enabled/commented out.
#include <pthread.h>
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
pthread_mutex_t m;
pthread_cond_t c;
pthread_t t;
void *
thr(void *arg)
{
sleep(5);
}
main()
{
struct timeval tv;
struct timespec ts;
int err;
gettimeofday(&tv, 0);
TIMEVAL_TO_TIMESPEC(&tv, &ts);
sleep(1); // ensure absolute timeout is in the "past"
#if 0
pthread_create(&t, 0, thr, 0);
#endif
pthread_mutex_init(&m, 0);
pthread_cond_init(&c, 0);
pthread_mutex_lock(&m);
err = pthread_cond_timedwait(&c, &m, &ts);
printf("%d: %s\n", err, strerror(err));
pthread_mutex_unlock(&m);
exit (0);
}
>Fix:
If the absolute timeout is in the past, clear the timeval that is
passed to select().
Index: pthread_cond.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread_cond.c,v
retrieving revision 1.14.2.1
diff -c -r1.14.2.1 pthread_cond.c
*** pthread_cond.c 6 May 2004 05:34:18 -0000 1.14.2.1
--- pthread_cond.c 18 Jun 2004 03:54:05 -0000
***************
*** 374,380 ****
tvp = &tv;
gettimeofday(&now, NULL);
TIMESPEC_TO_TIMEVAL(tvp, abstime);
! timersub(tvp, &now, tvp);
}
/*
--- 374,385 ----
tvp = &tv;
gettimeofday(&now, NULL);
TIMESPEC_TO_TIMEVAL(tvp, abstime);
!
! if (timercmp(tvp, &now, <)) {
! timerclear(tvp);
! } else {
! timersub(tvp, &now, tvp);
! }
}
/*
>Release-Note:
>Audit-Trail:
>Unformatted: