8

期間のあるで使用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

4 に答える 4

8

執筆日(2013年11月)の時点で、ブースト条件変数を待っている間に実時間が変更されると、単に悪い結果が得られます。

ブーストを使用する必要がない場合は、いわゆる「単調時計」を使用できます。単調時計は実時間の変更の影響を受けないため、説明した問題に対して脆弱ではありません。次のようなものを使用してpthreadsAPIを使用すると、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

于 2013-11-27T23:42:02.047 に答える
2

非常にまれな条件ですが、競合状態だと思います。期間を指定したcondition_variable::timed_wait()の実装は、get_system_time()+wait_durationを使用して値をsystem_timeに変換するだけです。get_system_time()が呼び出されてからシステム時間が変更され、計算された待機終了時間が基になるOS呼び出しのティックベースのカウンターに再変換される場合、待機時間は間違っています。

このアイデアをテストするために、Windowsで、次のように1つのスレッドで100ミリ秒ごとに出力を生成する単純なプログラムを作成しました。

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を提供していないようで、アプリは時計の外部変更に対して脆弱なままです。

于 2013-10-24T19:10:34.720 に答える
1

プロセスでもシグナルを使用している場合、これにはいくつかの問題があります。また、期間時間のあるBoost条件変数も使用します。

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

Boostから実装をコピーし、クロックモードをCLOCK_MONOTONICに設定しました。これで、時刻が変更されても条件変数が正しく機能するようになりました。

条件変数の最頻値を単調に設定する可能性があれば役に立ちましたが、現時点ではそれは不可能です。

于 2012-01-09T14:26:01.743 に答える
1

この問題は1.61開発ブランチで修正されました:

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

于 2016-08-01T09:34:16.663 に答える