1 poin oleh GN⁺ 2025-08-16 | 1 komentar | Bagikan ke WhatsApp
  • Tim Ghostty menulis ulang aplikasi GTK sepenuhnya dan secara aktif memanfaatkan sistem tipe GObject
  • Dalam proses ini, integrasi dengan bahasa Zig dan verifikasi isu memori melalui Valgrind memainkan peran penting
  • Dengan mengadopsi sistem GObject, manajemen memori dan implementasi widget kustom menjadi lebih sederhana dibanding sebelumnya
  • Dengan memanfaatkan Valgrind, mereka merasakan bahwa keamanan memori Ghostty meningkat secara signifikan
  • Ghostty GTK yang baru kini menjadi default untuk build dari source dan dijadwalkan akan masuk ke rilis 1.2

Pendahuluan

  • Ghostty adalah emulator terminal lintas platform yang mendukung macOS, Linux, FreeBSD
  • Ghostty memiliki keunggulan dengan menggunakan framework GUI native di tiap platform
    • macOS: aplikasi besar berbasis Swift dan Xcode
    • Linux dan BSD: aplikasi berbasis GTK, terintegrasi langsung dengan X11/Wayland dan lainnya
    • Core bersama ditulis dalam Zig dan menyediakan API yang kompatibel dengan C ABI
  • Alasan menulis ulang aplikasi GTK dalam struktur sebelumnya dapat dilihat pada PR asli
  • Tulisan ini berfokus pada integrasi dengan sistem tipe GObject serta isu memori yang diverifikasi dengan Valgrind

Sistem tipe GObject dan Zig

  • Saat menggunakan GTK, strukturnya pada dasarnya mengharuskan untuk berinteraksi dengan sistem tipe GObject
  • Di masa lalu, mereka menghindari sistem GObject dan mencoba menyelaraskan sendiri siklus hidup objek Zig tanpa reference counting dan objek GObject, tetapi berulang kali muncul masalah pelepasan memori yang tidak berjalan dengan benar
    • Contoh: memori di sisi Zig sudah dibebaskan, tetapi memori di sisi GTK masih hidup, atau sebaliknya, dan situasi ini terus berulang
  • Pendekatan seperti ini tidak hanya bermasalah dari sisi correctness, tetapi juga menyulitkan penggunaan fitur khas GTK (event signal, property binding, action)
  • Contoh konkretnya, saat me-reload struct konfigurasi (config), semua elemen GUI yang terhubung harus diperbarui secara konsisten, tetapi proses ini rumit dan sering menimbulkan kesalahan
    • Sekarang, ini dikelola sebagai GhosttyConfig GObject dengan reference counting yang membungkus struct Config Zig, sehingga perubahan dapat menyebar secara alami ke seluruh aplikasi melalui notifikasi perubahan properti
  • Pembuatan widget GObject kustom juga menjadi lebih mudah, sehingga teknologi UI GTK modern seperti Blueprint dapat digunakan
    • Baru-baru ini, dengan mengadopsi Blueprint, fitur baru seperti tab titlebar GTK dan bingkai lonceng beranimasi menjadi lebih mudah ditambahkan

Valgrind, GTK, dan Zig

  • Sepanjang proses pengembangan, Valgrind digunakan untuk memverifikasi secara sistematis masalah seperti memory leak dan akses ke memori yang tidak terdefinisi
  • Pemeriksaan Valgrind pada aplikasi GTK cukup rumit, dan memerlukan file suppression dalam jumlah besar (80% untuk GTK sendiri, sisanya untuk library pihak ketiga dan driver GPU)
  • Dengan pemeriksaan berulang, bug memori kompleks yang hanya muncul pada kasus tertentu bisa ditemukan lebih awal
    • Contoh: jika WeakRef milik GObject tidak diinisialisasi dengan benar, akses ke memori tak terdefinisi dapat terjadi ketika objek target dibebaskan nanti, dan ini bisa ditangkap lebih dulu oleh Valgrind
  • Berdasarkan pengalaman nyata, isu di dalam codebase Zig sendiri hanya berjumlah 2 kasus (1 leak, 1 akses tak terdefinisi), dan itu pun terjadi dalam proses integrasi dengan C API pihak ketiga
    • Allocator debug milik Zig dan fitur integrasi dengan Valgrind juga terbukti efektif
  • Isu memori lain yang ditemukan sebagian besar berasal dari boundary C API dan pengelolaan siklus hidup yang kompleks dalam sistem GObject
    • Kesimpulannya, untuk menggunakan C API dari library kompleks dengan aman, diperlukan alat seperti Valgrind
  • Fitur pendukung keamanan memori di Zig terbukti efektif bukan hanya dalam diskusi teoretis, tetapi juga melalui pengalaman proyek yang terverifikasi secara empiris

Kesimpulan

  • Ini adalah pengalaman kelima membangun ulang bagian GUI Ghostty dari nol
    • Secara berurutan: GLFW, macOS SwiftUI, macOS AppKit+SwiftUI, Linux GTK (prosedural), Linux GTK+sistem tipe GObject
  • Dalam proses penulisan ulang yang berulang, setiap kali ada pelajaran baru dan pertumbuhan teknis yang didapat
    • Pengalaman kali ini juga direncanakan untuk sebagian diterapkan pada proyek macOS
  • Kolaborasi aktif dari tim pemelihara sistem Ghostty GTK juga ditekankan
  • Aplikasi Ghostty GTK yang baru ditulis ulang kini telah menjadi default untuk build dari source, dan akan diterapkan pada rilis resmi 1.2

1 komentar

 
GN⁺ 2025-08-16
Komentar Hacker News
  • Saya belum pernah bekerja langsung dengan GTK, tetapi dari penjelasan Anda, rasanya ini sangat mirip dengan masalah yang saya hadapi saat membuat binding Godot dengan Zig. Godot punya sangat banyak konsep OOP seperti kelas, metode virtual, properti, sinyal, dan sebagainya. Selain itu, ada C API yang menangani semua konsep itu dan memungkinkan pembuatan objek serta properti kustom. Ia juga mengelola siklus hidup objek engine secara langsung, dan ada struktur pohon objek dengan reference counting. Khususnya saat mencoba membungkus masalah lifetime ini menjadi API optimal yang sesuai idiom Zig, kompleksitasnya jadi luar biasa. Karena memikirkan hal-hal ini, saya juga membuat library oopz. Status API-nya saat ini masih seperti itu, dan contoh nyatanya bisa dilihat di sini. Saya juga ingin mencoba membuat frontend Ghostty sebagai ekstensi Godot

    • Dulu saya pernah merasa tidak nyaman saat memakai binding GTK khusus bahasa secara langsung. 98% berjalan baik, tetapi pada 2% sisanya ada bagian seperti “apakah fungsi ini mengambil referensi objek atau tidak, itu berubah tergantung argumen lain”, jadi analisis siklus hidup objek benar-benar merepotkan
    • Sekaligus ingin menyampaikan terima kasih, saya juga pernah kesulitan saat mencoba menulis kode Godot C# yang berkinerja baik karena terlalu banyak konversi bolak-balik dengan tipe engine, sehingga alokasi terus berulang. Saya penasaran apakah Anda juga mengalami masalah seperti ini saat membuat binding
    • Saya tidak tahu sedang ada proyek membuat binding Godot dengan Zig. Karena saya suka Godot dan Zig sekaligus, saya sangat menantikannya. Saya akan terus mengikutinya
  • Ini contoh yang bagus bahwa pemrograman yang baik pada akhirnya berarti menyesuaikan diri dengan cara kerja yang disediakan sistem. Apa pun pandangan kita tentang OOP atau manajemen memori, kalau memakai GTK maka mau tak mau harus merancang antarmuka dengan sistem tipe GObject dalam satu bentuk atau lainnya. Sekalipun ingin menghindarinya, pada akhirnya memang tidak bisa dihindari. Tetapi kami mencoba menghindarinya, dan hasilnya terjadi kekacauan besar saat mengikat lifetime objek yang reference-counted dengan objek yang tidak reference-counted. Di aplikasi Ghostty GTK, bug terus berulang di mana saat memori Zig dibebaskan, memori GTK tidak dibebaskan, atau sebaliknya

    • Alasan GTK punya struktur seperti ini adalah latar belakang kelahiran Vala. Vala terinspirasi dari C#, memanfaatkan GObject, dan mentranspilasi kodenya ke C. Karena itu cukup banyak aplikasi GTK sebenarnya ditulis dengan Vala. Kadang terasa sayang, bukankah akan lebih baik kalau dulu memakai bahasa D. Dalam banyak hal, D terasa seperti C# yang dikompilasi
    • Menyerah pada sistem yang buruk bukanlah hal yang baik, melainkan pilihan yang pragmatis
  • Terlepas dari sikap saya soal OOP dan manajemen memori, saya setuju bahwa jika memakai GTK maka Anda pasti akan terjerat dengan sistem tipe GObject. Karena itu saya memutuskan untuk sama sekali tidak memakai GTK secara langsung. Saya paham nilai dari tema UI yang seragam, tetapi menurut saya kelebihan GTK tidak cukup besar untuk layak dibayar dengan biaya seperti itu. Dari pengalaman saya menyentuh bagian pinggiran GTK di aplikasi open source, saya jadi yakin bahwa cara pandang GTK dan GObject tidak cocok dengan kecenderungan saya. Saya tidak benci GTK itu ada. Saya baik-baik saja memilih untuk tidak memakainya, tetapi anehnya sebagian orang tampaknya tidak menganggap pilihan itu sebagai hak saya. Ini hanya salah satu dari sekian banyak GUI toolkit, dan meskipun secara teknis sangat rapi, kalau pangsa GTK sedikit lebih kecil mungkin polesan itu bisa diarahkan ke toolkit lain yang secara struktural lebih baik. Tentu saja, apa yang saya anggap baik belum tentu baik bagi semua orang. Saya penasaran, dari orang-orang yang memakai GTK, berapa banyak yang sebenarnya terpaksa memakainya, dan berapa banyak yang merasa ini toolkit terbaik

    • Saya setuju dengan bagian bahwa gaya GTK dan GObject yang sangat opinionated juga tidak terlalu cocok dengan cara berpikir saya. Saya juga merasa banyak tidak cocok dengan arah ekosistem Gnome. Memakai GTK untuk Linux di Ghostty adalah pilihan yang sangat pragmatis. Target Ghostty soal apa artinya native platform, terutama di Linux, dijelaskan di sini. GTK adalah yang paling luas dipakai di Linux dan paling alami menyatu dengan sebagian besar ekosistem aplikasi, jadi keputusan ini pada dasarnya tak terhindarkan. Ke depannya saya berharap libghostty memungkinkan munculnya berbagai frontend dari pihak ketiga. Contohnya sudah ada frontend Ghostty native Wayland, yaitu Wraith. Keren
    • Saya rasa alasan utama GTK begitu luas dipakai di Linux justru karena ia punya “binding C”. Karena itu binding untuk hampir semua bahasa tersedia secara bawaan atau mudah dihasilkan secara otomatis. Sebaliknya, Qt terlalu terikat pada C++ dan Python sehingga aksesibilitasnya jauh menurun. Penting untuk menemui pengembang di bahasa yang sudah mereka gunakan. Selain itu, saat menulis aplikasi desktop yang kompleks, toolkit UI imperatif model lama justru praktis, punya banyak widget yang sudah teruji, dan polanya juga familier. Pendekatan yang lebih baru sebaliknya menuntut Anda mengutak-atik semuanya sejak hal kecil, dan begitu mulai kompleks jadi cukup berat
    • Saya penasaran jenis penolakan seperti apa yang paling sering Anda temui terkait bagian “saya bisa memilih untuk tidak memakai GTK, tetapi sebagian orang menganggap itu bukan pilihan saya”. Dari sudut pandang saya, GTK cukup baik dalam hal aksesibilitas dan input non-Roman, area yang biasanya tidak terlalu diperhatikan oleh pengembang yang membuat sendiri, jadi dukungan di sini tampak seperti daya saing utamanya
  • Fakta menariknya, di Ghostty dan beberapa aplikasi GTK lain ada gejala klik scroll pertama diabaikan ketika mouse keluar dari jendela lalu masuk lagi. Ini akibat bug yang sangat tua, pertama kali dilaporkan pada 2015. Tautan bug. Sampai sekarang tidak ada rencana memperbaikinya, dan posisi maintainer adalah menunggu Wayland

    • Sebenarnya masalah ini tampaknya bukan di GTK sendiri, melainkan di XInput2. Tentu GTK bisa membuat workaround seperti heuristik yang dipakai Chromium, tetapi pada dasarnya ini masalah di lapisan atasnya, yaitu XInput2
    • Kalau membaca laporan bug itu dan issue yang ditautkan, terlihat sudah ada beberapa upaya untuk memperbaikinya, tetapi pada akhirnya tetap harus bergantung pada beberapa heuristik, dan terus muncul efek samping yang lebih parah daripada masalah yang semula ingin ditangani. Karena akar masalahnya memang berasal dari fondasi X11, rasanya baru setelah perbaikan fundamental dilakukan barulah peningkatan lain bisa maju dengan berarti. Tetapi X11 sekarang pada dasarnya sudah dalam mode pemeliharaan, jadi selama para penggemarnya terus bersikeras bahwa “semuanya sudah bekerja sempurna dan tidak perlu kerja tambahan”, rasanya sulit berharap banyak. Pada akhirnya yang tersisa hanyalah menunggu transisi ke Wayland
  • Pada bagian “saya memverifikasi semua langkah dengan Valgrind”, sebenarnya ini terdengar sangat wajar, tetapi saya sendiri belum pernah benar-benar melakukannya, dan juga jarang melihat pengembang lain melakukannya. Biasanya Valgrind hanya dipakai saat bug tertentu atau penurunan performa sudah muncul. Kalau alat seperti Valgrind, khususnya Memcheck dan Helgrind, dipakai secara aktif sepanjang proses pengembangan, kualitas tool tampaknya bisa meningkat drastis, dan bug juga bisa ditangkap tepat saat diperkenalkan, sehingga tidak perlu repot menelusuri ratusan commit setelah kejadian

    • Saya sendiri saat menulis C dan C++ selalu rutin memakai valgrind. Error yang ditangkap valgrind dan asan biasanya tidak langsung muncul sebagai crash yang jelas, melainkan menjadi bug merepotkan yang sulit terlihat dan muncul sesekali, sehingga sangat sulit menemukan penyebabnya. Di antaranya juga ada kerentanan keamanan. Selain itu, kebocoran memori kecil yang menumpuk sedikit demi sedikit nantinya bisa memicu masalah yang benar-benar besar, dan saat itu justru semakin sulit menemukan penyebabnya karena sudah terlalu banyak kebocoran kecil yang terakumulasi. Jadi sebaiknya dipakai secara proaktif
    • Saya juga selama ini memakai Valgrind, terutama memcheck, secara aktif untuk lebih dulu menangkap masalah yang mudah diperbaiki sebelum masuk ke debugging rinci laporan bug. Hanya saja masalah terbesarnya adalah overhead performanya tinggi sehingga pengalaman menjalankannya secara interaktif kurang menyenangkan. Tetapi menjalankan test sesekali dengan Valgrind menurut saya sangat menguntungkan
    • Namun, Valgrind sangat lambat dan mahal, jadi sulit memasukkannya langsung ke siklus edit-kompilasi-test. Masih bisa dipakai pada siklus pengujian seperti nightly atau otomatisasi, tetapi agar terintegrasi dengan baik tetap butuh pekerjaan tambahan
  • Saat memakai Ghostty, sangat mengganggu bahwa menempel banyak baris ke nano di Mac tidak bekerja dengan baik. Sepertinya ini tergantung bagaimana terminal menangani “bracketed pasting”, tetapi anehnya di iterm2 atau term masalah ini tidak ada

    • Ghostty sebagai pengganti terminal sudah memuaskan 99%, tetapi masalah copy-paste ini benar-benar menjengkelkan dan saya mengalaminya setiap hari
    • Sejak menjadikan Ghostty sebagai terminal default di komputer baru, kekurangan terbesar yang saya rasakan adalah tidak adanya fitur pencarian. Biasanya saya sering memakai shortcut untuk mencari isi tertentu dalam output, tetapi itu tidak ada. Memang di issue juga ini jadi masalah yang paling sering disebut
    • Saat terhubung ke Ubuntu secara remote, menjalankan nano di dalam Ghostty bahkan tidak bisa
      $ nano
      Error opening terminal: xterm-ghostty.
      
      Di lingkungan yang sama, terminal macOS atau terminal bawaan VSCode bekerja dengan baik
    • Ini tampaknya bisa jadi bug sungguhan, jadi saya sarankan melaporkannya
    • Tidak adanya pencarian perintah seperti Cmd+F adalah yang paling fatal
  • Saya penasaran apakah kalau dipakai Rust alih-alih Zig, error memori bisa dicegah. Karena kebanyakan masalah muncul dari interaksi Zig/C, mungkin dengan Rust hasilnya akan mirip. Sebagai pengembang Go saya hanya menebak, tetapi saya juga penasaran apakah ada bahasa yang memberi lebih banyak alat keselamatan saat harus berintegrasi besar-besaran dengan C

    • Kalau Rust, satu masalah mungkin bisa dicegah, tetapi sisanya akan sama saja. Seperti yang Anda tunjukkan, semuanya adalah masalah di batas dan semantik C API, jadi keselamatan nyata pada akhirnya bergantung pada kualitas wrapper. Rust memang sudah punya ekosistem wrapper yang lebih teruji, jadi dalam aspek itu risikonya mungkin lebih rendah dibanding wrapper buatan sendiri di Zig, tetapi secara keseluruhan tidak akan jauh berbeda. Sebagai contoh, undefined memory access yang kemungkinan akan ditangkap Rust adalah bagian yang sebenarnya diperbaiki di PR ini. Dalam praktiknya memori yang salah memang sempat disalin ke frame pertama, tetapi tidak pernah dipakai atau dikirim ke mana pun, jadi tidak terlalu serius. Tetap saja itu jelas tidak benar
    • Rust juga tetap membutuhkan manajemen memori dan lifetime manual di batas FFI dengan C/GObject. Borrow checker Rust tidak bisa memverifikasi penggunaan memori oleh kode eksternal
    • Salah satu poin tulisan itu adalah bahwa kombinasi zig + valgrind menghasilkan jauh lebih sedikit masalah memori daripada yang diduga
    • Menulis binding C dengan Rust jauh lebih sulit. Karena itu, membuat binding gtk dengan rust sendiri mungkin memang tidak akan berhasil
  • Saat memakai aplikasi berbasis GPU seperti Ghostty, Alacritty, WezTerm, Zed, dan lainnya, saya memang merasa lebih cepat dan lebih baik. Tetapi ironisnya, aplikasi semacam ini justru memperlihatkan dengan lebih jelas keterbatasan driver Nvidia. Dulu saya tidak sadar karena hampir tidak pernah memakai GPU, tetapi baik di lingkungan tanpa compositor seperti Regolith i3wm maupun di sway/wayland, driver nvidia benar-benar buruk dalam hal screen sharing, bangun dari sleep, crash, dan sebagainya. Saya sudah mencoba beberapa versi berbeda (550/560/575/580) dan semuanya sama saja. Baru belakangan ini saya sadar ternyata sudah seburuk ini sejak lama

    • Saya juga mengalami hal yang mirip di Wayland. Di X11, setelah efek compositing dimatikan, baik 1050Ti maupun kartu AMD lama saya yang butuh driver radeon berjalan baik tanpa masalah. Sebaliknya di Wayland ada stutter, crash, tampilan rusak, dan masalah lain
  • Saya pernah bisa membuat satu aplikasi besar tanpa membiarkan sistem tipe GTK memengaruhi kode saya. Tetapi sebagai gantinya, alih-alih memakai pewarisan kelas atau ekstensi, saya menghubungkan semua komponen hanya dengan binding lambda. Hasil akhirnya tidak terlalu berantakan, tetapi bagi pengembang yang terbiasa dengan gaya GTK yang ortodoks mungkin akan terasa membingungkan

  • Saya sendiri tidak mengerti hype berlebihan terhadap Ghostty. UI-nya hanya punya tab dan menu konteks, jadi saya ragu apakah integrasi dan rewrite seperti ini benar-benar layak. Saya menduga mereka mungkin ingin menambahkan lingkungan GUI yang kuat seperti iterm2. Kitty menggambar tab sendiri dengan OpenGL sehingga bisa dikustomisasi penuh, dan karena tidak membuang waktu untuk integrasi dengan framework yang rumit, ia bisa lebih cepat menghadirkan fitur yang sangat praktis seperti membungkus hasil perintah terakhir ke pager untuk ditampilkan. Kitty juga mendukung remote dengan baik

    • UI Ghostty tidak hanya tab, tetapi juga split, banner “proses telah selesai”, dialog konfirmasi penutupan, dialog perubahan judul, deteksi paste tidak aman, bel notifikasi animasi, terminal dropdown, progress bar, dan lebih banyak lagi dari yang terlihat. Di Mac juga ada integrasi Apple Shortcuts dan Spotlight. Tentu, semua ini pun sebenarnya bisa diimplementasikan secara murni tanpa GUI toolkit, tetapi misi Ghostty adalah memakai toolkit native tiap platform agar aplikasinya terasa “benar-benar native”. Kalau tidak suka pendekatan ini, memilih tab teks seperti Kitty juga pilihan yang baik. Orang bisa memilih sesuai nilai dan prioritas yang dikejar. Ke depan juga sedang disiapkan berbagai ekspansi GUI, serta integrasi mendalam dengan fitur native tiap platform seperti sinkronisasi iCloud
    • Soal klaim “Kovid mengimplementasikan fitur lebih cepat”, perlu hati-hati karena akun ini punya riwayat yang membuat saya curiga itu Kovid sendiri. Saya pernah melihatnya di HN dan Reddit berpura-pura memperkenalkan Kitty secara netral sambil mengkritik pengembang lain. Bahkan ada tautan yang menyarankan melihat riwayat komentarnya dulu
    • Selain penjelasan positif di atas, saya juga menganggap kemunculan ‘libghostty’ sebagai game changer. Seperti WebKit, ini adalah implementasi terminal yang kuat yang bisa langsung dipakai siapa saja sebagai drop-in
    • Saya juga pernah berpindah-pindah mencari terminal yang cocok, dan meskipun Ghostty tidak sepenuhnya ideal, saya akhirnya pindah ke sana ketika tidak menemukan hal lain yang cukup memuaskan. Itu sendiri sudah cukup berarti bagi saya. Sering kali justru bukan karena ada satu alasan penentu, melainkan karena tidak ada masalah besar yang membuat saya terus memakainya, dan itu adalah kelebihan tersendiri
    • Font terlihat jauh lebih bagus di Ghostty daripada di Kitty. Neovide memang lebih indah lagi, tetapi belum mendukung tab dan juga lebih boros baterai