Pthread_cond_timedwait returns immediately
I have 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 calls gettimeofday before each line and adds a line with time. This leads to the following result:
7.991151: condwait: timeout = 5, 705032704 7.991158: cond timed out As you can see, only 7 microseconds passed through two lines of debugging, but pthread_cond_timedwait returned ETIMEDOUT . How can this happen? I even tried to set the clock to something else while 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). I tried both CLOCK_REALTIME and CLOCK_MONOTONIC .
This code is part of the lock queue. I need such functionality that if nothing is delivered in this queue after 5 seconds, something else will happen. The mutex and cond are initialized, since the blocking queue works fine if I do not use pthread_cond_timedwait .
pthread_cond_timedwait accepts absolute time, not relative time. You must make your wait time absolute by adding the current time to your timeout value.
timespec overflow is usually the culprit of weird timeouts.
Check out 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; } The condition variable may falsely unlock. You need to check this in a loop and check the condition every time. You probably also need to update the timeout value.
I found the documentation for pthread_cond_timedwait here .
When using variables, the condition is always a Boolean predicate involving related variables with a wait condition, which is true if the flow should continue. fake wakeups from pthread_cond_timedwait () or pthread_cond_wait () functions may occur. Since returning from pthread_cond_timedwait () or pthread_cond_wait () does not mean anything about the value of this predicate, the predicate must be reevaluated with such a return.
As mentioned in the other answers mentioned, you should use absolute time. With C11 you can use timespec_get() .
struct timespec time; timespec_get(&time, TIME_UTC); time.tv_sec += 5; pthread_cond_timedwait(&cond, &mutex, &time);