5 poin oleh GN⁺ 2025-01-24 | 4 komentar | Bagikan ke WhatsApp
  • Saat EdgeDB memindahkan I/O jaringan dari Python ke Rust, pengujian HTTP fetch baru berbasis reqwest tampak seperti macet hanya di CI ARM64, tetapi sebenarnya mengalami crash
  • Analisis core dump menunjukkan titik masalahnya bukan pada kode HTTP baru, melainkan di dalam getenv() milik libc, yang gagal saat mencoba membaca pointer tidak valid 0x220 ketika menelusuri array variabel lingkungan
  • Thread lain menyetel SSL_CERT_FILE dan SSL_CERT_DIR lewat jalur openssl-probe, sehingga setenv() mengalokasikan ulang environ; pada saat yang sama jalur penanganan error Python memanggil getenv(), memicu race condition
  • Tidak ada unsafe eksplisit di kode Rust, tetapi saat std::env::set_var() mengubah environment global, sinkronisasi dengan lock internal Rust tidak mencakup runtime lain atau pemanggilan langsung ke libc
  • Solusinya adalah beralih di Linux dari backend rust-native-tls/openssl milik reqwest ke rustls, dan Rust edisi 2024 serta glibc juga sedang berubah untuk mengurangi kelas masalah ini

Crash yang hanya terlihat di CI ARM64

  • EdgeDB sedang membuat fitur HTTP fetch baru sambil memindahkan sebagian besar kode I/O jaringan dari Python ke Rust
  • Mereka menggunakan reqwest sebagai pustaka klien HTTP, dan fitur itu lolos di mesin lokal maupun runner CI x86_64, tetapi gagal sesekali di runner CI ARM64
  • Awalnya terlihat seperti test runner macet tanpa batas, dan di log CI satu pengujian terus tampak berjalan tanpa error hingga timeout beberapa jam kemudian
  • Hipotesis awal adalah perbedaan model memori antara Intel dan ARM64
    • Intel memiliki model memori yang relatif ketat, dengan urutan total yang disepakati semua prosesor untuk penulisan memori
    • ARM memiliki model memori dengan urutan yang lebih lemah, sehingga penulisan bisa terlihat dalam urutan berbeda oleh thread yang berbeda

Melacak core dump di lingkungan Docker CI

  • Mesin CI malam hari berjalan di Amazon AWS, sehingga bisa masuk sebagai pengguna root nyata di luar container untuk melihat dmesg dan log sistem
  • PID yang tampak macet dicari dari dalam dan luar container, tetapi prosesnya tidak ada, sehingga terungkap bahwa ini bukan deadlock melainkan crash
  • Karena container Docker memakai process namespace, core dump diteruskan ke host Docker, dan di journalctl terlihat core dump dari proses python3
  • Saat pertama membuka core dengan gdb, backtrace tidak berguna karena file .so di dalam container tidak ada
  • Setelah menyalin /lib, /usr, dan lainnya dari container serta mengatur solib-absolute-prefix di gdb, dipastikan bahwa titik crash ada di getenv() pada libc.so.6

Pointer variabel lingkungan rusak yang dibaca getenv()

  • Backtrace lengkapnya adalah alur getenv()__dcigettext()strerror_r()strerror()PyErr_SetFromErrnoWithFilenameObjects()
  • Bukan kode HTTP baru yang crash secara langsung, melainkan Python memanggil getenv() lewat jalur terkait gettext saat sedang membuat exception berbasis errno
  • Implementasi getenv() di GLIBC 2.17 menelusuri environ milik POSIX sebagai daftar char **, memeriksa pointer string variabel lingkungan hingga pointer NULL terakhir
  • Dari disassembly dan status register, getenv() crash saat mencoba membaca byte dari alamat x19 = 0x220
    • 0x220 jelas merupakan alamat memori yang tidak valid
    • Saat environ sendiri diperiksa, daftar variabel lingkungan saat ini tampak konsisten

Penyebab: race condition antara setenv() dan getenv()

  • setenv() bukan fungsi yang aman dipanggil di lingkungan multithread, dan masalah crash aneh di getenv() milik libc sudah berulang kali ditemukan kembali
  • Dengan mencocokkan disassembly dan kode C, diketahui bahwa x20 sesuai dengan pointer ep yang berjalan menelusuri array environ
  • Saat crash, x20 bernilai 0x248b5000, sedangkan environ saat ini berada di 0x28655750, sekitar 60MB lebih jauh
  • Setelah membandingkan memori di sekitar array environment lama dengan environ saat ini, perbedaan terakhir muncul pada entri SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt dan SSL_CERT_DIR=/etc/ssl/certs
  • Thread lain tampaknya memindahkan environ saat memanggil setenv(), dan getenv() terus membaca array environment lama, sehingga terjadi use-after-free

Kaitan dengan openssl-probe dan backend TLS

  • Dari issue lama terkait rust-native-tls, ditemukan petunjuk bahwa openssl-probe menyetel variabel lingkungan SSL_CERT_FILE dan SSL_CERT_DIR untuk menemukan sertifikat sistem
  • Di Linux, jalur ini dipanggil saat memakai backend openssl dari rust-native-tls
  • Kode openssl-probe yang bermasalah menyetel dua variabel lingkungan itu lewat env::set_var() tanpa unsafe eksplisit
    • SSL_CERT_FILE
    • SSL_CERT_DIR
  • Kombinasi ini membuat kode Rust tanpa unsafe berinteraksi buruk dengan penggunaan libc lain dalam proses yang sama, hingga menyebabkan crash

Mengapa bisa direproduksi di Linux ARM64

  • Crash ini hanya terjadi jika setenv() memindahkan array environment dengan realloc tepat ketika thread lain memanggil getenv()
  • Untuk mereproduksinya, beberapa syarat harus terjadi bersamaan
    • Jumlah variabel lingkungan harus pas sehingga memicu realloc
    • Kegagalan I/O yang tidak terkait harus tertangkap oleh asyncio
    • Jalur penanganan error Python harus memanggil getenv() untuk mengambil variabel lingkungan LANGUAGE tepat pada saat yang sama
  • Nilai salah 0x220 dekat dengan ukuran environment lama dalam satuan word 64-bit
    • 0x220 / 8 = 68
    • Nilai ini tampaknya menimpa NULL penutup blok environment lama, kemungkinan sebagai penanda ukuran free block oleh malloc sistem
  • Karena butuh banyak prasyarat, fakta bahwa bug ini cukup bisa direproduksi di satu platform justru merupakan keberuntungan tersendiri

Petunjuk yang terlihat dari disassembly ARM64

  • Di disassembly getenv(), sempat membingungkan karena titik perubahan x20 tidak terlihat jelas
  • Kuncinya adalah mode pengalamatan pre-index pada AArch64
  • ldr x19, [x20, #8]! bekerja seperti ini
    • x19 = *(x20 + 8)
    • x20 = x20 + 8
  • Karena mode pengalamatan ini, x20 tetap menelusuri array pointer variabel lingkungan meski tidak ditulis eksplisit di sisi kiri

Perbaikan yang diterapkan dan perubahan di proyek terkait

  • Pada akhirnya diputuskan untuk bermigrasi di Linux dari backend rust-native-tls/openssl milik reqwest ke rustls
  • Alasan awal memilih backend TLS native adalah untuk menghindari membawa dua engine TLS sekaligus saat memindahkan kode Python ke Rust
  • Setelah masalah ini, diputuskan bahwa membawa dua engine TLS dalam jangka pendek masih dapat diterima
  • Alternatif lain adalah memastikan pemanggilan pertama try_init_ssl_cert_env_vars() dilakukan saat memegang GIL milik Python
    • Rust memiliki lock internal untuk mencegah race saat kode Rust membaca dan menulis environment sesamanya
    • Namun lock itu tidak melindungi kasus ketika kode bahasa lain langsung memakai libc
    • Dengan memegang GIL, setidaknya race dengan thread Python bisa dicegah
  • Proyek Rust sendiri sudah menyadari masalah ini, dan di edisi 2024 berencana menjadikan fungsi setter environment sebagai unsafe
  • Proyek glibc juga baru-baru ini menambahkan perubahan untuk meningkatkan thread safety getenv() dengan menghindari realloc dan membocorkan array environment lama

4 komentar

 
carnoxen 2025-01-24
 
y15un 2025-01-24

Saya akan menulis judulnya sebagai, "Ketidakamanan thread pada stdlib C bahkan tidak bisa diselamatkan oleh Rust yang katanya aman." :)

 
halfenif 2025-01-24

Saya benar-benar memahaminya.

 
GN⁺ 2025-01-24
Komentar Hacker News
  • Poin terbesar di sini adalah bahwa pada edisi Rust berikutnya, fungsi pengaturan variabel lingkungan akan menjadi unsafe
    Kalau beruntung, dampaknya mungkin akan menjalar sampai ke crate-crate yang memicu crash seperti ini, dan sementara itu issue upstream sudah diajukan di https://github.com/alexcrichton/openssl-probe/issues/30

    • Namun masalah mendasarnya, yaitu bahwa getenv dan setenv atau unsetenv tidak bisa dipanggil dengan aman dari thread yang berbeda, sebenarnya belum diperbaiki
      Satu-satunya solusi yang tampak dapat diandalkan adalah mengubah fungsi-fungsi ini agar wajib mengambil mutex
    • Penilaian penulis library bahwa “solusi terbaik untuk masalah ini saat ini adalah memakai library seperti rustls dan berhenti menggunakan crate ini” terasa masuk akal dan melegakan
      Sayangnya ekosistemnya tidak demikian: https://github.com/seanmonstar/reqwest/blob/master/Cargo.tom...
    • Orang-orang terlatih untuk mengabaikan blok dan prefiks seperti ____UNSAFE_payattention__nevermindthatthisappears50timesinthisfile___
      Hal serupa juga terjadi di framework web: Vue punya direktif v-html dan React punya dangerouslySetInnerHTML, dan dalam hal ini Vue jelas lebih baik
  • set_var dan remove_var di pustaka standar Rust akan benar-benar mewajibkan blok unsafe {} pada edisi 2024 berikutnya
    Dokumentasinya sekarang juga menyebut masalah keamanan, tetapi sejak awal menjadikan fungsi-fungsi ini sebagai safe adalah sebuah kesalahan, dan bahasa tingkat lebih tinggi pun pernah melakukan kesalahan yang sama
    https://doc.rust-lang.org/stable/std/env/fn.set_var.html
    glibc punya patch yang membuat getenv aman dalam lebih banyak kasus ketika environment dimodifikasi, tetapi C tetap bisa mengakses environ secara langsung, jadi dalam situasi ketika modifikasi terjadi, ini tidak akan pernah sepenuhnya aman: https://github.com/bminor/glibc/commit/7a61e7f557a97ab597d6f...

    • Mengejutkan bahwa glibc kini mempertahankan versi-versi lama dan mengadopsi kebijakan pengubahan ukuran eksponensial
      Ini menimbulkan kebocoran memori berukuran konstan secara amortisasi untuk setiap variabel lingkungan yang aktif, tetapi variabel itu sendiri juga sudah memiliki kebocoran seperti itu, bahkan bergantung pada panjangnya dan termasuk nilai yang sudah tidak dipakai lagi
      Rasanya pasti ada kasus penggunaan patologis yang, bahkan pada program yang benar menurut API, menyebabkan memori terus bertambah tanpa batas karena hal ini
      Menarik tapi agak mengganggu bahwa demi memperbaiki program yang melanggar aturan dengan memakai API ini dari beberapa thread, bug pertumbuhan memori tanpa batas diperkenalkan ke program yang justru mengikuti API. Rasanya lebih pragmatis daripada dogmatis
    • Jika implementasi pustaka standar bisa menangani sinkronisasi, mengapa harus mewajibkan unsafe?
  • Walaupun para pemelihara pustaka standar C menentang menjadikan setenv aman untuk multithread, setidaknya harus didefinisikan API baru yang thread-safe, entah di dalam POSIX atau dengan membuat standar de facto lebih dulu lalu POSIX menyusul
    Jika waktu yang dipakai untuk menjelaskan mengapa tidak ada yang bisa dilakukan dipakai untuk memperbaiki masalah ini, setenv lama seharusnya sudah bisa digantikan dan dihentikan pemakaiannya lalu dihapus dari banyak proyek perangkat lunak
    Melihat glibc membuat perubahan untuk pada dasarnya menghilangkan masalah ini, pernyataan pemelihara Musl bahwa ini tidak bisa diperbaiki di Musl juga terasa kurang meyakinkan

    • Masalah terbesar bukan tidak adanya API yang thread-safe, melainkan keberadaan extern char **environ;
      Selama environ bisa diakses secara publik, tidak ada jaminan bahwa setenv dan getenv benar-benar dipakai. Keduanya memang tidak wajib
      Jika environ bisa dihapus, membuat setenv dan getenv thread-safe cukup sederhana. Jika tidak bisa dihapus maka itu mustahil, tetapi tetap bisa dikatakan bahwa menjadikan setenv dan getenv thread-safe adalah perbaikan walaupun bukan solusi sempurna
    • Sepertinya semua fungsi exec() yang tidak menerima environment sebagai argumen atau yang mencari executable lewat PATH juga akan memerlukan locking
    • Tidak meyakinkan bahwa seseorang tahu lebih baik daripada para ahli yang sudah menyimpulkan bahwa ini tidak bisa diperbaiki dengan cara yang tetap kompatibel ke belakang
  • Di Linux, terkena bug terkait variabel lingkungan rasanya seperti semacam ritus peralihan, dan anehnya di Unix lain biasanya lebih jarang jadi masalah
    Linus dan kernel memperbaiki bug POSIX secara pragmatis dengan membuatnya tidak benar-benar meledak di dunia nyata, jadi agak lucu bahwa glibc masih tertinggal meski sudah puluhan tahun orang mencoba setidaknya meredakan masalah ini
    Memang ada banyak sumber sakit kepala seperti TZ, tetapi kalau saja mereka menyediakan getenv_r(), menyinkronkannya dengan setenv(), dan setidaknya memberi peringatan pada tahap kompilasi atau penautan saat getenv() dipakai, banyak masalah ini mungkin sudah hilang
    Bahkan bisa melangkah lebih jauh dengan pendekatan copy-on-write (COW) yang membuat pointer lingkungan tetap hanya-baca sebelum ditulis
    Sebaliknya, masalah ini justru dilempar ke masing-masing aplikasi, padahal penulis aplikasi hampir tidak mungkin tahu apa yang dilakukan dependensinya, jadi ini kesalahan besar. Situasi yang pernah saya alami dulu juga seperti itu, dan vendor pustaka closed-source saat itu malah menyuruh saya berhenti memakai Linux, si klon Unix mainan itu

    • Saya tidak tahu penilaian bahwa “Linux punya bug terkait variabel lingkungan dan Unix lain lebih jarang bermasalah” itu berasal dari mana
      Masalahnya bukan implementasi, melainkan API itu sendiri. setenv(), unsetenv(), putenv(), dan terutama environ pada dasarnya tidak aman dalam program multithread
      Bahkan getenv_r() pun tidak bisa sepenuhnya menyelamatkan keadaan. Itu karena saat satu thread sedang menyalin nilai lama variabel lingkungan ke buffer yang disediakan, thread lain bisa memanggil setenv()
      Tentu, kasus ketika setelah nilai diambil lewat getenv(), thread lain memanggil setenv() lalu membuat memori itu tidak valid memang diperbaiki oleh getenv_r(), tetapi tidak ada cara untuk mencegah panggilan lain yang juga merusak API
      libc memang bisa meredakan sebagian masalah dengan mengambil mutex di dalam getenv()/setenv()/putenv()/unsetenv(), tetapi tetap tidak ada cara bagi libc untuk menjamin bahwa nilai yang dikembalikan getenv() akan tetap valid selama kode pemanggil membutuhkannya
      Tidak ada cara bagus juga untuk membuat akses langsung ke environ menjadi aman. environ bisa saja dibuat thread-local, tetapi itu bisa membuat sudut pandang lingkungan pada tiap thread menyimpang secara permanen, dan hasil getenv_r() bisa berbeda dari hasil pemeriksaan langsung terhadap environ
      Menjaga kompatibilitas mundur di sini memang sangat sulit, dan bahkan hanya menambahkan mutex untuk melindungi fungsi-fungsi ini saja bisa mengubah makna program lama hingga rusak
  • Dulu pernah ada tulisan bahwa setenv itu mengerikan: https://www.evanjones.ca/setenv-is-not-thread-safe.html
    Ada juga diskusinya, dan sejak komentar pertama sudah membahas bahwa ini menyebabkan masalah di Rust: https://news.ycombinator.com/item?id=38342642

    • Itu sebenarnya sudah diketahui
      Di sini sebagian besar sisa masalah tampaknya terkait lingkungan pengembangan. Pengujian dilakukan dengan Docker di mesin jarak jauh dalam data center Amazon, dan mesin itu gagal melaporkan proses yang crash
      Selain itu, di dalam container juga tidak ada informasi simbol debug yang cukup untuk mendapatkan backtrace. Kalau saat kegagalan pertama mereka langsung mendapat backtrace yang bersih, penyebabnya pasti akan segera jelas
      Dari awal pun muncul pertanyaan kenapa setenv dipakai sama sekali
  • Membaca ini mengingatkan saya pada gerakan 12-factor app yang sangat dipercaya beberapa rekan kerja saya dulu. Salah satu “factor”-nya adalah konfigurasi aplikasi harus menggunakan variabel lingkungan
    Saya selalu merasa itu agak bodoh, karena cara konfigurasi tersebut pada dasarnya menaruh nilai bertipe string ke dalam keranjang dengan namespace datar
    Bahaya getenv()/setenv()/environ juga menurut saya menjadi alasan kuat mengapa variabel lingkungan sebaiknya tidak dipakai untuk konfigurasi
    Tentu saja tidak selalu ada alternatif yang hebat dan didukung dengan baik. Saya lebih suka file konfigurasi, dan bisa juga memakai konfigurasi templat yang hanya diisi nilai untuk development, staging, dan production. Biasanya saya tetap memakai YAML meskipun ada kelemahan dan jebakannya, karena walaupun mungkin ada format file konfigurasi yang lebih baik, YAML tetap jauh lebih baik daripada variabel lingkungan

    • Ada banyak antipati kuat terhadap Windows dan Microsoft, tetapi seiring waktu cukup sering ada situasi di mana desain API mereka terasa terbukti benar
      Di NT, variabel lingkungan bisa dibuat bertipe dan ditemplatisasi, dan juga ada registry, yaitu basis data konfigurasi dengan namespace. Memang bertele-tele dan aneh, tetapi tetap ada
      Selain itu, MSVC menyediakan versi thread-safe untuk hampir semua fungsi pustaka standar
      Saya sering mendengar pengembang C/C++ baru mengeluhkan kurangnya kompatibilitas POSIX di MSVC, tetapi tampaknya mereka tidak terlalu memikirkan apa artinya itu dalam praktik. Itu lebih mirip keinginan agar tetap kompatibel silang dengan program C yang ditulis pada 1990-an
    • Saya punya kekhawatiran serupa tentang variabel lingkungan. Saya tidak suka karena bisa dibaca dari mana saja
      Itu mengganggu kemampuan untuk menebak perilaku hanya dari signature fungsi, dan membuat banyak fungsi yang seharusnya bisa murni menjadi tidak murni
      Jika ada fitur bahasa yang bisa menandai aplikasi sehingga, dalam proses apa pun, variabel lingkungan tidak bisa ditulis dan hanya bisa dibaca sekali, bukan per variabel tetapi sekali baca secara keseluruhan, saya rasa saya akan memakainya di mana-mana
    • getenv() sendiri sepenuhnya baik-baik saja; masalahnya ada pada setenv()
      Secara teori, environment sudah disiapkan sebelum aplikasi misterius itu dimulai, jadi seharusnya tidak perlu memakai ini
      Namun namespace datar, nilai string, dan fakta bahwa ini adalah ruang global bebas yang dibagi semua orang tanpa tahu pustaka dan modul apa saja yang akan ikut masuk, tetap bukan ide yang baik bahkan jika masalah keamanan setenv() tidak ada
    • Seharusnya ada lampiran pada “12-factor app” yang mengatakan bahwa selama proses hidup, environment harus diperlakukan hanya-baca
      Sebagian besar masalah yang dibicarakan orang di sini tampaknya muncul dari penyalahgunaan environment seolah-olah itu penyimpanan key-value untuk status global yang dapat diubah. Saya tidak paham kenapa orang ingin melakukan itu
      JVM pada praktiknya memperlakukan environment sebagai immutable, dan mungkin saja perusahaan pengguna Scala/Java seperti SoundCloud ikut memengaruhi gerakan 12-factor app. Saya sendiri belum pernah mengalami environment berubah atau menimbulkan masalah threading
      Bahkan jika environment berubah, salinan immutable yang dibuat saat JVM dimulai tetap sama, dan kode yang berinteraksi dengan environment lewat API Java biasa tidak akan melihat perubahan itu
      Masalah file konfigurasi adalah parsing dilakukan per proses. Itulah sebabnya Linux/Unix menjadi sangat semrawut. Tiap alat punya konvensi dan mekanisme konfigurasi sendiri, dan tidak ada standar
      Dalam ekosistem Docker, apa pun yang dilakukan di dalam container, antarmuka ke dunia luar biasanya adalah memasang volume lalu mengikuti cara konfigurasi rumit tiap aplikasi, atau cukup memakai variabel lingkungan
      Sebagian besar perangkat lunak modern yang dijalankan dengan Docker saat ini cukup ramah Docker sehingga perilakunya bisa dikendalikan sepenuhnya lewat environment, dan dalam banyak kasus itu sudah cukup
      Jika memakai Docker Compose atau Kubernetes, Anda pada akhirnya punya daftar variabel lingkungan yang mendefinisikan cara proses dimulai dalam file YAML, jadi sampai batas tertentu struktur yang diinginkan memang muncul. Saya tidak suka YAML, tetapi itu cukup berfungsi, dan walaupun masalah sintaks bisa merusak hari Anda, alternatifnya juga bukan tanpa masalah
    • Ini sebenarnya isu yang terpisah. Jika variabel lingkungan dibaca sebagai konfigurasi lalu tidak disentuh lagi, itu sepenuhnya aman
      Saya juga memakai gaya 12-factor app, tetapi setelah masuk ke aplikasi, saya memvalidasi dan menyimpan variabel lingkungan serta datanya. Setelah itu tidak ada masalah sama sekali
  • Ini tulisan yang luar biasa, menggali bug yang sulit terlihat
    Ada bug intermiten, kekhususan arsitektur, tersembunyi di dalam dependensi, Rust, Python GIL, sampai gettext
    Laporan pemecahan masalah sedetail ini adalah bahan yang paling mendekati pengalaman mengalaminya langsung. Dalam situasi ketika dependensi Anda yang memakainya dan Anda tak mungkin tahu sebelumnya, sulit untuk sekadar bilang “ya tinggal jangan pakai X”

  • Katanya “mesin CI malam hari berjalan di Amazon AWS dan punya keuntungan bisa memakai pengguna root sungguhan, bukan container”, tetapi pada saat yang sama juga dikatakan “di luar container tidak ada file yang diperlukan dan container dibuat sangat minimal sehingga gdb tidak bisa dipasang dengan mudah”
    Apakah sekarang orang-orang sudah kehilangan kemampuan untuk build dan debug secara lokal tanpa cloud dan container?

    • Betul. Mengejutkan betapa cloud SaaS telah mendistorsi pemahaman orang
      Untuk melakukan hal yang sangat sepele saja sekarang dibutuhkan segala macam kompleksitas cloud dan lapisan deployment. Seolah revolusi PC diputar balik 100% dan kita kembali ke era komputasi mainframe yang kaku dan mahal
      Alasannya karena ada uang di cloud, dan cloud itu DRM. Jika perangkat lunak dipindahkan ke sana, Anda bisa menarik biaya langganan, pengguna tak bisa menghindarinya, dan ketergantungan total bisa dipertahankan selamanya. Sering kali pengguna bahkan tidak bisa mengambil data mereka sendiri
      Analitik real-time untuk optimasi produk juga jadi mudah dilakukan
      Arsitektur komputasi berada di hilir dari model bisnis. Mainframe dulu mati bukan hanya karena tidak ada internet dan PC lebih murah, tetapi juga karena vendor kehilangan banyak kekuatan untuk mengunci pelanggan
      Sekarang ada cara untuk menghidupkan kembali model yang jauh lebih menguntungkan itu. Kebebasan pengguna yang merepotkan telah hilang, dan sejujurnya ketika pengguna punya kebebasan seperti itu mereka sering juga tidak membayar, sehingga bisnis perangkat lunak berkualitas tinggi jadi sulit dijalankan
    • Ini masalah seperti korupsi memori acak yang hanya muncul di ARM
      Besar kemungkinan mereka tidak bisa mereproduksi crash itu secara lokal. Mesin pengembang kebanyakan x86, dan di sana crash-nya tidak terjadi
      Penanganan crash memang seharusnya bisa lebih baik, tetapi mereka tampaknya juga menyadari itu, dan itu bukan inti utama yang dibahas di sini
    • Tentu saja bukan berarti kemampuannya hilang, hanya saja di mesin kami crash-nya memang tidak terjadi
    • Jika mereka kemungkinan besar tidak punya perangkat yang menjalankan arsitektur tempat masalah itu muncul, bagaimana mereka bisa debug secara lokal? Toh debug langsung di lingkungan nyata tempat kegagalan terjadi jauh lebih cepat
  • Status global yang bisa diubah itu jahat. Kalau teman, jangan biarkan teman memakai status global yang bisa diubah
    Saya benci variabel lingkungan. Ini memang “cara Linux”, tapi saya menghindarinya seperti wabah. Sangat direkomendasikan
    libc itu mengerikan, dan dunia sekarang harus move on

    • Variabel lingkungan masih oke kalau diperlakukan sebagai hanya-baca di dalam proses
    • Kalau “status global yang bisa diubah itu jahat”, berarti CPU dan RAM juga harus dibuang
    • Penasaran alternatif apa yang diusulkan
      Masalahnya bukan Linux, bukan status global yang bisa diubah atau resource, juga bukan libc
      Masalahnya adalah di tempat kerja kita tidak diberi waktu untuk mengerjakan sesuatu dengan benar. Misalnya, untuk menangkap masalah dengan GDB sebelum meledak, atasan harus memberi waktu untuk dengan gigih men-debug dan menelusuri balik kode serta semua hal yang disentuh kode itu
      Terlalu banyak uang mengalir ke kode yang masih setengah matang. Menyedihkan, tapi itu kenyataannya
    • libc telah mendorong dunia masuk ke era informasi
    • Penasaran apa alternatif yang lebih disukai
  • Karena masalah seperti ini terlalu banyak, akhirnya saya menambal getenv / setenv / putenv dengan LD_PRELOAD

    • Apakah ini dibuat dengan implementasi tetap yang membocorkan environment, seperti yang baru saja masuk ke glibc?