私が期間でtimed_waitをしている間にシステムの時間が変化した場合はどうなりますか?

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

質問

使用するとき timed_wait aで 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年11月)の時点で、ブースト条件変数を待っている間に壁2時間が変化した場合、単に悪い結果が得られます。

もし、あんたが しないでください Boostを使用する必要があります。「単調な時計」と呼ばれるものを使用できます。単調なクロックは壁2時間の時間の変化の影響を受けないため、説明した問題に対して脆弱ではありません。このようなものを使用して、PTHREADS APIを使用して5秒間安全に待つことができます。

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

他のヒント

非常にまれなものですが、私はそれが人種の状態だと思います。条件_variable :: timed_wait()の実装は、get_system_time()+wait_durationを使用して、値をSystem_timeに変換するだけです。時間get_system_time()が呼び出され、計算された待機終了時間が基礎となるOS呼び出しのためにティックベースのカウンターに再変換されると、システム時間が変化した場合、待機時間は間違っています。

このアイデアをテストするために、Windowsで、私はこのような100msごとに1つのスレッドが生成される1つのスレッドを使用して簡単なプログラムを書きました。

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

別のスレッドは、過去100ミリ秒ごとに1分間戻ってシステムを設定することでした(このスレッドは、システム時間への変換を避けるOSレベルの「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を提供しないようで、アプリはクロックの外部の変更に対して脆弱になります。

あなたのプロセスが信号も使用している場合、私はこれにいくつかの問題を見ました。また、期間のブースト条件変数も使用します。

POSIXタイマーを使用して20 Hzで正確なタイミングを取得するプロセスがあります。このタイマーがアクティブになり、時間が以前の日付/時刻に設定されている場合、条件変数ブロックがブロックされます。時間を元の値に変更すると、条件変数が続きます。

実装をBoostからClock_monotonicに設定し、設定しました。これで、時間が変更されても、条件変数は正しく機能します。

条件変数のモードを単調に設定する可能性があったら役に立ちましたが、現時点ではそれは不可能です。

問題は1.61開発ブランチに固定されました:

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top