20 puan yazan darjeeling 22 일 전 | 9 yorum | WhatsApp'ta paylaş

macOS XNU kernelinde, tam olarak 49 gün 17 saat 2 dakika 47 saniye kesintisiz çalıştıktan sonra TCP ağ iletişimini tamamen felç eden bir hata keşfedildi. Sebep, kernel içindeki TCP zaman damgası sayacı tcp_now için oluşan 32 bit tamsayı taşması. ping yanıt vermeye devam ediyor, ancak yeni TCP bağlantıları artık hiç kurulamıyor ve şu anda tek çözüm yeniden başlatma.


Keşif süreci

Photon, iMessage servis durumunu izleyen Mac sunucu filosunu 7/24 çalıştırıyordu. 30 Mart 2026’da, son yeniden başlatmadan tam 49,7 gün sonra birden fazla makine sessizce yeni TCP bağlantılarını reddetmeye başladı. ping normaldi, mevcut bağlantılar da korunuyordu, ancak yeni soket açmaya yönelik tüm girişimler başarısız oluyordu.

Hizmeti geri yüklemek için yeniden başlattıktan sonra ekip, birkaç gün içinde aynı kritik eşiğe ulaşacak iki makineyi (A, B) seçip canlı deney tasarladı.


Hatanın teknik mekanizması

Sorunlu sayaç tcp_now

XNU kernelindeki tcp_now, açılıştan sonra geçen süreyi milisaniye cinsinden sayan 32 bit işaretsiz bir tamsayı. 32 bitin ifade edebildiği en büyük değer 4.294.967.295 ms — bu da tam olarak 49 gün 17 saat 2 dakika 47 saniyeye denk geliyor.

Sayaç neden "donuyor"?

tcp_now güncelleme kodunda, "saatin geriye gitmesini önlemek" için basit bir koruma bulunuyor:

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

Taşma anında yeni hesaplanan current_tcp_now yeniden 0 civarına sarılıyor, ancak mevcut tmp değeri en yüksek değerin yakınında kalıyor. Bu yüzden tmp < current_tcp_now koşulu sonsuz şekilde false oluyor ve tcp_now o değerde takılı kalıyor. Yani kernelin TCP saati durmuş oluyor.

TIME_WAIT neden süresi dolmuyor?

Bir TCP bağlantısı kapandığında kernel, bitiş zamanını tcp_now + 30 saniye olarak kaydediyor. Çöp toplayıcı bunu periyodik olarak tarıyor ve tcp_now >= bitiş zamanı ise bağlantıyı serbest bırakıyor. Ancak tcp_now donarsa bu koşul asla true olmuyor, dolayısıyla TIME_WAIT bağlantıları hiçbir zaman temizlenmiyor.


Deney sonuçları

Ekip, taşma öncesi ve sonrasında beşer dakika boyunca saniyede birden çok kısa ömürlü TCP bağlantısı oluşturarak TIME_WAIT sayısını gözlemledi.

Aralık Durum
Taşma öncesi TIME_WAIT yaklaşık 200 civarında kararlı kaldı (her 30 saniyede normal süre dolumu)
Taşmadan hemen sonra Süre dolumu durdu ve TIME_WAIT monoton artmaya başladı
Bağlantı oluşturma durdurulduktan 84 saniye sonra 0 olması gereken TIME_WAIT bunun yerine arttı (2.828 → 2.837)
Taşmadan 9,5 saat sonra Machine A: 4.888, Machine B: 8.217 — tek bir kayıt bile temizlenmedi

9,5 saat sonra SYN_SENT durumundaki bağlantılar da 3.000’in üzerine çıktı ve Machine B’nin load average değeri 49.74 seviyesine fırladı.


Etkilenen ortamlar

Genel kullanıcı Mac’leri, OS güncellemeleri nedeniyle genellikle 49 günden önce yeniden başlatıldığı için daha az etkileniyor. Ancak şu ortamlar yüksek risk taşıyor:

  • Uzun süre kesintisiz çalışan sunucu filoları
  • macOS CI/CD build sunucuları (Jenkins, GitHub Actions self-hosted runner’ları)
  • Mac Pro iş istasyonları (uzun süreli render/derleme işleri)
  • Uzaktan yönetilen colocation Mac’ler
  • Mac mini build farm ve test altyapıları

Mevcut ve gelecekteki önlemler

Ekip şu anda, yeniden başlatma olmadan donmuş tcp_now değerini doğrudan düzeltmeye yarayacak bir workaround geliştiriyor. O zamana kadar tek geçici önlem şu:

> 49 gün 17 saat 2 dakika 47 saniye dolmadan yeniden başlatmayı planlayın.


Benzer tarihsel hatalar

Bu hata, köklü bir geçmişe sahip tamsayı taşması hataları ailesine ait: Windows 95/98’in 49,7 günlük çökmesi, 2038 problemi (Y2K38), GPS hafta numarası rollover’ı ve Pac-Man 256. seviye kill screen’i aynı kategoriye giriyor.


Orijinal metin: Photon Blog, 2026.04.07

9 yorum

 
brilliant08 22 일 전

Görünüşe göre artık macOS da 49 günlük yasını tamamlıyor.

 
bungker 17 일 전

Ahahahah

 
roxie 21 일 전

zzzzz

 
devil1032 21 일 전

Zaman meselesi denince aklıma Y2K geliyor.. 🤖..

 
savvykang 21 일 전

İnsanlar aynı hataları tekrarlar.

 
shincad 20 일 전

Demek ki gerçekten 49 günden önce yeniden başlatmak gerekiyormuş.

Aslında burada zamanı asla mutlak olarak < ile karşılaştırmamak gerekiyor..

if ((int32_t)(tmp - current_tcp_now) < 0) {
os_atomic_cmpxchg(&tcp_now, tmp, current_tcp_now, ...);
}
Böyle yapıp iki değerin farkına bakmak gerekiyordu... İnsan aynı hatayı hep yapıyor.

 
icosahedron 21 일 전

Böyle şeyleri görünce 2038'de gerçekten ortalık karışabilir diye düşünüyorum

 
princox 21 일 전

Vay canına, bu gerçekten akıl almaz....

 
jic5760 21 일 전

Peki AWS ya da GitHub'ın mac instance'larında şimdiye kadar nasıl sorun çıkmadı...?