Ini disebabkan oleh livelock ketika ntpd memanggil adjtimex (2) untuk memberitahu kernel untuk memasukkan leap second. Lihat lkml memposting http://lkml.indiana.edu/hypermail/linux/kernel/1203.1/04598.html
Red Hat juga harus memperbarui artikel KB mereka. https://access.redhat.com/knowledge/articles/15145
UPDATE: Red Hat memiliki artikel KB kedua hanya untuk masalah ini di sini: https://access.redhat.com/knowledge/solutions/154713 - artikel sebelumnya adalah untuk masalah sebelumnya yang tidak terkait
Cara mengatasinya adalah dengan mematikan ntpd. Jika ntpd sudah mengeluarkan panggilan adjtimex (2), Anda mungkin perlu menonaktifkan ntpd dan reboot agar 100% aman.
Ini mempengaruhi RHEL 6 dan distro lain yang menjalankan kernel yang lebih baru (lebih baru dari kira-kira 2.6.26), tetapi tidak RHEL 5.
Alasan ini terjadi sebelum lompatan kedua sebenarnya dijadwalkan terjadi adalah bahwa ntpd memungkinkan kernel menangani lompatan kedua di tengah malam, tetapi perlu mengingatkan kernel untuk memasukkan lompatan kedua sebelum tengah malam. Oleh karena itu ntpd memanggil adjtimex (2) sekitar hari kabisat detik, saat bug ini dipicu.
Jika Anda telah memasang adjtimex (8), Anda dapat menggunakan skrip ini untuk menentukan apakah flag 16 diatur. Bendera 16 adalah "menyisipkan lompatan kedua":
adjtimex -p | perl -p -e 'undef $_, next unless m/status: (\d+)/; (16 & $1) && print "leap second flag is set:\n"'
MEMPERBARUI:
Red Hat telah memperbarui artikel KB mereka untuk mencatat: "Pelanggan RHEL 6 mungkin terpengaruh oleh masalah yang diketahui yang menyebabkan NMI Watchdog mendeteksi hang ketika menerima pengumuman NTP leapsecond. Masalah ini sedang ditangani tepat waktu. Jika sistem Anda menerima Pengumuman leapsecond dan tidak mengalami masalah ini, maka mereka tidak lagi terpengaruh. "
UPDATE: Bahasa di atas telah dihapus dari artikel Red Hat; dan solusi KB kedua ditambahkan dengan merinci masalah kecelakaan adjtimex (2): https://access.redhat.com/knowledge/solutions/154713
Namun, perubahan kode pada pos LKML oleh Insinyur IBM John Stultz mencatat mungkin juga ada jalan buntu ketika lompatan kedua benar-benar diterapkan, jadi Anda mungkin ingin menonaktifkan lompatan kedua dengan me-reboot atau menggunakan adjtimex (8) setelah menonaktifkan ntpd.
PEMBARUAN AKHIR:
Yah, saya bukan kernel dev, tapi saya meninjau patch John Stultz lagi di sini: https://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h = 6b43ae8a619d17c4935c3320d2ef9e92bdeed05d
Jika saya membacanya dengan benar kali ini, saya salah tentang kebuntuan lain ketika lompatan kedua diterapkan. Itu tampaknya menjadi pendapat Red Hat juga, berdasarkan entri KB mereka. Namun, jika Anda telah menonaktifkan ntpd, biarkan dinonaktifkan selama 10 menit lagi, sehingga Anda tidak menemui jalan buntu ketika ntpd memanggil adjtimex (2).
Kami akan mencari tahu apakah ada bug lagi segera :)
PEMBARUAN KEDUA POST-LEAP:
Saya menghabiskan beberapa jam terakhir membaca kode kernel ntpd dan pre-patch (buggy), dan sementara saya mungkin sangat salah di sini, saya akan mencoba menjelaskan apa yang saya pikir sedang terjadi:
Pertama, ntpd memanggil adjtimex (2) sepanjang waktu. Ia melakukan ini sebagai bagian dari "clock loop filter" -nya, didefinisikan dalam local_clock di ntp_loopfilter.c. Anda dapat melihat kode itu di sini: http://www.opensource.apple.com/source/ntp/ntp-70/ntpd/ntp_loopfilter.c (dari ntp versi 4.2.6).
Filter loop jam berjalan cukup sering - ini berjalan setiap kali ntpd polling server hulu, yang secara default setiap 17 menit atau lebih. Bit filter loop jam yang relevan adalah:
if (sys_leap == LEAP_ADDSECOND)
ntv.status |= STA_INS;
Lalu:
ntp_adjtime(&ntv)
Dengan kata lain, pada hari-hari ketika ada lompatan kedua, ntpd menetapkan flag "STA_INS" dan memanggil adjtimex (2) (melalui portabilitas-pembungkusnya).
Panggilan sistem itu menuju kernel. Berikut kode kernel yang relevan: https://github.com/mirrors/linux/blob/a078c6d0e6288fad6d83fb6d5edd91ddb7b6ab33/kernel/time/ntp.c
Kernel codep kira-kira ini:
- baris 663 - mulai dari do_adjtimex rutin.
- line 691 - batalkan pengatur detik kabisat yang ada.
- baris 709 - ambil ntp_lock spinlock (kunci ini terlibat dalam kemungkinan kecelakaan livelock)
- baris 724 - panggil process_adjtimex_modes.
- saluran 616 - panggil process_adj_status.
- line 590 - set variabel global time_status, berdasarkan pada flag yang ditetapkan pada panggilan adjtimex (2)
- baris 592 - periksa time_state variabel global. dalam banyak kasus, panggil ntp_start_leap_timer.
- baris 554 - periksa time_status variabel global. STA_INS akan diset, jadi atur time_state ke TIME_INS dan panggil hrtimer_start (fungsi kernel lain) untuk memulai timer kedua lompatan. dalam proses membuat timer, kode ini mengambil xtime_lock. jika ini terjadi ketika CPU lain telah meraih xtime_lock dan ntp_lock, maka kernel livelocks. inilah sebabnya John Stultz menulis tambalan untuk menghindari penggunaan hrtimer. Inilah yang menyebabkan masalah semua orang hari ini.
- baris 598 - jika ntp_start_leap_timer tidak benar-benar memulai timer kabisat, atur time_state ke TIME_OK
- baris 751 - dengan asumsi kernel tidak livelock, stack dibatalkan dan spinlock ntp_lock dilepaskan.
Ada beberapa hal menarik di sini.
Pertama, saluran 691 membatalkan timer yang ada setiap kali adjtimex (2) dipanggil. Kemudian, 554 menciptakan kembali timer itu. Ini berarti setiap kali ntpd menjalankan clock loop filter-nya, kode buggy dipanggil.
Karena itu saya percaya Red Hat salah ketika mereka mengatakan bahwa sekali ntpd menetapkan flag leap-second, sistem tidak akan crash. Saya percaya setiap sistem yang menjalankan ntpd memiliki potensi untuk menghidupkan setiap 17 menit (atau lebih) selama 24 jam sebelum lompatan-detik. Saya percaya ini juga dapat menjelaskan mengapa banyak sistem crash; satu kali kesempatan tabrakan akan jauh lebih kecil kemungkinannya mengenai dibandingkan dengan 3 peluang per jam.
PEMBARUAN: Dalam solusi KB Red Hat di https://access.redhat.com/knowledge/solutions/154713 , para insinyur Red Hat sampai pada kesimpulan yang sama (bahwa menjalankan ntpd akan terus menerus mengenai kode kereta). Dan memang mereka melakukannya beberapa jam sebelum saya melakukannya. Solusi ini tidak ditautkan ke artikel utama di https://access.redhat.com/knowledge/articles/15145 , jadi saya tidak menyadarinya sampai sekarang.
Kedua, ini menjelaskan mengapa sistem yang dimuat lebih cenderung macet. Sistem yang dimuat akan menangani lebih banyak interupsi, menyebabkan fungsi kernel "do_tick" dipanggil lebih sering, memberikan lebih banyak peluang untuk kode ini untuk menjalankan dan mengambil ntp_lock ketika timer sedang dibuat.
Ketiga, apakah ada kemungkinan sistem crash ketika lompatan kedua benar-benar terjadi? Saya tidak tahu pasti, tetapi mungkin ya, karena timer yang menyala dan benar-benar menjalankan penyesuaian leap-second (ntp_leap_second, pada baris 388) juga mengambil ntp_lock spinlock, dan memiliki panggilan ke hrtimer_add_expires_ns. Saya tidak tahu apakah panggilan itu juga dapat menyebabkan livelock, tetapi sepertinya itu tidak mungkin.
Akhirnya, apa yang menyebabkan flag leap-second dinonaktifkan setelah leap-second berjalan? Jawabannya ada ntpd berhenti mengatur lompatan-bendera di beberapa titik setelah tengah malam ketika panggilan adjtimex (2). Karena flag tidak disetel, tanda centang pada baris 554 tidak akan benar, dan tidak ada timer akan dibuat, dan baris 598 akan mengatur ulang variabel global time_state ke TIME_OK. Ini menjelaskan mengapa jika Anda memeriksa flag dengan adjtimex (8) tepat setelah leap second, Anda masih akan melihat set flag leap-second.
Singkatnya, saran terbaik untuk hari ini adalah yang pertama kali saya berikan: disable ntpd, dan nonaktifkan flag leap-second.
Dan beberapa pemikiran terakhir:
- tidak ada vendor Linux yang memperhatikan patch John Stultz dan menerapkannya pada kernel mereka :(
- mengapa John Stultz tidak memperingatkan beberapa vendor bahwa ini diperlukan? mungkin peluang livelock tampak cukup rendah sehingga kebisingan tidak dijamin.
- Saya telah mendengar laporan tentang proses Java mengunci atau memutar ketika leap-second diterapkan. Mungkin kita harus mengikuti petunjuk Google dan memikirkan kembali bagaimana kita menerapkan lompatan detik ke sistem kita: http://googleblog.blogspot.com/2011/09/time-technology-and-leaping-seconds.html
06/02 Pembaruan dari John Stultz:
https://lkml.org/lkml/2012/7/1/203
Posting tersebut berisi langkah demi langkah mengapa lompatan kedua menyebabkan timer futex berakhir sebelum waktunya dan terus menerus, sehingga meningkatkan beban CPU.