- macOS'taki TCP zaman damgası sayacı (
tcp_now), açılıştan yaklaşık 49,7 gün sonra 32 bit taşma nedeniyle dahili TCP saatini durduruyor - Bunun sonucunda TIME_WAIT durumundaki bağlantılar süresi dolmadan birikiyor ve geçici portlar serbest bırakılmıyor
- Zamanla geçici port tükenmesi nedeniyle tüm yeni TCP bağlantıları başarısız oluyor ve yalnızca mevcut bağlantılar korunuyor
- ICMP (
ping) normal çalışsa da TCP'nin tüm işlevi felç oluyor ve yeniden başlatma dışında kurtarma mümkün olmuyor - Uzun süre çalışan macOS sunucuları, build makineleri ve CI ortamları bu soruna 49 gün 17 saatlik döngüyle maruz kalıyor; çekirdek düzeltilene kadar periyodik yeniden başlatma gerekiyor
Arka plan: TCP'nin temel kavramları
- TCP bağlantıları kapanırken hemen ortadan kaybolmaz; bunun yerine TIME_WAIT durumuna girer. Bu, gecikmeli paketleri işlemek ve güvenilir kapanışı sağlamak için gerekli bir aşamadır
- Eski paketlerin yeni bir bağlantı olarak yanlış yorumlanmasını önlemek ve son ACK kaybolduğunda yeniden iletimi işlemek içindir
- TIME_WAIT süresi 2 × MSL (Maximum Segment Lifetime) olarak tanımlanır ve macOS'te yaklaşık 30 saniye olarak ayarlanmıştır
- MSL, bir TCP segmentinin ağ üzerinde yaşayabileceği azami süredir; RFC 793'te 2 dakika olarak tanımlansa da modern sistemlerde çok daha kısa ayarlanır
- 32 bit işaretsiz tamsayı taşması, değer azami sınırı (4.294.967.295) aştığında 0'a dönmesi durumudur. macOS'un TCP zaman damgası (
tcp_now) açılıştan itibaren milisaniye cinsinden artan 32 bitlik bir sayaçtır ve 49 gün 17 saat 2 dakika 47,296 saniye sonra taşma oluşur
Keşif: 49,7 gün sonra TCP bağlantılarının durması
- Photon'un iMessage izleme amaçlı Mac sunucuları 7/24 çalışıyordu ve 30 Mart 2026'da, açılıştan tam 49,7 gün sonra, tüm yeni TCP bağlantılarının başarısız olduğu bir durum yaşandı
- Mevcut bağlantılar ve ICMP (
ping) normal çalışıyordu ancak yeni TCP soketi oluşturulamıyordu
- Mevcut bağlantılar ve ICMP (
- Nedeni, XNU çekirdeğindeki TCP zaman damgası sayacı (
tcp_now) taşmasıydı; monoton artış doğrulama mantığı wraparound sonrasında güncellemeyi engelleyerek dahili TCP saatini durduruyordu - TIME_WAIT bağlantılarının süresi dolmadığı için geçici portlar serbest kalmadan birikiyor ve sonuçta yeniden başlatma dışında kurtarma mümkün olmuyordu
- Yeniden başlatmadan sonra aynı sorun 49,7 günlük döngüyle tekrar ediyordu
Deney tasarımı: Taşma öncesi ve sonrası TCP davranışının karşılaştırılması
- Hipotez: Taşma sonrasında TIME_WAIT çöp toplama işlemi duruyorsa, taşma öncesi ve sonrası kısa ömürlü TCP bağlantısı oluşturma desenlerinde fark görülmelidir
- Taşma öncesi: TIME_WAIT 30 saniye sonra normal şekilde sona erer
- Taşma sonrası: TIME_WAIT sonsuza kadar sürer
- Üç aşamadan oluşan bir test betiği çalıştırıldı
- İzleme aşaması: Taşmadan 35 dakika önceden 5 dakika öncesine kadar TIME_WAIT sayısı 10 saniye aralıklarla kaydedildi
- Patlama aşaması: Taşma öncesi ve sonrası 10 dakika boyunca her 2 saniyede yaklaşık 15 kısa TCP bağlantısı oluşturuldu
- Gözlem aşaması: Bağlantı oluşturma durdurulduktan sonra TIME_WAIT değişimi izlendi
Sonuçlar: Taşmadan sonra TIME_WAIT birikmesi
- Taşma öncesinde TIME_WAIT sayısı 0 ile 200 arasında istikrarlı biçimde dönüyor, normal geri toplama davranışı doğrulanıyordu
- Taşmadan hemen sonra TIME_WAIT sayısı sürekli artmaya başladı ve artık süresi dolmuyordu
- Machine B'de 2.828 TIME_WAIT bağlantısından hiçbiri 84 saniye sonra bile geri toplanmadı ve sonrasında da birikmeye devam etti
- Machine A'de de manuel kontrolde TIME_WAIT sayısının monoton biçimde arttığı ve kurtarılamaz durumda olduğu görüldü
Kök neden: XNU çekirdeğinde tcp_now 32 bit taşması
tcp_now,bsd/netinet/tcp_var.hiçinde tanımlanan, açılıştan sonra geçen süreyi izleyen milisaniye tabanlı 32 bit sayaçtırcalculate_tcp_clock()işlevinde(uint32_t)now.tv_sec * 1000işlemi 49,7 gün sonrasında azami değeri aşıyor ve wraparound oluşuyorif (tmp < current_tcp_now)koşulu nedeniyle taşma anında mevcut değer yeni değerden büyük hale geliyor, bu da güncellemeyi engelliyor vetcp_now'u kalıcı olarak durduruyor- TIME_WAIT süre sonu kontrolü
tcp_nowtemel alınarak yapıldığından, saat durduğunda süre sonu koşulu her zaman yanlış kalıyor ve geri toplama imkânsız hale geliyor
Zincirleme etki: TCP'nin tüm işlevinin durmasına yayılması
- Birkaç dakika sonra: TIME_WAIT geri toplama durur, kısa bağlantıların yoğun olduğu iş yüklerinde kademeli sorunlar başlar
- Birkaç saat sonra: Binlerce TIME_WAIT birikir, geçici port tükenmesi yaşanır
- Portlar tükendikten sonra: Yeni TCP bağlantıları SYN_SENT durumunda başarısız olur, yalnızca mevcut bağlantılar ayakta kalır
- CPU yükü keskin biçimde artar: Çekirdek TIME_WAIT kuyruğunu sürekli tararken yük artar
- Sonuç olarak TCP tamamen felç olur, yalnızca ICMP normal çalışır
- Tek kurtarma yöntemi yeniden başlatmadır; ardından 49,7 günlük sayaç yeniden başlar
Ek kanıtlar ve ilgili vakalar
- RFC 7323, 1 ms birimindeki 32 bit zaman damgasında işaret bitinin yaklaşık her 24,8 günde bir wrap yaptığını açıkça belirtir
- macOS'teki durum ise tam 32 bit taşmasıdır (49,7 gün) ve RFC'de ele alınan uzak zaman damgası sorunundan farklı, yerel bir çekirdek kusurudur
- Apple toplulukları ve açık kaynak projelerinde aynı semptomlar çok kez raporlandı
- TCP bağlantısı kurulamıyor,
pingnormal çalışıyor, yalnızca yeniden başlatma çözüyor, birkaç haftalık çalışma sonrasında ortaya çıkıyor - Podman issue #12495 gibi kayıtlarda aynı desen görülebiliyor
- TCP bağlantısı kurulamıyor,
- Ortak noktalar: Yalnızca TCP başarısız, ICMP normal, yeniden başlatma gerekiyor, birkaç haftalık döngülerle ortaya çıkıyor
Etki alanı
- 49 gün 17 saatten uzun süre kesintisiz çalışan macOS sistemlerde görülebilir
- Sıradan kullanıcılar düzenli güncellemeler nedeniyle yeniden başlattığından etkisi düşüktür
- Yüksek riskli ortamlar
- Uzun süre çalışan sunucu filoları
- macOS tabanlı CI/CD build sunucuları
- Mac Pro iş istasyonları
- Uzak yönetilen colocation Mac'ler
- Build farm ve test altyapısı için Mac mini kümeleri
Yeniden üretim adımları
- Açılış zamanından hareketle taşmanın beklenen anını hesaplayın
- Taşma öncesi ve sonrasında TIME_WAIT sayısını izleyin
- Taşma anında çok sayıda kısa TCP bağlantısı oluşturun
- 2 dakika sonra TIME_WAIT sayısı azalmıyorsa hata başarıyla yeniden üretilmiş demektir
9,5 saat sonra gözlemlenen sistem durumu
- TIME_WAIT bağlantılarından tek bir tanesi bile geri toplanmadı ve sayı artmaya devam etti
- SYN_SENT durumundaki başarısız bağlantılar 3.000'in üzerine çıktı
- Yalnızca mevcut bağlantılar korunuyor, yeni bağlantılar kurulamıyordu
- Machine B'nin ortalama yükü 49,74 seviyesine kadar yükseldi; çekirdek TIME_WAIT kuyruğunu tararken aşırı CPU tüketiyordu
Sonuç
- Tek bir 32 bit tamsayı ve
if (tmp < current_tcp_now)koşulu, 49,7 gün sonra TCP'nin tamamını durduran bir saatli bomba gibi çalışıyor - Bu, geliştirme, test ve kod inceleme aşamalarında fark edilmesi zor; ancak gerçek üretim ortamında ortaya çıkan bir kusur türü
- Photon, birden fazla sunucuda aynı durumu yeniden üretti ve taşma öncesinde normal geri toplama, sonrasında ise TIME_WAIT birikmesi açık biçimde doğrulandı
tcp_nowdurduğunda çekirdeğin TCP saati de duruyor; sistem yüzeyde normal görünse de tüm TCP portları tükeniyor- Uzun süre çalışan macOS sistem yöneticilerinin 49 gün 17 saat 2 dakika 47 saniye eşiğini akılda tutması ve yeniden başlatma döngüsünü ayarlaması ya da çekirdek düzeltilene kadar periyodik yeniden başlatma yapması gerekiyor
- Photon şu anda yeniden başlatma olmadan
tcp_now'u kurtaran bir geçici çözüm geliştiriyor
1 yorum
Hacker News yorumları
iMac’imin bazen hiçbir bağlantı kuramamasının nedenini ancak şimdi anladım
Bunun uptime yüzünden olduğunu hiç bilmiyordum
Yazıyı okurken bunun yapay zeka tarafından yazıldığı hissi çok güçlüydü; Apple’a gerçekten sorulup sorulmadığını merak ettim
Elbette hata önemli ama çok fazla abartılı ifade varmış gibi geldi
Çoğu kullanıcı büyük olasılıkla neredeyse hiç etkilenmeyecek
Mac’i uyku moduna alırsanız TCP stack sıfırlandığı için bu sorundan kaçınmak da mümkün olabilir
Sonuçta Apple bunu düzeltecektir ama şu anda panik yapılacak bir durum değil
Otomatik uyku kapalı bir MacBook yaklaşık 50 gündür açıktı ve ping çalışmasına rağmen TCP bağlantılarının hiç kurulmaması durumu vardı
Wi‑Fi’ı değiştirmek ya da kablolu bağlantıya geçmek de çözmedi; yeniden başlatınca hemen normale döndü
“Yeniden başlatmadan daha iyi bir alternatif çözüm geliştiriyorum; o zamana kadar düzenli olarak yeniden başlatın” dediği söyleniyor
Böyle zamanlar yeniden başlatmak için iyi bir an oluyor
Bu aralar yapay zekayla yazılmış blog yazılarını okumak çok zor
Üslup doğal değil ve asıl noktaya gelmesi çok uzun sürüyor
tcp_nowsaatinin overflow olmasına rollover ile izin vermiyor“50 gün boyunca test edecek geliştirici olmaz” sözüne katılmıyorum
Pratikte zamanı hızlandırarak simülasyon testi yapmak yeterli
Böyle bir durumda
calculate_tcp_clockgibi bir fonksiyonu değiştirip doğrulama için uptime’ı argüman olarak geçirmek mümkün olurduBu hata yalnızca OpenClaw’ı değil, tüm TCP bağlantılarını etkiliyor
macOS uptime’ı 49,7 günü geçince tüm TCP bağlantıları etkilenmeye başlıyor
Bende birkaç macOS cihazı 600–1000 günden uzun süredir açık ve TCP bağlantıları normal şekilde zaman aşımına uğruyor
Kernel sürümleri sırasıyla 20.6.0 ve 17.7.0
Bu yüzden bu hatanın yalnızca belirli bir sürümden sonra ortaya çıktığı anlaşılıyor
tcp_nowdeğeri overflow’dan hemen önce takılı kalıyor ve yanlış wraparound nedeniyle yapılan zamanlayıcı hesabı negatife dönerek karşılaştırmayı bozuyorKısa bir süre için TIME_WAIT bağlantıları birikebilir ama asıl yazı gereğinden fazla tepki veriyordu ve LLM tarafından yazılmış gibi görünüyordu
İlgili GitHub bağlantısı
Bu tür sorunlar farklı yazılımlarda tekrar tekrar görülüyor
Eskiden Guild Wars sunucularında da benzer bir durum olmuştu; overflow’u hızla tetiklemek için
GetTickCount()üzerine belirli bir değer ekleyerek test etmişlerdiBu hata Windows 95’in 49,7 günlük hatasını hatırlatıyor
İlgili yazı
OpenClaw ile bu hata arasında nasıl bir bağlantı olduğunu merak ediyorum
Bu sorun Linux kernel scheduler’daki 208 günlük hatayı hatırlatıyor
Referans bağlantı