Augmenter le problème de secondes intercalaires timed_wait

J’utilise timed_wait de la bibliothèque boost C ++ et j’obtiens un problème de secondes intercalaires.

Voici un test rapide:

#include  #include  #include  int main(){ // Determine the absolute time for this timer. boost::system_time tAbsoluteTime = boost::get_system_time() + boost::posix_time::milliseconds(35000); bool done; boost::mutex m; boost::condition_variable cond; boost::unique_lock lk(m); while(!done) { if(!cond.timed_wait(lk,tAbsoluteTime)) { done = true; std::cout << "timed out"; } } return 1; } 

La fonction timed_wait renvoie 24 secondes plus tôt que prévu. 24 secondes correspond au nombre actuel de secondes bissextiles en UTC.

Donc, boost est largement utilisé mais je n’ai trouvé aucune information sur ce problème particulier. Quelqu’un d’autre a-t-il rencontré ce problème? Quelles sont les causes possibles et les solutions?

Notes: J’utilise boost 1.38 sur un système Linux. J’ai entendu dire que ce problème ne se produit pas sous MacOS.

UPDATE: Un peu plus d’infos: Cela se passe sur 2 machines redhat avec le kernel 2.6.9. J’ai exécuté le même code sur une machine Ubuntu avec le kernel 2.6.30 et le minuteur se comporte comme prévu.

Donc, je pense que cela est probablement causé par le système d’exploitation ou par une configuration mal définie sur les machines redhat.

J’ai codé une solution de contournement qui ajuste l’heure en UTC et qui obtient la différence par rapport à cet ajustement et l’ajoute à l’heure d’origine. Cela me semble une mauvaise idée, car si ce code est exécuté sur une machine ne présentant pas ce problème, il se peut que ce soit 24 AHEAD. Je ne pouvais toujours pas trouver la raison de cela.

Sur un système Linux, l’horloge système suivra la norme POSIX, qui impose de ne PAS observer les secondes intercalaires! Si vous vous attendiez au contraire, c’est probablement la source de la divergence que vous constatez. Ce document explique en grande partie le lien qui existe entre UTC et d’autres échelles de temps, ainsi que les problèmes que l’on est susceptible de rencontrer si l’on s’appuie sur le concept de chronométrage du système d’exploitation.

Est-il possible que cela soit réglé prématurément et qu’un réveil parasite provoque la sortie de la boucle plus tôt que prévu?

Ok, voici ce que j’ai fait. C’est une solution de contournement et je n’en suis pas content mais c’était le meilleur que j’ai pu trouver:

 int main(){ typedef boost::date_time::c_local_adjustor local_adj; // Determine the absolute time for this timer. boost::system_time tAbsoluteTime = boost::get_system_time() + boost::posix_time::milliseconds(25000); /* * A leap second is a positive or negative one-second adjustment to the Coordinated * Universal Time (UTC) time scale that keeps it close to mean solar time. * UTC, which is used as the basis for official time-of-day radio broadcasts for civil time, * is maintained using extremely precise atomic clocks. To keep the UTC time scale close to * mean solar time, UTC is occasionally corrected by an adjustment, or "leap", * of one second. */ boost::system_time tAbsoluteTimeUtc = local_adj::utc_to_local(tAbsoluteTime); // Calculate the local-to-utc difference. boost::posix_time::time_duration tLocalUtcDiff = tAbsoluteTime - tAbsoluteTimeUtc; // Get only the seconds from the difference. These are the leap seconds. tAbsoluteTime += boost::posix_time::seconds(tLocalUtcDiff.seconds()); bool done; boost::mutex m; boost::condition_variable cond; boost::unique_lock lk(m); while(!done) { if(!cond.timed_wait(lk,tAbsoluteTime)) { done = true; std::cout << "timed out"; } } return 1; } 

Je l'ai testé sur des machines problématiques et non problématiques et cela a fonctionné comme prévu sur les deux, je le garde donc tant que je ne peux pas trouver une meilleure solution.

Merci à tous pour votre aide.