5 puan yazan GN⁺ 2025-01-24 | 4 yorum | WhatsApp'ta paylaş
  • EdgeDB, ağ I/O'sunu Python'dan Rust'a taşırken reqwest tabanlı yeni HTTP fetch testinin yalnızca ARM64 CI'da takılmış gibi göründüğünü, ama aslında çöktüğünü fark etti
  • Çekirdek dökümü analizi, sorunun yeni HTTP kodunda değil libc içindeki getenv() çağrısında olduğunu gösterdi; ortam değişkeni dizisini dolaşırken hatalı 0x220 işaretçisini okumaya çalışıp başarısız oluyordu
  • Başka bir thread, openssl-probe yolunda SSL_CERT_FILE ve SSL_CERT_DIR ayarlarken setenv() environ dizisini yeniden tahsis etti; aynı anda Python hata işleme yolu getenv() çağırınca yarış durumu oluştu
  • Rust kodunda açık bir unsafe yoktu, ancak std::env::set_var() global ortamı değiştirirken bu işlem Rust içi kilitle, diğer runtime'larla veya doğrudan libc çağrılarıyla senkronize edilmiyordu
  • Çözüm, Linux'ta reqwestin rust-native-tls/openssl backend'i yerine rustls kullanmaya geçmek oldu; Rust 2024 edition ve glibc de bu tür sorunları azaltacak yönde değişiyor

Yalnızca ARM64 CI'da ortaya çıkan çöküş

  • EdgeDB, ağ I/O kodunun önemli bir bölümünü Python'dan Rust'a taşırken yeni bir HTTP fetch özelliği geliştiriyordu
  • HTTP istemci kütüphanesi olarak reqwest kullanıldı; özellik yerelde ve x86_64 CI runner'larında geçmesine rağmen ARM64 CI runner üzerinde aralıklı olarak başarısız oluyordu
  • Başta test runner'ın süresiz takıldığı sanıldı; CI loglarında hata olmadan tek bir test saatlerce çalışıyor görünüyor ve sonunda timeout'a düşüyordu
  • İlk hipotez, Intel ile ARM64 arasındaki bellek modeli farkları idi
    • Intel nispeten daha katı bir bellek modeline sahiptir ve bellek yazmaları için tüm işlemcilerin uzlaştığı küresel bir sıra vardır
    • ARM ise daha zayıf sıralı bir bellek modeline sahiptir; yazmalar farklı thread'lere farklı sıralarda görünebilir

Docker CI ortamında çekirdek dökümünü izleme

  • Gece CI makineleri Amazon AWS üzerinde çalıştığından, konteyner dışındaki gerçek root kullanıcıyla bağlanıp dmesg ve sistem logları görülebiliyordu
  • Konteynerin içinde ve dışında takılmış gibi görünen PID arandı ama ilgili süreç bulunamadı; böylece bunun deadlock değil çöküş olduğu anlaşıldı
  • Docker konteyneri süreç namespace'i kullandığından çekirdek dökümü Docker host'una iletildi ve journalctl içinde python3 sürecine ait çekirdek dökümü görüldü
  • Başta çekirdek gdb ile açıldığında, konteyner içindeki .so dosyaları olmadığından backtrace kullanışsızdı
  • Konteynerden /lib, /usr vb. kopyalanıp gdb içinde solib-absolute-prefix ayarlandıktan sonra, çöküş noktasının libc.so.6 içindeki getenv() olduğu doğrulandı

getenv() tarafından okunan bozuk ortam değişkeni işaretçisi

  • Tam backtrace şu akıştaydı: getenv()__dcigettext()strerror_r()strerror()PyErr_SetFromErrnoWithFilenameObjects()
  • Yeni HTTP kodu doğrudan çökmemişti; Python, errno tabanlı bir istisna üretirken gettext ile ilgili bir yol üzerinden getenv() çağırıyordu
  • GLIBC 2.17'deki getenv() uygulaması, POSIX environ yapısını bir char ** listesi olarak dolaşır ve son NULL işaretçisine kadar ortam değişkeni string işaretçilerini inceler
  • Disassembly ve register durumuna göre getenv(), x19 = 0x220 adresinden bayt okumaya çalışırken çöktü
    • 0x220 açıkça geçersiz bir bellek adresiydi
    • environ'ın kendisi incelendiğinde mevcut ortam değişkeni listesi tutarlı görünüyordu

Neden: setenv() ile getenv() arasında yarış durumu

  • setenv() çok thread'li ortamlarda güvenle çağrılabilecek bir fonksiyon değildir; libc içindeki getenv() tarafında garip çöküşlere yol açtığı daha önce de defalarca yeniden keşfedildi
  • Disassembly ile C kodu karşılaştırıldığında, x20'nin environ dizisini gezen ep işaretçisine karşılık geldiği görüldü
  • Çöküş anında x20 değeri 0x248b5000 idi; o sıradaki environ ise 0x28655750 adresindeydi, yani yaklaşık 60 MB ilerideydi
  • Eski ortam dizisinin çevresindeki bellek ile güncel environ karşılaştırılınca son farkın SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt ve SSL_CERT_DIR=/etc/ssl/certs girdilerinde olduğu görüldü
  • Başka bir thread setenv() çağrısı sırasında environ'ı taşımıştı ve getenv() eski ortam dizisini okumaya devam ederek bir use-after-free durumuna düşmüştü

openssl-probe ve TLS backend bağlantısı

  • rust-native-tls ile ilgili eski bir issue'da, openssl-probe'un sistem sertifikalarını bulmak için SSL_CERT_FILE ve SSL_CERT_DIR ortam değişkenlerini ayarladığına dair ipucu bulundu
  • Linux'ta rust-native-tlsin openssl backend'i kullanıldığında bu yol çağrılıyordu
  • Sorunlu openssl-probe kodu, açık bir unsafe olmadan env::set_var() ile şu iki ortam değişkenini ayarlıyordu
    • SSL_CERT_FILE
    • SSL_CERT_DIR
  • Bu birleşim yüzünden unsafe içermeyen Rust kodu, aynı süreç içindeki libc kullanımıyla kötü etkileşime girerek çöküş üretti

Neden ARM64 Linux'ta yeniden üretilebildi

  • Bu çöküşün oluşması için setenv()'in realloc ile ortam dizisini taşıdığı anda başka bir thread'in getenv() çağırması gerekiyordu
  • Yeniden üretim için aynı anda birçok koşulun sağlanması gerekiyordu
    • Ortam değişkeni sayısı realloc tetikleyecek düzeyde olmalıydı
    • İlgisiz bir I/O hatası asyncio tarafından yakalanmalıydı
    • Python hata işleme yolu, LANGUAGE ortam değişkenini almak için tam o anda getenv() çağırmalıydı
  • Hatalı 0x220 değeri, 64 bit word cinsinden eski ortam boyutuna yakındı
    • 0x220 / 8 = 68
    • Bu değer eski ortam bloğunun sonundaki NULL yerine yazılmıştı ve sistem malloc'unun free block boyutunu göstermek için kullandığı bir değer gibi görünüyordu
  • Bu kadar çok önkoşul gerektiği için, tek bir platformda oldukça yeniden üretilebilir olması bile şanslı bir durumdu

ARM64 disassembly'de görülen ipucu

  • getenv() disassembly'sinde x20'nin değiştiği nokta ilk başta açık görünmediği için kafa karıştırıcıydı
  • Kilit nokta, AArch64'ün pre-index addressing mode özelliğiydi
  • ldr x19, [x20, #8]! şu şekilde çalışır
    • x19 = *(x20 + 8)
    • x20 = x20 + 8
  • Bu adresleme modu yüzünden x20, solda açıkça yazılmasa da ortam değişkeni işaretçi dizisini dolaşıyordu

Uygulanan düzeltme ve ilgili projelerdeki değişiklikler

  • Sonunda Linux'ta reqwestin rust-native-tls/openssl backend'i yerine rustls kullanmaya geçme kararı alındı
  • Başta native TLS backend'in seçilme nedeni, Python kodu Rust'a taşınırken iki TLS motorunu aynı anda paketlemekten kaçınmaktı
  • Bu sorundan sonra, kısa vadede iki TLS motorunu birlikte taşımak kabul edilebilir bulundu
  • Alternatif olarak try_init_ssl_cert_env_vars() çağrısının ilk kez Python'un GIL'i elde tutulurken yapılması da mümkündü
    • Rust'ta, Rust kodunun kendi arasında ortam okuma ve yazma yarışlarını önleyen dahili bir kilit var
    • Ancak bu kilit, başka dillerin doğrudan libc kullanmasını engellemez
    • GIL tutulursa en azından Python thread'leriyle yarış engellenebilir
  • Rust projesi bu sorunun zaten farkında ve 2024 edition'da ortam setter fonksiyonlarını unsafe yapmayı planlıyor
  • glibc projesi de yakın zamanda realloc kullanımından kaçınıp eski ortam dizilerini sızdırarak getenv()in thread safety düzeyini artıran değişiklikler ekledi

4 yorum

 
carnoxen 2025-01-24

Setenv thread-safe değil ve C bunu düzeltmek istemiyor

Setenv fonksiyonu yine sorun çıkarıyor.

 
y15un 2025-01-24

Ben başlığı şöyle yazardım: 'C stdlib'in thread-unsafe olması, o güvenli denilen Rust'u bile kurtaramaz'. :)

 
halfenif 2025-01-24

Kesinlikle anladım.

 
GN⁺ 2025-01-24
Hacker News yorumları
  • Buradaki en büyük nokta, Rust’ın bir sonraki edition’ında ortam değişkeni ayarlama fonksiyonunun unsafe olacağı.
    Şansımız yaver giderse, bu tür çökmelere yol açan crate’lere kadar etkisi iner gibi görünüyor; bu arada upstream’de şu issue açıldı: https://github.com/alexcrichton/openssl-probe/issues/30

    • Ancak temel sorun, yani getenv ile setenv veya unsetenv’in farklı thread’lerden güvenli biçimde çağrılamaması gerçekten düzeltilmiş olmuyor.
      Güvenilir tek çözüm, bu fonksiyonların mutlaka bir mutex alacak şekilde değiştirilmesi gibi görünüyor.
    • Kütüphane yazarının “bugünlerde bu soruna en iyi çözüm rustls gibi bir kütüphane kullanmak ve bu crate’i artık kullanmamak” değerlendirmesi makul; bunu görmek sevindirici.
      Ne yazık ki ekosistem öyle değil: https://github.com/seanmonstar/reqwest/blob/master/Cargo.tom...
    • İnsanlar ____UNSAFE_payattention__nevermindthatthisappears50timesinthisfile___ gibi blokları ve önekleri görmezden gelecek şekilde eğitilmiş durumda.
      Web framework’lerinde de benzer; Vue’da v-html yönergesi, React’te ise dangerouslySetInnerHTML var. Bu açıdan Vue’nun kesinlikle daha iyi olduğunu düşünüyorum.
  • Rust standart kütüphanesindeki set_var ve remove_var, bir sonraki edition olan 2024 edition’da artık düzgün biçimde unsafe {} bloğu gerektirecek.
    Belgeler de artık güvenlik sorunundan bahsediyor; ama en başta bu fonksiyonları safe yapmak bir hataydı ve daha yüksek seviyeli dillerin de yaptığı bir hataydı.
    https://doc.rust-lang.org/stable/std/env/fn.set_var.html
    glibc’de, ortamın değiştirildiği daha fazla durumda getenv’i güvenli hale getiren bir patch var; ancak C hâlâ environ’a doğrudan erişebildiği için, değişiklik yapılan durumlarda tamamen güvenli olamaz: https://github.com/bminor/glibc/commit/7a61e7f557a97ab597d6f...

    • glibc’nin artık eski sürümleri tutması ve üstel büyütme politikası benimsemesi şaşırtıcı.
      Aktif ortam değişkeni başına amorti edilmiş olarak sabit büyüklükte bir bellek sızıntısı oluşuyor; ama değişkenin kendisinde de zaten böyle bir sızıntı var, hatta uzunluğa bağlı olarak değişiyor ve artık kullanılmayan değerleri de içerdiği söyleniyor.
      API açısından doğru programlarda bile bunun yüzünden belleğin sınırsız büyüdüğü patolojik kullanım senaryoları mutlaka vardır gibi geliyor.
      API’yi birden fazla thread’den kullanarak kuralları ihlal eden programları düzeltmek için, API’ye uyan programlara sınırsız bellek artışı gibi bir bug sokuluyor olması ilginç ama rahatsız edici. Dogmatizmden çok pragmatizm hissi veriyor.
    • Standart kütüphane implementasyonu senkronizasyonu halledebiliyorsa neden unsafe gerektirmesi gerektiğini merak ediyorum.
  • C standart kütüphanesi bakımcıları setenv’i çok thread’li kullanıma güvenli hale getirmeye karşı çıksa bile, en azından POSIX içinde ya da önce fiilî bir standart oluşturup POSIX’in sonradan kabul etmesini sağlayarak yeni bir thread-safe API tanımlanmalı.
    Hiçbir şey yapılamamasının nedenlerini açıklamaya harcanan zamanla bu sorun düzeltilmiş olsaydı, eski setenv’in yerini alabilecek ve birçok yazılım projesinde kullanımdan kaldırılıp kaldırılabilecek bir çözüm olurdu.
    glibc’nin bu sorunu fiilen ortadan kaldırmaya yönelik değişiklik yaptığını görünce, Musl bakımcısının Musl içinde düzeltilemeyeceği yönündeki sözü de pek ikna edici gelmiyor.

    • En büyük sorun thread-safe API olmaması değil, extern char **environ;’ın var olması.
      environ herkese açık biçimde erişilebilir olduğu sürece setenv ve getenv’in kullanıldığının bile garantisi yok; çünkü ikisi zorunlu değil.
      environ kaldırılabilseydi setenv ve getenv’i thread-safe yapmak epey basit olurdu. Kaldırılamıyorsa imkânsız; yine de tam bir çözüm olmasa bile setenv ve getenv’i thread-safe yapmanın bir iyileştirme olduğu savunulabilir.
    • Ortamı argüman olarak almayan veya çalıştırılabilir dosyayı bulmak için PATH içinde arama yapan tüm exec() fonksiyonlarının da kilit gerektireceği gibi görünüyor.
    • Geriye dönük uyumlu biçimde düzeltilemeyeceği sonucuna varan uzmanlardan daha iyi bildiğiniz iddiası ikna edici değil.
  • Linux’ta ortam değişkenleriyle ilgili bir bug’a denk gelmek bir tür geçiş ritüeli gibi; diğer Unix’lerde ise tuhaf biçimde daha az sorun oluyor
    Linus ve kernel, POSIX bug’larını pratik şekilde, gerçekten patlamayacak hâle getirerek düzeltiyor; glibc’nin ise insanların sorunu biraz olsun hafifletmeye çalışmasının üzerinden onlarca yıl geçmişken hâlâ geride kalması biraz komik
    TZ gibi türlü baş ağrıları olduğu doğru, ama getenv_r() sağlanıp setenv() ile senkronize edilse ve getenv() kullanıldığında derleme/bağlama aşamasında sadece uyarı verilse bile sorunların önemli bir kısmı ortadan kalkardı
    Daha da ileri gidip ortam işaretçisini salt okunur tutan yazma sırasında kopyalama (COW) yaklaşımı bile uygulanabilirdi
    Bunun yerine sorun tek tek uygulamalara yıkıldı; uygulama yazarları bağımlılıkların ne yaptığını neredeyse hiç bilemediği için bu büyük bir hata. Uzun zaman önce benim içinde bulunduğum durum da böyleydi; o sırada kapalı kaynak kütüphane tedarikçisi de o oyuncak Unix klonu Linux’u bırakmamı söylemişti

    • “Linux’ta ortam değişkenleriyle ilgili bug var, diğer Unix’lerde daha az sorun” yargısının nasıl çıkarıldığını bilmiyorum
      Sorun implementasyonda değil, API’nin kendisinde. setenv(), unsetenv(), putenv() ve özellikle environ, çok iş parçacıklı programlarda doğası gereği güvenli değil
      getenv_r() de tamamen kurtaramaz. Çünkü bir iş parçacığı bir ortam değişkeninin eski değerini sağlanan arabelleğe kopyalarken başka bir iş parçacığı setenv() çağırabilir
      Elbette getenv() ile aldıktan sonra başka bir iş parçacığının setenv() çağırıp o belleği geçersiz kılması durumunu getenv_r() düzeltir; ancak API’yi bozan diğer çağrıları engellemenin bir yolu yok
      libc, getenv()/setenv()/putenv()/unsetenv() içinde mutex alarak bazı sorunları hafifletebilir; ama getenv()in döndürdüğü değerin çağıran kodun kullanabileceği kadar uzun süre geçerli kalacağını libc’nin garanti etmesinin hâlâ bir yolu yok
      environa doğrudan erişimi güvenli hâle getirmenin de iyi bir yolu yok. environ iş parçacığına yerel yapılabilir, ama o zaman her iş parçacığının ortam görünümü kalıcı olarak birbirinden sapabilir ve getenv_r() çağrısının sonucu ile environu doğrudan kontrol etmenin sonucu farklı olabilir
      Burada geriye dönük uyumluluğu korumak gerçekten zor; yalnızca fonksiyonları koruyan bir mutex eklemek bile mevcut programların anlamını değiştirip onları bozabilir
  • Daha önce setenvin berbat olduğuna dair bir yazı vardı: https://www.evanjones.ca/setenv-is-not-thread-safe.html
    Tartışması da vardı ve daha ilk yorumdan itibaren Rust’ta sorun çıkardığından bahsediliyordu: https://news.ycombinator.com/item?id=38342642

    • Bu zaten bilinen bir gerçek
      Buradaki kalan sorunların çoğu geliştirme ortamı gibi görünüyor. Amazon veri merkezindeki uzak makinelerde Docker kullanarak test etmişler ve o makine süreç çökmelerini raporlayamamış
      Üstelik konteyner içinde geri izleme almak için yeterli debug sembol bilgisi de yokmuş. İlk hatada temiz bir geri izleme alınsaydı hemen netleşirdi
      En başta neden setenv kullandıkları da ayrı bir soru
  • Bunu görünce, eski bazı meslektaşlarımın büyük inanç beslediği 12-factor app hareketi aklıma geldi. O “factor”lardan biri, uygulama yapılandırmasının ortam değişkenleriyle yapılması gerektiğiydi.
    Bunu hep biraz aptalca bulmuşumdur; çünkü yapılandırma yöntemi, düz bir ad alanında string türündeki değerleri bir sepet gibi tutan bir yapıdan ibaret.
    getenv()/setenv()/environ tehlikesini de ortam değişkenlerini yapılandırma için kullanmamak adına güçlü bir gerekçe olarak görüyorum.
    Elbette her zaman mükemmel ve iyi desteklenen bir alternatif yok. Ben yapılandırma dosyalarını tercih ediyorum; geliştirme, staging ve production değerlerinin doldurulduğu şablon yapılandırmalar da kullanılabilir. Genelde eksileri ve tuzakları olsa da YAML kullanıyorum; daha iyi bir yapılandırma dosyası biçimi olabilir ama YAML’ın ortam değişkenlerinden çok daha iyi olduğunu düşünüyorum.

    • Windows’a ve Microsoft’a karşı çok güçlü bir antipati var, ama zaman geçtikçe onların API tasarımının haklı çıktığı epey durum oluyor.
      NT’de ortam değişkenleri tiplendirilebilir ve şablonlaştırılabilir; ayrıca ad alanları olan bir yapılandırma veritabanı, yani registry de var. Gerçi uzun uzadıya ve garip.
      Üstelik MSVC, neredeyse tüm standart kütüphane fonksiyonlarının thread-safe sürümlerini sunuyor.
      Yeni C/C++ geliştiricilerinin MSVC’nin POSIX uyumluluğu eksikliğinden yakındığını sık duyuyorum, ama bunun pratikte ne anlama geldiğini pek derinlemesine düşünmüyor gibiler. Daha çok 1990’larda yazılmış C programlarıyla çapraz uyumlu olmasını istemek gibi.
    • Ortam değişkenleriyle ilgili benzer kaygılarım var. Her yerden okunabiliyor olmalarını sevmiyorum.
      Bir fonksiyonun imzasından davranışını çıkarma becerisini zedeliyor ve saf fonksiyon olabilecek birçok fonksiyonu saf olmayan hâle getiriyor.
      Herhangi bir proseste ortam değişkenlerinin kullanılamayacağını ve yalnızca bir kez, değişken bazında değil toplu olarak tek seferde okunabileceğini belirten bir dil özelliği olsaydı, onu her yerde kullanırdım.
    • getenv() kendi başına tamamen sorun değil; sorun setenv().
      Teoride, o gizemli uygulama başlamadan önce ortam zaten ayarlanmış olacağı için buna ihtiyaç olmamalı.
      Ama düz ad alanı, string değerler ve hangi kütüphane ve modüllerin içeri girdiğini bile bilmediğiniz, herkesin paylaştığı serbest bir global alan olması, setenv()in güvenlik sorunu olmasa bile iyi bir fikir değil.
    • “12-factor app”e, proses yaşadığı sürece ortamın salt okunur kabul edilmesi gerektiğini söyleyen bir ek konmalı.
      Burada insanların bahsettiği sorunların çoğu, ortamı değiştirilebilir global durum için bir anahtar-değer deposu gibi kötüye kullanma isteğinden kaynaklanıyor gibi. Bunu neden yapmak istediklerini anlamıyorum.
      JVM ortamı fiilen değişmez kabul ediyor; SoundCloud gibi Scala ve Java kullanan şirketlerin 12-factor app hareketini etkilemiş olması da mümkün. Ben ortamın değiştiği veya threading sorunu çıkardığı bir durum yaşamadım.
      Ortam değişse bile JVM başlarken oluşturulan değişmez kopya aynı kalıyor; genel Java API’siyle ortamla etkileşen kod bu değişikliği görmüyor.
      Yapılandırma dosyalarının sorunu, ayrıştırmanın proses başına yapılması. Linux/Unix’in bu kadar karmakarışık olmasının nedeni de bu. Her aracın yapılandırma gelenekleri ve mekanizmaları farklı, bir standart yok.
      Docker ekosisteminde, konteynerin içinde ne yaptığınız bir yana, dış dünyayla arayüz ya bir volume mount edip her uygulamanın karmaşık yapılandırma yöntemini izlemek ya da sadece ortam değişkenlerini kullanmak oluyor.
      Bugün Docker ile çalıştırılan modern yazılımların çoğu, davranışı tamamen ortam üzerinden kontrol edilebilecek kadar Docker dostu ve bu çoğu durumda yeterli.
      Docker Compose veya Kubernetes kullanırsanız, prosesi başlatma biçimini tanımlayan ortam değişkenleri listesini bir YAML dosyası olarak tutarsınız; böylece bir ölçüde istediğiniz yapı ortaya çıkar. YAML’ı sevmiyorum ama yeterince iş görüyor; sözdizimi sorunlarının gününüzü mahvetme ihtimali yüksek olsa da alternatifler de sorunsuz değil.
    • Bu aslında ayrı bir sorun. Ortam değişkenlerini yapılandırma olarak okuyup sonra bir daha dokunmazsanız tamamen güvenli.
      Ben de 12-factor app tarzını kullanıyorum, ama uygulamaya girdikten sonra ortam değişkenlerini ve verileri doğrulayıp saklıyorum. Ondan sonra hiçbir sorun yok.
  • Göze pek çarpmayan bir bug’ın izini süren harika bir yazı.
    Aralıklı bug, mimariye özgü durumlar, bağımlılıkların içine gizlenmiş olması, Rust, Python GIL, gettext; hepsi vardı.
    Böyle ayrıntılı sorun giderme raporları, insanın bizzat yaşamasına en yakın kaynaklar. Bir bağımlılık onu kullanıyorken “X kullanmasaydın ya” demek kolay değil; bunu nasıl bilebilirdim ki?

  • “Gece CI makinesi Amazon AWS’de çalışıyor ve konteyner değil, gerçek root kullanıcısı kullanabilme avantajı var” derken aynı zamanda “konteynerin dışında gerekli dosyalar yok ve konteyner çok minimal olduğu için gdbyi kolayca kuramıyoruz” diyorlar.
    İnsanlar artık bulut ve konteyner olmadan yerelde build edip debug etme becerisini mi kaybetti?

    • Evet. Bulut SaaS’ın insanların anlayışını ne kadar çarpıttığı şaşırtıcı.
      Çok basit bir işi yapmak için her türlü bulut karmaşıklığı ve dağıtım katmanı gerekli hâle geldi. PC devrimini %100 geri sarıp hantal ve pahalı mainframe computing dönemine dönmüş olduk.
      Nedeni, paranın bulutta olması ve bulutun DRM olması. Yazılımı oraya koyarsanız abonelik ücreti alabilirsiniz; bundan kaçınılamaz ve kusursuz bir bağımlılığı sonsuza kadar sürdürebilirsiniz. Kullanıcının kendi verisini bile dışarı çıkaramadığı çok olur.
      Ürün optimizasyonu için gerçek zamanlı analiz yapmak da kolaylaşır.
      Bilişim mimarisi, iş modelinin aşağısında yer alır. Mainframe’in ilk kez ölmesinin nedeni internetin olmaması ve PC’nin daha ucuz olmasıydı; ama satıcıların bağımlılık yaratma gücünü de büyük ölçüde kaybetmiş olmalarıydı.
      Şimdi çok daha kârlı bir modeli yeniden canlandırmanın yolu bulundu. Kullanıcıların can sıkıcı özgürlüğü ortadan kalktı; açıkçası kullanıcılar o özgürlüğe sahip olunca çoğu zaman para da ödemiyorlar, bu da kaliteli yazılım işini ayakta tutmayı zorlaştırabiliyor.
    • Bu, yalnızca ARM’de patlayan rastgele bellek bozulması gibi bir sorun.
      Yerelde çöküşü yeniden üretememiş olmaları çok olası. Geliştirici makinelerinin çoğu x86’ydı ve orada muhtemelen çökme olmuyordu.
      Çökme yönetimini daha iyi yapmaları gerekirdi, ama onlar da bu sorunun farkında gibi ve burada ele alınan ana mesele bu değil.
    • Elbette beceriyi kaybetmedik, ama bizim makinelerde çökme olmadı.
    • Sorun çıkaran mimariyi çalıştıran bir cihaza sahip olmama ihtimaliniz yüksekse yerelde nasıl debug edeceksiniz? Zaten hatanın gerçekleştiği gerçek ortamda debug etmek çok daha hızlı.
  • Değiştirilebilir küresel durum kötüdür. Dost olan, dostunun değiştirilebilir küresel durum kullanmasına izin vermez
    Ortam değişkenlerinden nefret ediyorum. Bu “Linux usulü” ama veba gibi kaçınıyorum. Şiddetle tavsiye ederim
    libc korkunç ve dünyanın artık bunu geride bırakması gerekiyor

    • Ortam değişkenleri süreç içinde salt okunur kabul edilirse sorun yok
    • “Değiştirilebilir küresel durum kötüdür” deniyorsa CPU ve RAM’i de çöpe atmak gerekir
    • Alternatif olarak ne önerildiğini merak ediyorum
      Sorun Linux, değiştirilebilir küresel durum ya da kaynaklar, libc de değil
      Sorun, iş yerinde işi düzgün yapmak için zaman verilmemesi. Örneğin sorun patlamadan önce GDB ile yakalamak için yöneticinizin kodu ve o kodun dokunduğu her şeyi ısrarla debug edip geriye doğru iz sürmeye zaman tanıması gerekir
      Yarı pişmiş koda çok fazla para akıyor. Üzücü ama gerçek
    • libc dünyayı bilgi çağına itti
    • Tercih edilen alternatifin ne olduğunu merak ediyorum
  • Bu tür sorunlar o kadar çoktu ki sonunda LD_PRELOAD ile getenv / setenv / putenv’i yamaladım

    • Az önce glibc’ye giren gibi, ortamı sızdıran sabit bir uygulama şeklinde mi yaptın?