1 puan yazan GN⁺ 21 일 전 | 1 yorum | WhatsApp'ta paylaş
  • 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
  • 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ı
    1. İzleme aşaması: Taşmadan 35 dakika önceden 5 dakika öncesine kadar TIME_WAIT sayısı 10 saniye aralıklarla kaydedildi
    2. 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
    3. 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.h içinde tanımlanan, açılıştan sonra geçen süreyi izleyen milisaniye tabanlı 32 bit sayaçtır
  • calculate_tcp_clock() işlevinde (uint32_t)now.tv_sec * 1000 işlemi 49,7 gün sonrasında azami değeri aşıyor ve wraparound oluşuyor
  • if (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 ve tcp_now'u kalıcı olarak durduruyor
  • TIME_WAIT süre sonu kontrolü tcp_now temel 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, ping normal ç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
  • 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_now durduğ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

 
GN⁺ 21 일 전
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

    • Ben de bu sorunu yaşamış olabilirim
      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ü
    • Apple’a sorulmamış; blog yazarı bunu kendisi düzeltmeye çalışıyor gibi görünüyor
      “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
    • Ben de Mac Mini’mi 7/24 açık tutuyorum; bazen ağ durursa Wi‑Fi adaptörünü kapatıp açmak sorunu çözüyor
      Böyle zamanlar yeniden başlatmak için iyi bir an oluyor
    • Gerçekten Apple’a bildirilmiş ve iç sistemlerine kaydedildiği söyleniyor
  • 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

    • Ben de aynı fikirdeyim. Yapay zekayla yazılmış yazıları okumak yorucu oluyor ve odaklanamıyorum
    • Yapay zekanın özetlediği hâliyle olay basit: Mac, tcp_now saatinin 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

    • Linux kernel’de bu tür sorunları yakalamak için jiffies sayacı önyükleme anında overflow’a çok yakın bir değerle başlatılır deniyor
    • macOS donanım saatini kullanıyor ve bu saat uyku sırasında duruyor
      Böyle bir durumda calculate_tcp_clock gibi bir fonksiyonu değiştirip doğrulama için uptime’ı argüman olarak geçirmek mümkün olurdu
    • Bu yaklaşım video oyunu testlerinde de sık kullanılır
  • Bu hata yalnızca OpenClaw’ı değil, tüm TCP bağlantılarını etkiliyor

    • Tek tek bağlantıların uzun süre açık kalması gerekmiyor
      macOS uptime’ı 49,7 günü geçince tüm TCP bağlantıları etkilenmeye başlıyor
    • “Demek ki artık OpenClaw dünyadaki en önemli şey gibi görünüyor” diye şaka yapanlar da vardı
  • 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

    • Analize göre tcp_now değ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ı bozuyor
      Kı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
    • Gerçekten de bu hata geçen yıl macOS 26’da yeni eklenen koddan kaynaklanıyormuş
      İ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şlerdi

    • Overflow’la uğraşan sistemlerde başladıktan hemen sonra overflow’u tetikleyip test etmek gerekir
  • Bu 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ı