このサイトは、ほんの入り口です

ここにあるのは、だれかが実際に調べ、考え、作ってきたことを集めたメモです。気になったら、ページの下の「参考にした情報源」から、もとの本や記事、それを生み出した人たちに、直接ふれてみてください。このメモには書ききれないおもしろさが、そこにあります。

1秒びょう ふえるだけで、コンピューターが おかしく なるのは どうして?

1秒足すだけで、なぜコンピューターに不具合が起きるのか ── うるう秒とソフトウェアの思い込み

うるう秒でシステムが不具合を起こす理由 ── Cloudflare(2017年)とLinuxカーネル(2012年)の事例、平滑化、うるう秒廃止の決議

分野:技術

2017ねんの がんじつ、かかった 時間を はかって いた コンピューターが、「1秒びょうぐらい マイナス」と いう 答えを だしました。かかった 時間が マイナスに なる はずは ありません。

うるう秒びょうで 時計が 1秒びょう もどった からです。コンピューターの プログラムは、「時間は まえへ すすむ ものだ」と かんがえて つくって あります。その ぜんていが くずれると、こまる ことが おきます。この きじでは、ほんとうに あった ふたつの できごとを みて、どうして そう なるのかを たしかめます。

2017年の元日、世界中のサイトを支える会社Cloudflareの機械が、「数ミリ秒」のはずの時間を「マイナス約1秒」と測りました。このプログラムは、測った時間がマイナスになる場合を想定していませんでした。

原因は、うるう秒で時計が1秒もどったことです。多くのプログラムは「時間は前にしか進まない」「1日は必ず86400秒」という前提で書かれています。うるう秒はその前提を破ります。この記事では、2017年のCloudflareと2012年のLinuxの例、対策、そしてうるう秒をやめる決定までを見ていきます。

2017年1月1日、Cloudflareのプログラムは、数ミリ秒のはずの応答時間を負の値として計算した。原因はうるう秒で、システムの時計が1秒戻ったことである。

多くのソフトウェアは、時刻が単調に増え、1日は必ず86400秒であることを前提に書かれている。うるう秒はその前提を破る。この記事では、2017年のCloudflare、2012年のLinuxカーネルという2つの別種の不具合、Googleの平滑化という対策、2026年10月に決まったうるう秒の廃止を扱う。

読み方を切り替えられます。画面の上にある「よみかた」のボタンで、小学校低学年むけ・小学校高学年むけ・中学生むけの3つの書き方に切り替わります。むずかしいと思ったら、いつでもやさしい方に戻ってください。選んだ読み方はブラウザが覚えているので、次に別の記事を開いたときも同じ読み方で始まります。

1. どうして 1秒びょうで こまるの?

1. 「時間は前に進む」という前提が崩れる

1. 時刻は単調増加するという前提と、うるう秒

うるう秒びょうは、じっさいの 地球の まわり方と 時計の ずれを なおす ために、ときどき 1秒びょう たす きまりです。1972ねんから 2016ねんの おわりまでに、27かい ありました[7]。

人間は「1秒びょうたす」と きいても、なにも こまりません。でも、プログラムは ちがいます。プログラムは「1日は ぜんぶで 86400秒びょう」と きめて つくって あることが おおいのです[5]。86401秒びょうの 日は、かんがえて いません。

たとえば、「ゴールの 時こく ひく スタートの 時こく」で かかった 時間を けいさんする プログラムが あるとします。まんなかで 時計が 1秒びょう もどると、こたえは ほんとうより 1秒びょう みじかく なります。1秒びょうより みじかい 時間を はかって いたなら、マイナスに なって しまいます。

うるう秒は、地球の自転にもとづく時刻と原子時計の時刻のずれを直すために、ときどき1秒を足す決まりです。1972年から2016年末までに27回行われました[7]。

人間は「1秒足す」と聞いても困りません。でも、プログラムは別です。多くのコンピューターは、時刻を「1970年1月1日から、うるう秒を数えずに表した秒数」で扱います(UNIX時間)。この数え方を定めたPOSIXは、1日をちょうど86400秒として数えます[5]。だから、うるう秒だけに対応する秒の番号はありません。

そのため、うるう秒のとき、システムは時計を1秒もどしたり、同じ秒を2回数えたりして、つじつまを合わせます(表示がどうなるかはうるう秒で日本の時計が「午前8時59分60秒」になるのはなぜ?で扱いました)。この「時計が1秒もどる」ことが、不具合のもとになります。

たとえば、ストップウォッチ代わりに「終わった時刻 − 始まった時刻」を計算するプログラムを考えます。計算のとちゅうで時計が1秒もどると、答えは本当より1秒短くなります。1秒より短い時間を測っていたなら、マイナスになります。

うるう秒は、地球の自転にもとづく時刻(UT1)と、原子時計にもとづく協定世界時(UTC)のずれを0.9秒以内に保つため、必要なときに1秒を挿入する制度である。1972年から2016年末までに27回行われた[7]。

人間には1秒の挿入は大きな問題ではない。だがソフトウェアは、時刻を「1970年1月1日から、うるう秒を数えずに表した秒数」で扱うことが多い(UNIX時間)。POSIXは、この経過秒数の計算で、各日をちょうど86400秒として数える。UTCとの対応は規定されず、調整は実装に任されている[5]。つまり、23:59:60に固有の番号がない。

結果として、システムは時計を1秒戻す、同じ秒を2回数える、といった扱いで折り合いをつける。表示の側の事情は別の記事で扱った(うるう秒挿入時の時計表示)。この記事では、中身のプログラムの側で何が起きるかを扱う。

時刻の差を計算する処理は、時計が1秒戻ると実際より1秒短い値を返し、測る時間が1秒より短ければ負の値になる。時刻が単調増加するという前提は、うるう秒で破れる。

2. 2017ねん がんじつ、時間が マイナスに なった

2. 2017年の元日、Cloudflareで起きたこと

2. Cloudflare(2017年)── 負の値が乱数関数を止めた

Cloudflareは、せかいじゅうの ウェブサイトの はやさや あんぜんを たすける 会社です。ここの ネットの「じゅうしょ ちょう」の プログラムは、ほかの コンピューターに たずねて、へんじが くるまでの 時間を はかって います。へんじが はやい あいてを えらぶ ためです。

ふつうは 1秒びょうより ずっと みじかい 時間です。ところが 2017ねん1月1日の ぜろ時(せかいの きじゅんの 時こく。日本では 朝9時)、うるう秒びょうで 時計が 1秒びょう もどりました。はかって いた さいちゅうに もどったので、「かかった 時間」が マイナスに なりました[1]。

プログラムは、マイナスの 数を うけとる ことを かんがえて いませんでした。そのため、あいてを えらぶ ぶぶんが とまって しまい、一ぶの といあわせで エラーが でました。いちばん ひどい ときでも、この しくみへの といあわせの 0.2パーセントぐらいでした[1]。

同じ 日の 朝6時45分ごろ(せかいの きじゅんの 時こく)には、なおした プログラムが ぜんぶの ばしょに とどきました。Cloudflareは あとで、「時間は もどらない」という おもいこみが もとだったと ふりかえって います。

Cloudflareは、世界中のウェブサイトの表示や安全を助ける会社です。その「名前から住所を調べる」DNSの自社プログラムは、他のコンピューターに問い合わせて、返事が来るまでの時間(往復時間)を測っています。返事の速い相手を選ぶためです。

通常は数ミリ秒です。ところが2017年1月1日0時(UTC、日本では午前9時)、うるう秒で時計が1秒戻りました。測っている最中に戻ったので、往復時間が負の値になりました[1]。

プログラムは、複数の測定値をならして使っていました。1回の負の値なら影響は小さいのですが、数回続くと、ならした値までマイナスになりました。この値を、相手を選ぶための乱数を作る関数に渡したところ、マイナスの数が渡されると停止する関数だったため、そこで止まりました。

影響を受けたのは、CNAMEというタイプのDNS記録を使っていたお客さんだけでした。いちばん多いときで、DNSの問い合わせの約0.2%、HTTPリクエスト全体の1%未満にエラーが出た、とCloudflareは書いています。特にひどい機械の修正は90分以内に配られ、すべての拠点には、UTCの午前6時45分までに行き渡りました[1]。

Cloudflareの技術者は、原因を「時間は決して戻らないという誤った前提」とまとめています。当時このプログラムを書いていたGo言語には、戻らない時計(単調時計)がなかった、とも書いています。

Cloudflareの自社製DNSソフトウェアRRDNSは、Go言語で書かれ、上流のリゾルバーへの問い合わせの往復時間を、time.Now()の差で測っていた。リゾルバーの重みづけ選択には、この往復時間を平滑化した値を使う[1]。

2017年1月1日0時(UTC。日本時間では午前9時)、うるう秒でシステムの時計が1秒戻った。往復時間は通常、数ミリ秒だったため、測定中に1秒戻ると、差は負になる。1回の負の値は平滑化で吸収されたが、数回続くと平滑化後の値が負になり、これが引数に負の値を取るとパニックを起こすrand.Int63n()に渡された。パニックはrecoverで捕捉されていた。

影響はCNAMEレコードを使う顧客に限られ、102拠点のうち少数の機械で起きた。ピーク時でDNS問い合わせの約0.2%、HTTPリクエスト全体の1%未満でエラーが出た。最も影響を受けた機械へのパッチは90分以内、全世界への展開は6時45分(UTC)に完了した。パッチは、時刻が逆行した場合に上流の性能データをリセットし、負の値が選択処理に渡らないようにした[1]。

Cloudflareは、根本原因を「時間は戻らない」という誤った前提と述べている。当時のGoには単調な時間源がなかったため、2つの時刻の差が負になっていないかを確認すべきだったとしている。

3. 2012ねんにも、「タイマー」の ふぐあいが あった

3. 2012年、時計を戻してもタイマーは戻らなかったLinux

3. Linuxカーネル(2012年)── hrtimerのオフセットが更新されなかった

もうひとつ、2012ねんにも うるう秒びょうの ふぐあいが ありました。6月30日が おわる とき(せかいの きじゅんの 7月1日 ぜろ時。日本では 朝9時)に うるう秒びょうが はいると、「リナックス」という きほんの ソフトを つかっていた コンピューターが、あちこちで おかしく なりました。

オーストラリアの ひこうきの よやくの システムが 1時間ほど とまり、ひこうき会社の カンタスと ヴァージン・オーストラリアの 人たちは、おきゃくさんを 手で うけつけしました。レディットや モジラなどの サイトも、おなじ ふぐあいの えいきょうを うけたと つたえられました[2]。

げんいんの ひとつは、時計の「なおしかた」でした。リナックスは、うるう秒びょうの ときに 時計を 1秒びょう もどしました。ところが、「9時0ぷん1秒びょうに ならしてね」と 時こくを きめて たのむ タイマーの かかりには、1秒びょう もどった ことを つたえませんでした。かかりは、もどす まえの 時計を みつづけて いた ような ものです。

タイマーは 1秒びょう はやく なり、1秒びょうより みじかく まつ しごとは、すぐ もどって くる ことが ありました。それが くりかえされて、コンピューターの いそがしさが きゅうに ふえたのです[3]。ただし、ぜんぶの ふぐあいが この げんいんだったかは、わかって いません。

もう1つの例は2012年です。6月30日が終わるとき(UTCの7月1日午前0時、日本では午前9時)にうるう秒が入ると、Linuxを使っていたコンピューターが、世界のあちこちで不調になりました。

オーストラリアの航空会社カンタス航空とヴァージン・オーストラリアが使う予約システム「Amadeus Altea」は、約1時間止まり、職員は手作業で搭乗手続きをしました。Mozilla、Reddit、LinkedIn、Yelpなどのサービスも、同じ不具合の影響を受けたと報じられました。Amadeusは原因を「Linuxカーネルのバグ」と説明し、1時間以内に回避策を取ったと述べました[2]。

カーネル開発者のジョン・ストルツ氏は、原因を次のように説明しています。うるう秒のとき、カーネルは時計(CLOCK_REALTIME)を1秒戻しました。ところが、タイマーを管理する部分(hrtimer)には、1秒戻ったことを知らせる処理が抜けていました[3]。

「9時ちょうどに知らせて」と時刻で頼まれる係が、戻す前の時計を見続けていたようなものです。その結果、時刻を指定したタイマーは、1秒早く鳴ります。待ち時間が1秒より短いものは、すぐに返ってしまうことがありました。待っては返り、待っては返りを繰り返すプログラムは、処理が急に増えました。修正は、うるう秒の処理に、この知らせを加えることでした[3]。

この資料が説明しているのは、タイマーによる負荷の急上昇です。報じられた障害のすべてが、この1つの原因だったとはいえません。

2012年6月30日23:59:60(UTC。日本時間では7月1日午前8時59分60秒)のうるう秒の前後に、Linuxを使うシステムで障害が相次いだ。Amadeus Alteaは約1時間停止し、カンタス航空とヴァージン・オーストラリアは手作業で搭乗手続きを行った。Mozilla、Reddit、LinkedIn、Yelpなどにも同じ不具合の影響が出たと報じられた。Amadeusは原因をLinuxカーネルのバグとし、1時間以内に回避策を取ったと説明している[2]。

カーネル開発者のJohn Stultzの説明では、うるう秒でCLOCK_REALTIMEが1秒戻されたが、clock_was_set()が呼ばれなかったため、hrtimerのbase.offsetが更新されなかった。hrtimerが持つ壁時計の見え方が、本来の時刻より1秒進んだ状態になる[3]。

「この時刻まで待つ」と時刻で指定するタイマー(TIMER_ABSTIMEのCLOCK_REALTIMEタイマー)が、1秒早く期限に達する。1秒未満の待ちは、即座に返る。これをfutex_waitなどのループで使うプログラムでは、返っては待つ処理が繰り返され、負荷が急に上がった。この状態は、clock_was_set()が呼ばれるまで続いた。修正は、うるう秒の処理からclock_was_set()を呼ぶことである[3]。

この資料が説明しているのは、タイマーによる負荷の急上昇である。報じられた障害のすべてが、この1つの原因だったとはいえない。

4. こまらない ために、人は なにを して いる?

4. 不具合を避ける2つの方法 ── 戻らない時計と、1日かけて延ばす

4. 対策 ── 単調時計とうるう秒の平滑化(スミア)

ひとつめは、「もどらない 時計」を つかう ことです。かかった 時間を はかる ときは、かべの 時計では なく、ストップウォッチの ように かならず すすむ 時計を つかいます。

ふたつめは、Googleの やりかたです。1秒びょうを 一ぺんに たすのでは なく、1日ぐらい かけて、すこしずつ 1秒びょうの ながさを のばします。時計は もどらず、「60秒びょう」も でて きません。Googleは 2008ねんから、この やりかたを つかって いると のべて います[4]。

1つ目は、戻らない時計(単調時計)を使うことです。経過時間を測るときは、壁の時計ではなく、戻らないストップウォッチのような時計を使います。たとえばPythonのtime.monotonic()は「戻ることのない時計」で、システムの時計が変更されても影響されない、と説明されています[6]。一方のtime.time()は、時計が戻されると、前より小さい値を返すことがあります。

2つ目は、Googleのやり方です。2008年から、うるう秒の1秒を一度に足さず、前後に広げて、少しずつ足しています。推奨されているのは、UTCの正午から翌日の正午までの24時間です。この間、1秒が約11.6マイクロ秒(100万分の11.6秒)ずつ長くなります。時計は戻らず、「60秒」も現れません。そのかわり、UTCとのずれは最大でおよそ0.5秒です[4]。

対策は主に2つある。1つ目は、経過時間の計測に単調時計を使うことだ。たとえばPythonのtime.monotonic()は、戻ることがなく、システム時計の更新に影響されない。一方time.time()は、時計が戻されると前の呼び出しより小さい値を返すことがある[6]。Cloudflareの事例なら、時刻の差を計算するときに単調時計を使うか、差が負になっていないかを確かめる、という対策になる。

2つ目は、Googleが2008年から使っている平滑化(スミア)である。推奨は、UTCの正午から翌日の正午までの24時間の線形平滑化で、この間に1秒あたり約11.6μsずつ長くして、うるう秒の1秒を分散させる。時計の進み方の変化は100万分の11.6ほどで、ごく小さい。うるう秒の開始時は、UTCよりほぼ0.5秒遅れ、終了時にほぼ0.5秒進む。時計は戻らず、23:59:60も現れない[4]。

5. うるう秒びょうは、これから どうなるの?

5. うるう秒そのものをやめる決議(2026年10月)

5. 2026年のCGPM決議 ── 連続的なUTCへ

2026ねんの 10月、せかいの たんい(秒びょうや メートルなど)を きめる 会ぎで、うるう秒びょうを やめる ことが きまりました。2027ねんの 5月20日から、UTCという せかいの 時計は、とぎれずに すすみます[8]。

かわりに、じっさいの 地球の 時こくと、時計の 時こくの ずれは、1時間ぐらいまで ひろがっても よい ことに なりました。星を みる しごとなど、ずれを きにする 人は、これからは ずれを べつに しらべます[7]。

うるう秒びょうを ひくという、まだ いちども やった ことの ない やりかたも、きけんが たかいと かんがえられて います。この はなしは1びょうを たす「うるう秒」の はんたいで、1びょうを けす ことも あるの?でも よめます。

2026年10月にフランスのベルサイユで開かれた第28回国際度量衡総会(CGPM)で、うるう秒をやめる決議が採択されました[7]。2027年5月20日から、世界の標準時UTCは連続的になります。地球の自転にもとづく時刻(UT1)とUTCの差を、最大3600秒(1時間)まで広げてよいことになりました[8]。

決議文は、背景として、将来「引く」うるう秒が必要になる確率が急速に高まると見られること(2035年までに30%という推定)を挙げています。引くうるう秒は一度も行われたことがなく、重要な基盤にとってリスクが高いと考えられている、とも書かれています[8]。この記事の2つの事例のように、時計が1秒戻るだけでも不具合は起きます。1秒が飛ぶ場合の影響は、まだ試されていません。

ただし、天文や測地のように、天体の位置と時刻のずれが必要な分野では、広がっていくずれを別に管理することになります[7]。引くうるう秒の話は1秒を足すうるう秒に、1秒を消す「負のうるう秒」はあるのかにあります(廃止の決議より前に書いた記事です)。

2026年10月15日、フランスのベルサイユで開かれた第28回国際度量衡総会(CGPM)が、うるう秒の廃止にあたる決議5を採択した[7]。決議の本文は、「連続的なUTCは2027年5月20日に有効になる」「|UT1−UTC|の最大値は3600秒(1時間)とする」と定める[8]。

決議は前文で、負のうるう秒の確率が近い将来に急速に高まると見込まれること(2025年3月のCCTF/IERSワークショップの推定では、2035年までに30%)、負のうるう秒は過去に実施されたことがなく、重要インフラにとって高リスクと考えられることを挙げている[8]。この記事の事例は、時計が戻っただけで障害が起きた例である。一度も試されていない「削除」の危険が、廃止の理由の1つになっている。

ただし、天文や測地など、天体の位置と時刻の差を必要とする分野では、広がるUT1とUTCの差を別に管理する必要がある[7]。引くうるう秒の見通しはうるう秒は「足す」だけでなく「消す」こともあるのかに書かれている(廃止の決議より前の記事なので、状況が変わった点に注意)。

6. じぶんで ためして みよう

6. 自分で確かめてみよう

6. 自分で確かめる ── 時刻の差を安全に計算する

かみに、スタートの 時こくと、ゴールの 時こくを かいて、ひきざんを して みましょう。たとえば、スタートが 10時0ぷん5秒びょう、ゴールが 10時0ぷん8秒びょうなら、3秒びょうです。

つぎに、「とちゅうで 時計が 1秒びょう もどった」ことに して、ゴールの 時こくを 10時0ぷん7秒びょうに して みます。こたえは 2秒びょうに なって しまいます。とちゅうで もどる 時計では、かかった 時間が ただしく はかれない ことが わかります。

ストップウォッチは、スタートした ときから かぞえはじめるので、かべの 時計が もどっても かんけいありません。

紙に、スタートとゴールの時刻を書いて、引き算をしてみましょう。スタートが10時0分5秒、ゴールが10時0分8秒なら、3秒です。

次に、「途中で時計が1秒戻った」ことにします。ゴールが10時0分7秒になったことにすると、答えは2秒です。ストップウォッチ(スタートから数え始める時計)なら、壁の時計が戻っても関係ありません。

Pythonが使える人は、time.time()とtime.monotonic()の説明を、公式ドキュメントで読み比べてみてください。実際に「時計を1秒戻す」実験は、他のソフトに影響するのでやらないでください。

経過時間の計算は、紙の上で試せる。スタートとゴールを時刻で書いて引き算をし、次にゴールの時刻を1秒小さくして、答えがどう変わるかを見る。時刻の差が、実際より短い値になることを、自分の手で確かめられる。

Pythonの公式ドキュメントで、time.time()とtime.monotonic()、time.perf_counter()の説明を読み比べるとよい。time.monotonic()が「戻らない時計」と説明され、time.time()は戻りうると書かれている[6]。実際にシステムの時計を戻す実験は、他のソフトウェアに影響するので避ける。

Cloudflareの原文(出典[1])には、コードの断片と、原因分析が詳しく書かれている。英語だが、短いので読む価値がある。

しらべた もとの じょうほう

参考にした情報源

参考にした情報源と、その使い方

本文の数字は、出典の値にもとづく。2012年の不具合の全体は、複数の報道とカーネル開発者のメールによるもので、原因が1つだったかどうかは分かれる。

  1. Cloudflare「How and why the leap second affected Cloudflare DNS」 https://blog.cloudflare.com/how-and-why-the-leap-second-affected-cloudflare-dns/ (2017年1月1日の障害の時刻・原因・影響・修正)
  2. The Register「Leap second 'crashes' Qantas, Virgin Australia check-in systems」(2012年7月2日) https://www.theregister.com/2012/07/02/leap_second_crashes_airlines/ (Amadeus Alteaの停止、航空会社、Linuxカーネルのバグという説明)
  3. LWN.net 掲載のカーネル開発者 John Stultz の投稿(2012年7月。うるう秒によるfutex関連の負荷上昇の修正案) https://lwn.net/Articles/504658 (hrtimerのオフセットが更新されなかった原因と症状)
  4. Google「Leap Smear」 https://developers.google.com/time/smear (24時間の線形平滑化、約11.6μs、2008年から)
  5. The Open Group「POSIX.1-2024 Base Definitions, 4.19 Seconds Since the Epoch」 https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap04.html (1日をちょうど86400秒として数える)
  6. Python Software Foundation「time — Time access and conversions」 https://docs.python.org/3/library/time.html (monotonic()とtime()の説明)
  7. Euronews「Global timekeeping rules change: leap second scrapped from 2027」(2026年10月16日) https://www.euronews.com/2026/10/16/global-timekeeping-rules-change-leap-second-scrapped-from-2027 (採択日、27回、天文分野の注意点)
  8. BIPM「Resolution 5 of the 28th CGPM (2026)」 https://www.bipm.org/en/cgpm-2026/resolution-5 (2027年5月20日、3600秒、負のうるう秒の前置き)

なおした ところ

更新履歴

更新履歴(改版の記録)

  •  初版を公開。

このサイトでは、公開した記事の本文は原則として書き直しません。誤りが見つかったときや、内容が古くなったときだけ手を入れ、その理由をこの欄に残します。