Subject: lib/28700: pthread_cond_timedwait() hang with "zero" absolute time
To: None <lib-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: J.T. Conklin <jtc@acorntoolworks.com>
List: netbsd-bugs
Date: 12/18/2004 06:42:00
>Number: 28700
>Category: lib
>Synopsis: pthread_cond_timedwait() hang with "zero" absolute time
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Dec 18 06:42:00 +0000 2004
>Originator: J.T. Conklin
>Release: NetBSD 2.0_RC5
>Organization:
>Environment:
System: NetBSD orac 2.0_RC5 NetBSD 2.0_RC5 (ORAC) #0: Sat Dec 11 15:17:07 PST 2004 jtc@orac:/home/jtc/netbsd/NetBSD-2.0/src/sys/arch/i386/compile/ORAC i386
Architecture: i386
Machine: i386
>Description:
The next ACE/TAO release is due out soon, so I've been making another
pass making sure it will run well on NetBSD. This evening, I've been
investigating why the TP_Reactor_Test hangs.
I discovered that this was caused by a "zero" ACE_Time_Value being
used as a timeout in a message queue getq() call. The intent of this
is to return a message block if one is present, otherwise to time out
immediately. Tracking this through the ACE C++ facades, I found that
this resulted in pthread_cond_timedwait() being called with a zero
absolute timeout (tv_sec = 0, tv_nsec = 0). Other values before "now"
correctly return ETIMEDOUT -- only "zero" fails.
The test program I've enclosed below demostrates the problem.
>How-To-Repeat:
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <time.h>
void *threadfunc(void *arg);
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t c = PTHREAD_COND_INITIALIZER;
int
main()
{
pthread_t new;
struct timespec ts;
int retval;
retval = pthread_mutex_lock(&m);
assert (retval == 0);
retval = pthread_create(&new, NULL, threadfunc, NULL);
assert (retval == 0);
#if 0
// set timeout one second in the future
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 1;
#else
// set zero timeout
ts.tv_sec = 0;
ts.tv_nsec = 0;
#endif
retval = pthread_cond_timedwait(&c, &m, &ts);
printf("%d\n", retval);
retval = pthread_mutex_unlock(&m);
assert (retval == 0);
retval = pthread_join(new, NULL);
assert (retval == 0);
}
void *
threadfunc(void *arg)
{
pthread_mutex_lock(&m);
// wait a few seconds to make sure the main thread waits on
// the condvar.
sleep (5);
pthread_cond_signal(&c);
pthread_mutex_unlock(&m);
return NULL;
}
>Fix:
>Unformatted: