Рассмотрим следующий исходный код, который полностью совместим с POSIX:
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
int main (int argc, char ** argv) {
pthread_cond_t c;
pthread_mutex_t m;
char printTime[UCHAR_MAX];
pthread_mutex_init(&m, NULL);
pthread_cond_init(&c, NULL);
for (;;) {
struct tm * tm;
struct timeval tv;
struct timespec ts;
gettimeofday(&tv, NULL);
printf("sleep (%ld)\n", (long)tv.tv_sec);
sleep(3);
tm = gmtime(&tv.tv_sec);
strftime(printTime, UCHAR_MAX, "%Y-%m-%d %H:%M:%S", tm);
printf("%s (%ld)\n", printTime, (long)tv.tv_sec);
ts.tv_sec = tv.tv_sec + 5;
ts.tv_nsec = tv.tv_usec * 1000;
pthread_mutex_lock(&m);
pthread_cond_timedwait(&c, &m, &ts);
pthread_mutex_unlock(&m);
}
return 0;
}
Печатает текущую системную дату каждые 5 секунд, однако она выполняет спящий режим в течение 3 секунд между получением текущего системного времени (gettimeofday
) и ожиданием условия (pthread_cond_timedwait
).
Сразу после печати "sleep (...)" попробуйте установить системные часы на два дня в прошлое. Что происходит? Ну, вместо того, чтобы ждать еще 2 секунды при условии, что это обычно происходит, pthread_cond_timedwait
теперь ждет двух дней и 2 секунды.
Как это исправить?
Как я могу написать POSIX-совместимый код, который не прерывается, когда пользователь манипулирует системными часами?
Пожалуйста, имейте в виду, что системные часы могут меняться даже без взаимодействия с пользователем (например, клиент NTP может обновлять часы автоматически один раз в день). Установка часов в будущее не проблема, это приведет к тому, что сна рано проснется, что обычно не представляет проблемы, и которое вы можете легко "обнаружить" и обработать соответствующим образом, но установив часы в прошлое (например, потому что это было работающий в будущем, NTP обнаружил, что и исправил его) может вызвать большую проблему.
PS:
В моей системе не существует pthread_condattr_setclock()
и CLOCK_MONOTONIC
. Они обязательны для спецификации POSIX 2008 (часть "Base" ), но большинство систем по-прежнему соответствуют только спецификации POSIX 2004 на сегодняшний день и в спецификации POSIX 2004, эти два являются необязательными (расширенное расширение в реальном времени).