- Di emulator terminal Ghostty, ditemukan kebocoran serius yang dapat memakai puluhan GB memori saat berjalan dalam waktu lama
- Penyebabnya adalah akumulasi memori yang tidak pernah dibebaskan karena
munmap tidak dipanggil dalam logika reuse halaman memori nonstandar pada struktur PageList
- Karena Claude Code CLI sering menghasilkan output graf dengan banyak code point, frekuensi penggunaan halaman nonstandar meningkat sehingga kebocoran muncul dalam skala besar
- Perbaikannya diubah agar halaman nonstandar tidak digunakan ulang dan langsung dibebaskan, serta pelacakan dan verifikasi kebocoran dilakukan dengan memanfaatkan fitur VM tag di macOS
- Perbaikan ini dinilai menyelesaikan masalah kebocoran terbesar di Ghostty dan akan disertakan dalam rilis mendatang (1.3)
Ringkasan kebocoran memori Ghostty
- Beberapa pengguna melaporkan Ghostty memakai lebih dari 37GB memori setelah berjalan lama
- Kebocoran ini sudah ada setidaknya sejak versi 1.0, dan belakangan aplikasi CLI tertentu memenuhi kondisi yang memunculkan masalah ini
- Perbaikannya sudah di-merge ke GitHub dan akan masuk ke build nightly serta rilis resmi 1.3
Struktur PageList dan cara pengelolaan memori
- Ghostty memakai struktur double-linked list bernama PageList untuk menyimpan isi terminal
- Setiap halaman memuat data seperti karakter, style, dan hyperlink
- Halaman dialokasikan dengan
mmap dan digunakan ulang melalui pool halaman berukuran standar
- Halaman yang ukurannya tidak melebihi standar dikembalikan ke pool
- Halaman berukuran nonstandar harus dibebaskan langsung dengan
munmap
- Struktur ini sendiri normal, tetapi kebocoran terjadi akibat bug dalam logika optimasi
Optimasi scrollback dan penyebab bug
- Saat Ghostty melampaui
scrollback-limit, ia melakukan optimasi dengan menggunakan ulang halaman tertua
- Kinerja meningkat karena cukup menyesuaikan pointer tanpa alokasi halaman baru
- Masalahnya, dalam proses ini hanya metadata halaman nonstandar yang diubah menjadi ukuran standar, sementara memori aktualnya tetap sama
- Akibatnya saat dibebaskan, halaman itu dianggap sebagai halaman standar sehingga
munmap tidak pernah dipanggil
- Karena itu, halaman nonstandar tidak pernah dibebaskan dan terus menumpuk, menyebabkan kebocoran memori besar saat dipakai lama
Claude Code dan terbukanya kebocoran dalam skala besar
- Claude Code CLI sering menghasilkan output graf dengan banyak code point sehingga frekuensi penggunaan halaman nonstandar meningkat
- Selain itu, output scrollback juga banyak sehingga kebocoran cepat terakumulasi
- Dalam desain Ghostty, halaman nonstandar seharusnya jarang muncul, tetapi karakteristik Claude Code membuat kebocoran bisa direproduksi dalam jumlah besar
- Pengembang menegaskan bahwa bug ini bukan masalah Claude Code, melainkan cacat pada logika internal Ghostty
Isi perbaikan
Melacak kebocoran dengan VM tag
- Fitur VM tag pada kernel Mach di macOS digunakan untuk memberi tag khusus pada alokasi memori PageList
- Saat debugging, area memori Ghostty bisa diidentifikasi dengan jelas
- Ini sangat membantu untuk melacak penyebab kebocoran dan memverifikasi perbaikannya
- Dengan fitur ini, status pembebasan memori terkait PageList dapat diperiksa secara visual
Sistem pencegahan kebocoran memori di Ghostty
- Ghostty mendeteksi dan mencegah kebocoran dengan berbagai cara
- Di build debug dan unit test, digunakan allocator pendeteksi kebocoran milik Zig
- Di CI, seluruh pengujian dijalankan dengan valgrind
- Di macOS Instruments, dilakukan pemeriksaan kebocoran pada kode Swift
- PR terkait GTK diverifikasi dengan tes GUI Valgrind
- Kebocoran kali ini hanya muncul dalam kondisi tertentu, sehingga tidak bisa direproduksi oleh pengujian yang ada sebelumnya
- Test case baru telah ditambahkan untuk mencegah regresi
Kesimpulan
- Masalah ini dipastikan sebagai kasus kebocoran memori terbesar yang pernah ditemukan di Ghostty
- Setelah perbaikan, pemantauan berlanjut melalui laporan pengguna dan pengujian reproduksi
- Data diagnosis dan contoh reproduksi dari komunitas berperan penting dalam penyelesaian masalah
- Ditekankan bahwa tersedianya lingkungan yang dapat direproduksi adalah kunci untuk menyelesaikan kebocoran memori
1 komentar
Komentar Hacker News
Ini benar-benar kabar yang sangat menggembirakan. Tepuk tangan untuk semua orang yang ikut berkontribusi menyelesaikan masalah ini
Ini sudah merupakan bug yang disebutkan minggu lalu di thread ini
Sepertinya Claude Code menjadi pemicu yang membuat bug ini terlihat oleh lebih banyak pengguna, tetapi ada juga orang seperti saya yang mengalami masalah yang sama meski sama sekali tidak memakai Claude Code
Kriteria sebuah halaman diklasifikasikan sebagai ‘non-standard’ ternyata tidak sehitam-putih itu
Saya juga merasa kebocoran ini mungkin lebih sering terjadi pada orang yang memakai pengaturan seperti
scrollback-limit = 0Agak disayangkan karena cara perbaikannya bisa saja menghapus lalu membuat ulang halaman non-standar secara tidak perlu, padahal mungkin halaman lama yang sudah non-standar itu bisa didaur ulang
Cara kerja PageList dari dulu memang sama, dan bahkan saat bug terjadi pun yang terlihat hanya ukuran yang salah selama penyesuaian kapasitas
Seharusnya tidak akan ada perubahan yang terasa dari sisi performa
Alternatif yang diusulkan juga sudah dipertimbangkan, tetapi pendekatan saat ini cukup didukung oleh data benchmark
Saya juga bisa saja berubah pikiran, tetapi kali ini saya fokus memperbaiki kebocorannya alih-alih mengubah keseluruhan cara pandang
Ini memang bug yang bisa direproduksi dan benar-benar menyebabkan segfault
Ini membuat CLI terasa baru lagi melebihi apa pun dalam 20 tahun terakhir
Tulisan yang luar biasa. Terima kasih kepada mitchellh karena telah membuat Ghostty
Saya beralih tahun lalu dan belum pernah menyesal
Hanya saja agak mengejutkan bahwa perbaikannya dimasukkan ke rilis fitur beberapa bulan kemudian
Saya kira ini akan masuk ke rilis perbaikan bug
Begitu pembahasan masuk ke soal halaman, saya langsung berpikir, “oh, ini pooling memori,” lalu “pasti ring buffer,” dan ternyata memang soal reuse scrollback
Saya juga langsung bisa menebak lokasi bug-nya — bagian yang tidak membebaskan memori halaman dengan benar
Diagram penyelarasan memorinya juga keren
Ini jadi pengingat lagi bahwa setiap kali mencoba hal baru, selalu ada potensi kebocoran
Minggu ini saya pindah ke Ghostty, lalu mengalami crash OOM saat mengembangkan aplikasi UI terminal
Strukturnya memakai ikon UTF8 di tab bar, dan terminal langsung crash saat ukuran jendela diubah
Karena mudah direproduksi, saya sedang menyiapkan laporan bug, dan masalahnya terlihat sangat mirip dengan yang dijelaskan di postingan blog
Semoga ini terselesaikan
Saya bertanya ke @mitchellh — alat apa yang dipakai untuk membuat visualisasi memorinya, dan karena situsnya juga berjalan baik di mobile, saya penasaran dengan stack yang digunakan
Kode untuk visualisasinya bersifat sekali pakai, jadi yang diverifikasi hanya akurasi-nya, bukan kualitasnya
Namespace dipisahkan per postingan blog dan tidak digunakan ulang
Saya hanya memastikan implementasinya tidak melakukan hal aneh (misalnya menambang bitcoin, membocorkan rahasia, dan sebagainya)
Intinya adalah menyampaikan informasi, dan diagram seperti ini membuat isi tulisan jauh lebih mudah dipahami
Saya terus mengikuti perkembangan Ghostty
Memang ada sedikit nuansa overengineering, tetapi postmortem bug seperti ini sangat berharga bagi orang yang mencintai craftsmanship
Kalau ini adalah terminal berbasis Rust, saya penasaran bagaimana implementasi seperti ini bisa ditangani tanpa kehilangan performa
Bahkan dari sudut pandang orang yang tidak terlalu paham Ghostty atau terminal emulator, ini tulisan yang mudah dipahami
Kesan yang saya dapat adalah penjelasannya sangat ramah dan mudah diakses
Ini mengingatkan lagi akan pentingnya laporan bug yang bisa direproduksi
Saya menunggu seseorang berkata, “Kalau pakai Rust, hal seperti ini tidak akan terjadi”
Rust tidak menjamin ‘keamanan terhadap kebocoran memori (leak safety)’ di tingkat bahasa
Bahkan kode Rust yang aman pun bisa membocorkan memori — hanya saja ini bukan masalah keamanan
API standar pun secara eksplisit mengizinkan kebocoran, seperti Box::leak
Rust hanya membuat kebocoran yang tidak disengaja lebih sulit terjadi, bukan mencegahnya sepenuhnya