Что, если системное время изменится, пока я выполняю timed_wait с длительностью?

StackOverflow https://stackoverflow.com/questions/4381095

Вопрос

При использовании 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?
}
Это было полезно?

Решение

На дату написания (ноябрь 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

Другие советы

Я считаю, что это состояние гонки, хотя очень редкое. Реализация Condition_Variable :: Timeed_Wait () с продолжительностью просто преобразует значение в систему_а с использованием 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 миллисекунд, запертые довольно быстро.

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top