再起動せずにうるう秒のスリープ問題を修正する方法

再起動せずにうるう秒のスリープ問題を修正する方法

最新のうるう秒の挿入 (2016-12-31 23:59:60) 後、ジョブ間で 1 秒間スリープするワーカー スレッドを持つ CentOS7 アプリケーションが、スリープ中のスレッドを 1 秒後ではなくすぐに起動し始めたことがわかりました。一般に、すべてのスリープは、予想される起動時間より 1 秒早く起動します。

最も簡単で有効な解決策は、ボックスを再起動することです。しかし、私たちのケースではそれは望ましくありません。再起動せずにこれを修正する方法はありますか?

PS. 参考までに、問題を再現する C++ の簡単なプログラムを以下に示します。

#include <boost/date_time.hpp>
#include <boost/thread.hpp>
#include <iostream>

using namespace std;


// this has to be run in a thread to be able to detect the issue
void check_thread()
{
    size_t expected_delay = 1000;
    cout << "Expected delay: " << expected_delay << " ms" << endl;
    boost::posix_time::ptime t1 = boost::posix_time::microsec_clock::universal_time();
    boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
    boost::posix_time::ptime t2 = boost::posix_time::microsec_clock::universal_time();
    size_t actual_delay = (t2 - t1).total_milliseconds();
    cout << "Actual delay: " << actual_delay << " ms" << endl;
    if (abs(expected_delay - actual_delay) > 900) {
        cout << "Too big delay difference: " << (expected_delay - actual_delay) << endl;
        cout << "Possible leap second issue" << endl;
    }
    else {
        cout << "No issues found" << endl;
    }
}

int main()
{
    boost::thread_group g;
    g.create_thread(check_thread);
    g.join_all();
    return 0;
}

建物:

g++ sleep_test.cpp -Wl,-Bstatic -lboost_thread -lboost_system -lboost_date_time -Wl,-Bdynamic -rdynamic -pthread

答え1

システム時間はntpdまたは と同期されていますかptp? そうでない場合は、tzdataパッケージを更新してください。

ntpd または ptp によって同期されていないシステムでは、12 月 31 日のうるう秒を含む更新された tzdata パッケージが必要です。更新された tzdata パッケージは RHEA-2016-1982 の一部としてリリースされており、ntpd または ptp によって同期されていない RHEL 7 を使用しているすべてのシステムは、この修正を受け取るために tzdata-2016g-2.el7 またはそれ以降のバージョンに更新する必要があります。

Red Hat Enterprise Linux におけるうるう秒の問題を解決する

答え2

Troy 氏の発言に加えて、うるう秒が適用された時点で tzdata を更新しておらず、ntpd を実行していない RHEL7 システムでは、手動で時間を 1 秒進めて、元に戻すという追加の手順が必要です。

date -s "+1 sec"
date -s "-1 sec"

関連情報