Что если системное время изменится, пока я выполняю timed_wait с продолжительностью? - PullRequest
8 голосов
/ 07 декабря 2010

При использовании timed_wait для boost::condition_variable с продолжительностью, истечет ли время ожидания по истечении указанного периода, даже если пользователь (или ntp) изменит системное время?

например.,

boost::posix_time::time_duration wait_duration(0, 0, 1, 0);  // 1 sec
// ** System time jumps back 15 minutes here. **
if( !signal.timed_wait(lock, wait_duration) )
{
    // Does this condition happen 1 second later, or about 15 minutes later?
}

Ответы [ 4 ]

8 голосов
/ 28 ноября 2013

На дату написания (ноябрь 2013 г.), если время настенных часов изменится во время ожидания переменной условия повышения, вы просто получите плохие результаты.

Если вам не нужно использовать усиление, вы можете использовать так называемые «монотонные часы». Поскольку на монотонные часы не влияют изменения времени на настенных часах, они не подвержены описанной вами проблеме. Вы можете спокойно ждать 5 секунд, используя API pthreads, используя что-то вроде этого:

pthread_condattr_t attr;
pthread_cond_t cond;
struct timespec ts;

pthread_condattr_init(&attr);
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
pthread_cond_init(&cond, &attr);
pthread_condattr_destroy(&attr);
clock_gettime(CLOCK_MONOTONIC, &ts);
ts.tv_sec += 5;
pthreead_cond_timedwait(&cond, &mutex, &ts);

Вы можете проверить реализацию boost :: condition_variable. Может быть, они исправят это когда-нибудь. Реализация здесь: http://svn.boost.org/svn/boost/trunk/boost/thread/pthread/condition_variable.hpp

2 голосов
/ 24 октября 2013

Я считаю, что это состояние гонки, хотя и очень редкое.Реализация condition_variable :: timed_wait () с длительностью просто преобразует значение в system_time, используя get_system_time () + wait_duration.Если системное время изменяется между временем вызова get_system_time () и вычисленное время окончания ожидания конвертируется в основанный на тиках счетчик для основного вызова ОС, ваше время ожидания будет неправильным.

Чтобы проверить этоПо идее, в Windows я написал простую программу с одним потоком, генерирующим некоторый вывод каждые 100 мс, например:

for (;;)
{
    boost::this_thread::sleep( boost::get_system_time() +
        boost::posix_time::milliseconds( 100 ) );
    std::cout << "Ping!" << std::endl;
}

Другой поток возвращал системное время на одну минуту в прошлом каждые 100 мс (этот поток используетвызов на уровне ОС «Sleep ()», который предотвращает преобразование в системное время):

for ( ;; )
{
    Sleep( 100 );
    SYSTEMTIME sysTime;
    GetSystemTime( &sysTime );
    FILETIME fileTime;
    SystemTimeToFileTime( &sysTime, /*out*/&fileTime );
    ULARGE_INTEGER fileTime64 = (ULARGE_INTEGER(fileTime.dwHighDateTime) << 32) |
        fileTime.dwLowDateTime;
    fileTime64 -= 10000000 * 60;   // one minute in the past
    fileTime.dwHighDateTime = (fileTime64>>32) & 0xFFFFFFFF;
    fileTime.dwLowDateTime = fileTime64 & 0xFFFFFFFF;
    FileTimeToSystemTime( &fileTime, /*out*/&sysTime );
    SetSystemTime( &sysTime );
}

Первый поток, хотя и должен выводить «Ping!»каждые 100 миллисекунд, довольно быстро блокируются.

Если только я чего-то не упустил, похоже, что Boost не предоставляет API-интерфейсы, позволяющие избежать этой проблемы внутренних преобразований в системное время, что делает приложения уязвимыми для внешних изменений вчасы.

1 голос
/ 01 августа 2016

исправлена ​​ошибка в ветке разработки 1.61:

https://svn.boost.org/trac/boost/ticket/6377

1 голос
/ 09 января 2012

Я видел некоторые проблемы с этим, если ваш процесс также использует сигналы.Я также использую переменные условия Boost с продолжительностью времени.

У нас есть процесс, который использует таймер POSIX для получения точного времени при 20 Гц.Когда этот таймер активирован, а время установлено на более раннюю дату / время, переменная условия блокируется.Когда я возвращаю время к исходному значению, переменная условия продолжается.

Я скопировал реализацию из Boost и установил режим часов CLOCK_MONOTONIC.Теперь переменная условия работает правильно, даже если время изменилось.

Было бы полезно, если бы была возможность установить режим переменной условия на монотонный, но это невозможно в данный момент.

...