Pregunta

Cuando se utiliza en un timed_wait boost::condition_variable con una duración, lo hará el tiempo condición de espera después de la duración, incluso si el usuario (o NTP) cambia la hora del sistema?

por ejemplo.,

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?
}
¿Fue útil?

Solución

A partir de la fecha de la escritura (noviembre de 2013), si los cambios de hora del reloj de pared mientras espera una condición variable impulso, sólo tiene que obtendrán malos resultados.

Si no tiene que impulsar el uso, puede utilizar lo que se llama el "reloj monótona." Desde el reloj monótona no se ve afectada por los cambios de hora del reloj de pared, no es vulnerable al problema que usted describió. Puede esperar 5 segundos de forma segura utilizando la API pthreads usar algo como esto:

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);

Se puede comprobar la aplicación de impulso :: condition_variable. Tal vez van a arreglar esto algún día. La aplicación está aquí: http: //svn.boost. org / sVN / impulso / trunk / impulso / hilo / pthread / condition_variable.hpp

Otros consejos

I believe it is a race condition, although a very rare one. The implementation of condition_variable::timed_wait() with a duration simply converts the value to a system_time using get_system_time()+wait_duration. If the system time changes between the time get_system_time() is called, and the calculated wait end time is reconverted to a tick-based counter for the underlying OS call, your wait time will be wrong.

To test this idea, on Windows, I wrote a simple program with one thread generating some output every 100ms, like this:

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

Another thread was setting the system time back one minute in the past every 100ms (this thread uses the OS-level "Sleep()" call which avoids conversions to system time):

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 );
}

The first thread, though supposed to output "Ping!" every 100 milliseconds, locked up rather quickly.

Unless I'm missing something, it seems Boost doesn't provide any APIs that avoid this problem of internal conversions to system time, leaving apps vulnerable to outside changes to the clock.

I did see some problems with this, if your process also uses signals. I also use the Boost condition variables with a duration time.

We have a process that uses a POSIX timer to get accurate timing at 20 Hz. When this timer is activated and the time is set to an earlier date/time the condition variable blocks. When I change the time back to the original value the condition variable continues.

I copied the implementation from Boost and set the clock mode to CLOCK_MONOTONIC. Now the condition variable works correctly even if the time is changed.

It would have been helpful if there would have been a possibility to set the mode of a condition variable to monotonic, but that is not possible at this moment.

issue was fixed at 1.61 develop branch:

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top