pthread_cond_timedwait revenant immédiatement

J’ai un problème étrange. J’ai le code suivant:

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 appelle gettimeofday avant chaque ligne et la précède avec l’heure. Il en résulte le résultat suivant:

  7.991151: condwait: timeout = 5, 705032704 7.991158: cond timed out 

Comme vous pouvez le constater, seules 7 microsecondes ont été passées entre les deux lignes de débogage, mais pthread_cond_timedwait renvoyé ETIMEDOUT . Comment cela peut-il arriver? J’ai même essayé de régler l’horloge sur autre chose lors de l’initialisation de la variable cond:

 int ret; ret = pthread_condattr_init(&atsortingbutes); if (ret != 0) printf("CONDATTR INIT FAILED: %d\n", ret); ret = pthread_condattr_setclock(&atsortingbutes, CLOCK_REALTIME); if (ret != 0) printf("SETCLOCK FAILED: %d\n", ret); ret = pthread_cond_init( &q->q_cond, &atsortingbutes ); if (ret != 0) printf("COND INIT FAILED: %d\n", ret); 

(aucun des messages d’erreur n’est imprimé). J’ai essayé à la fois CLOCK_REALTIME et CLOCK_MONOTONIC .

Ce code fait partie d’une queue de blocage. J’ai besoin de fonctionnalités telles que si rien n’est mis dans cette queue dans 5 secondes, quelque chose d’autre se produit. Le mutex et le cond sont tous deux initialisés, car la queue de blocage fonctionne correctement si je n’utilise pas pthread_cond_timedwait .

pthread_cond_timedwait prend un temps absolu, pas un temps relatif. Vous devez rendre votre temps d’attente absolu en ajoutant à l’heure actuelle votre valeur de délai d’attente.

Le débordement de timespec est généralement à l’origine des délais étranges.
Vérifiez pour 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; } 

La variable de condition peut débloquer de façon intempestive. Vous devez vérifier en boucle et vérifier l’état à chaque fois. Vous devrez probablement également mettre à jour la valeur de délai d’attente.

J’ai trouvé de la documentation pour pthread_cond_timedwait ici .

Lors de l’utilisation de variables de condition, il existe toujours un prédicat booléen impliquant des variables partagées associées à chaque condition. La valeur true si le thread doit continuer. Des réveils parasites des fonctions pthread_cond_timedwait () ou pthread_cond_wait () peuvent se produire. Puisque le retour de pthread_cond_timedwait () ou de pthread_cond_wait () n’implique rien sur la valeur de ce prédicat, le prédicat doit être réévalué lors de ce retour.

Comme déjà mentionné dans d’autres réponses, vous devez utiliser le temps absolu. Depuis C11, vous pouvez utiliser timespec_get() .

 struct timespec time; timespec_get(&time, TIME_UTC); time.tv_sec += 5; pthread_cond_timedwait(&cond, &mutex, &time);