pthread_cond_timedwait returning immediately
Solution 1
pthread_cond_timedwait takes an absolute time, not a relative time. You need to make your wait time absolute by adding to the current time to your timeout value.
Solution 2
Overflow in timespec
is usually the culprit for weird timeouts.
Check for EINVAL:
void timespec_add(struct timespec* a, struct timespec* b, struct timespec* out)
{
time_t sec = a->tv_sec + b->tv_sec;
long nsec = a->tv_nsec + b->tv_nsec;
sec += nsec / 1000000000L;
nsec = nsec % 1000000000L;
out->tv_sec = sec;
out->tv_nsec = nsec;
}
Solution 3
The condition variable can spuriously unblock. You need to check it in a loop and check the condition each time through. You'll probably need to update the timeout value too.
I found some documentation for pthread_cond_timedwait
here.
When using condition variables there is always a Boolean predicate involving shared variables associated with each condition wait that is true if the thread should proceed. Spurious wakeups from the pthread_cond_timedwait() or pthread_cond_wait() functions may occur. Since the return from pthread_cond_timedwait() or pthread_cond_wait() does not imply anything about the value of this predicate, the predicate should be re-evaluated upon such return.
Solution 4
As already in other answers mentioned you have to use the absolute time. Since C11 you can use timespec_get()
.
struct timespec time;
timespec_get(&time, TIME_UTC);
time.tv_sec += 5;
pthread_cond_timedwait(&cond, &mutex, &time);
Claudiu
Graduated from Brown University. E-mail: [email protected]
Updated on July 22, 2022Comments
-
Claudiu almost 2 years
I'm having a strange problem. I have the following code:
dbg("condwait: timeout = %d, %d\n", abs_timeout->tv_sec, abs_timeout->tv_nsec); ret = pthread_cond_timedwait( &q->q_cond, &q->q_mtx, abs_timeout ); if (ret == ETIMEDOUT) { dbg("cond timed out\n"); return -ETIMEDOUT; }
dbg
callsgettimeofday
before every line and prepends the line with the time. It results in the following output:7.991151: condwait: timeout = 5, 705032704 7.991158: cond timed out
As you can see, only 7 microseconds passed in between the two debug lines, yet
pthread_cond_timedwait
returnedETIMEDOUT
. How can this happen? I even tried setting the clock to something else when initializing the cond variable:int ret; ret = pthread_condattr_init(&attributes); if (ret != 0) printf("CONDATTR INIT FAILED: %d\n", ret); ret = pthread_condattr_setclock(&attributes, CLOCK_REALTIME); if (ret != 0) printf("SETCLOCK FAILED: %d\n", ret); ret = pthread_cond_init( &q->q_cond, &attributes ); if (ret != 0) printf("COND INIT FAILED: %d\n", ret);
(none of the error messages are printed out). I tried both
CLOCK_REALTIME
andCLOCK_MONOTONIC
.This code is part of a blocking queue. I need functionality such that if nothing gets put on this queue in 5 seconds, something else happens. The mutex and the cond are both initialized, as the blocking queue works fine if I don't use
pthread_cond_timedwait
. -
Claudiu about 15 yearsOh got it. You can use pthread_get_expiration_np() to figure out what the abs time is.
-
cato_minor over 11 years@Claudiu pthread_get_expiration_np() is not available on my GNU/Linux. Instead I had to:
timeval now; gettimeofday(&now, NULL); long int abstime_ns_large = now.tv_usec*1000 + delay_ns; timespec abstime = { now.tv_sec + (abstime_ns_large / 1000000000), abstime_ns_large % 1000000000 };
where delay_ns is the desired delay in nanoseconds. Then use abstime in your pthread_cond_timedwait call.