20 ポイント 投稿者 darjeeling 22 일 전 | 9件のコメント | WhatsAppで共有

macOS XNUカーネルで、正確に49日17時間2分47秒連続稼働した後、TCPネットワーキングが完全に麻痺するバグが発見された。原因は、カーネル内部のTCPタイムスタンプカウンタ tcp_now32ビット整数オーバーフローだ。ping は応答し続けるが、新しいTCP接続はまったく確立できなくなり、現時点で唯一の解決策は再起動である。


発見の経緯

Photon は iMessage サービスの状態を監視する Mac サーバーフリートを 24/7 で運用していた。2026年3月30日、最後の再起動から正確に49.7日が経過した時点で、複数のマシンが静かに新規TCP接続を拒否し始めた。ping は正常で、既存の接続も維持されていたが、新しいソケットを開くあらゆる試みが失敗した。

サービスを復旧するために再起動した後、チームは数日以内に同じしきい値へ到達するマシン2台(A、B)を選び、ライブ実験を設計した。


バグの技術的な仕組み

問題のカウンタ tcp_now

XNUカーネルの tcp_now は、起動後の経過時間をミリ秒単位で数える32ビット符号なし整数だ。32ビットで表現できる最大値は 4,294,967,295ms で、これを換算すると正確に49日17時間2分47秒になる。

なぜカウンタが「凍り付く」のか?

tcp_now の更新コードには、「時計が逆行しないように」する単純なガードがある:

if (tmp < current_tcp_now) {  
    os_atomic_cmpxchg(&tcp_now, tmp, current_tcp_now, ...);  
}  

オーバーフローの瞬間、新たに計算された current_tcp_now は 0 近辺へ巻き戻る一方、既存の tmp は最大値近辺にある。条件 tmp < current_tcp_now永遠に falseになり、tcp_now はその値で停止したままになる。カーネルのTCPクロックが止まってしまうのだ。

TIME_WAIT が期限切れにならない理由

TCP接続が閉じられる際、カーネルは有効期限を tcp_now + 30秒 として記録する。ガベージコレクタが定期的にスキャンし、tcp_now >= 有効期限 であれば接続を解放する。ところが tcp_now が凍結すると、この条件が決して真にならず、TIME_WAIT 接続が永久に回収されなくなる。


実験結果

チームは、オーバーフロー前後それぞれ5分間、毎秒複数の短命TCP接続を生成しながら TIME_WAIT 数を観察した。

区間 状態
オーバーフロー前 TIME_WAIT は約200件で安定して維持(30秒ごとに正常に期限切れ)
オーバーフロー直後 期限切れが止まり、TIME_WAIT の単調増加が始まる
接続生成停止から84秒後 0 になるはずの TIME_WAIT が逆に増加(2,828 → 2,837)
オーバーフロー後9.5時間 Machine A: 4,888件、Machine B: 8,217件 — 1件も回収されず

9.5時間後には SYN_SENT 状態の接続も 3,000件以上たまり、Machine B のロードアベレージは 49.74 まで急上昇した。


影響を受ける環境

一般消費者向けの Mac は、OSアップデートで49日より前に再起動することが多いため、影響は小さい。しかし、次の環境は高リスクだ:

  • 長時間無停止のサーバーフリート
  • macOS CI/CD ビルドサーバー(Jenkins、GitHub Actions セルフホストランナー)
  • Mac Pro ワークステーション(レンダリング・コンパイルを長時間実行)
  • リモート管理のコロケーション Mac
  • Mac mini のビルドファーム・テストインフラ

現在および今後の対応

チームは現在、再起動せずに凍結した tcp_now を直接修正するワークアラウンドを開発中だ。それまでの暫定対策は1つだけである:

49日17時間2分47秒に達する前に再起動をスケジュールせよ。


類似する歴史的バグ

このバグは、長い系譜を持つ整数オーバーフローバグの一群に属する。Windows 95/98 の49.7日クラッシュ、2038年問題(Y2K38)、GPS週番号ロールオーバー、パックマン256面キルスクリーンはいずれも同系統だ。


原文: Photon Blog, 2026.04.07

9件のコメント

 
brilliant08 22 일 전

最近はmacOSも49日をきっちり迎えるんですね

 
bungker 17 일 전

wwwww

 
roxie 21 일 전

zzzzz

 
devil1032 21 일 전

時刻の問題というと、Y2Kを思い出しますね.. 🤖..

 
savvykang 21 일 전

人間は同じ過ちを繰り返します

 
shincad 20 일 전

49日になる前に、本当に再起動しないといけないんですね。

これは本来、時刻を絶対値の < で比較してはいけないんですよね..

if ((int32_t)(tmp - current_tcp_now) < 0) {
os_atomic_cmpxchg(&tcp_now, tmp, current_tcp_now, ...);
}
こうして2つの値の差を見るべきなのに... 人間はいつも同じミスをしてしまいますね.

 
icosahedron 21 일 전

こういうのを見ると、2038年には本当に大騒ぎになるのかもしれませんね

 
princox 21 일 전

うわ、これは本当にありえないですね……。

 
jic5760 21 일 전

AWS や GitHub の Mac インスタンスは、これまでどうして問題がなかったんでしょうか……?