1 points par GN⁺ 2026-01-11 | 1 commentaires | Partager sur WhatsApp
  • Une fuite grave a été découverte dans l’émulateur de terminal Ghostty, pouvant consommer plusieurs dizaines de Go de mémoire après une longue période d’exécution
  • La cause du problème était liée à la logique non standard de réutilisation des pages mémoire de la structure PageList, où munmap n’était pas appelé, ce qui entraînait l’accumulation de mémoire non libérée
  • Comme Claude Code CLI génère fréquemment des sorties graphiques à points de code multiples, l’utilisation de pages non standard a augmenté, rendant la fuite visible à grande échelle
  • La correction a consisté à ne plus réutiliser les pages non standard et à les libérer immédiatement, avec suivi et validation de la fuite à l’aide de la fonction de tags VM de macOS
  • Cette correction est considérée comme la résolution de la plus importante fuite de Ghostty et sera incluse dans une prochaine version (1.3)

Vue d’ensemble de la fuite mémoire de Ghostty

  • Certains utilisateurs ont signalé que Ghostty utilisait plus de 37 Go de mémoire après être resté actif longtemps
    • La fuite existait au moins depuis la version 1.0, et des applications CLI récentes ont réuni certaines conditions qui ont révélé le problème
  • Le correctif a déjà été fusionné sur GitHub et sera inclus dans les builds nightly et la version stable 1.3

Structure de PageList et gestion de la mémoire

  • Ghostty utilise une structure de liste doublement chaînée appelée PageList pour stocker le contenu du terminal
    • Chaque page contient des données comme les caractères, les styles et les hyperliens
  • Les pages sont allouées avec mmap et réutilisées via un pool de pages de taille standard
    • Les pages de taille inférieure ou égale à la taille standard sont renvoyées dans le pool
    • Les pages de taille non standard doivent être libérées directement avec munmap
  • Cette structure n’avait rien d’anormal en soi, mais une erreur dans la logique d’optimisation a provoqué la fuite

Optimisation du scrollback et origine du bug

  • Lorsque Ghostty dépasse scrollback-limit, il applique une optimisation consistant à réutiliser la page la plus ancienne
    • Les performances sont améliorées en ajustant simplement les pointeurs, sans allouer de nouvelle page
  • Le problème vient du fait que, pendant ce processus, seules les métadonnées des pages non standard étaient modifiées pour indiquer une taille standard, alors que la mémoire réelle restait inchangée
    • Lors de la libération ultérieure, elles étaient alors prises pour des pages standard, et munmap n’était pas appelé
  • Résultat : les pages non standard n’étaient jamais libérées et s’accumulaient, provoquant une fuite mémoire massive sur les longues sessions

Claude Code et la visibilité à grande échelle de la fuite

  • Claude Code CLI produit fréquemment des sorties graphiques à points de code multiples, ce qui augmente la fréquence d’utilisation des pages non standard
    • En plus de cela, ses sorties de scrollback sont abondantes, ce qui accélère l’accumulation de la fuite
  • Dans la conception de Ghostty, les pages non standard sont censées rester rares, mais les caractéristiques de Claude Code ont permis de reproduire massivement la fuite
  • Le développeur précise que ce bug n’est pas un problème de Claude Code, mais bien un défaut de logique interne de Ghostty

Contenu du correctif

  • La solution consiste à ne plus réutiliser les pages non standard et à les libérer immédiatement avec munmap
    • Si une page non standard est rencontrée dans le scrollback, une nouvelle page standard est réallouée depuis le pool
  • Certains utilisateurs ont proposé une stratégie de réutilisation des pages non standard, mais une correction simple et sûre a été privilégiée dans l’immédiat
  • Exemple de code du correctif :
    if (first.data.memory.len > std_size) {
        self.destroyNode(first);
        break :prune;
    }
    

Traçage de la fuite avec les tags VM

  • La fonction de tags VM du noyau Mach sur macOS a été utilisée pour attribuer un tag spécifique aux allocations mémoire de PageList
    • En phase de débogage, cela permet d’identifier clairement les zones mémoire de Ghostty
    • Cela a grandement aidé à retracer l’origine de la fuite et à valider la correction
  • Cette fonctionnalité permet de vérifier visuellement si la mémoire liée à PageList est bien libérée

Dispositif de prévention des fuites mémoire dans Ghostty

  • Ghostty dispose déjà de plusieurs mécanismes pour détecter et prévenir les fuites
    • Utilisation de l’allocateur de détection de fuites de Zig dans les builds de débogage et les tests unitaires
    • Exécution de l’ensemble des tests avec valgrind dans la CI
    • Vérification des fuites dans le code Swift avec macOS Instruments
    • Validation des PR liées à GTK via des tests GUI Valgrind
  • Cette fuite ne se produisait que dans des conditions très spécifiques, ce qui explique pourquoi les tests existants ne la reproduisaient pas
    • Un nouveau cas de test a été ajouté pour éviter toute régression

Conclusion

  • Ce problème a été identifié comme le plus important cas de fuite mémoire observé jusqu’ici dans Ghostty
  • Même après le correctif, un suivi continu via les signalements utilisateurs et les tests de reproduction est prévu
  • Les données de diagnostic et les cas de reproduction fournis par la communauté ont joué un rôle décisif dans la résolution du problème
  • Le texte souligne qu’obtenir un environnement reproductible est essentiel pour résoudre les fuites mémoire

1 commentaires

 
GN⁺ 2026-01-11
Commentaires sur Hacker News
  • C’est vraiment une excellente nouvelle. Bravo à toutes les personnes qui ont participé à la résolution du problème
    C’était déjà le bug mentionné la semaine dernière dans ce fil
    Claude Code semble avoir contribué à exposer ce bug à davantage d’utilisateurs, mais certaines personnes, comme moi, ont rencontré le même problème sans jamais utiliser Claude Code
    Les critères selon lesquels une page est classée comme « non standard » sont moins binaires qu’on pourrait le penser
    Je pense aussi que la fuite a pu se produire plus souvent chez les personnes utilisant une configuration comme scrollback-limit = 0
    Je regrette un peu que la correction appliquée puisse supprimer puis recréer inutilement des pages non standard, alors qu’il aurait peut-être été possible de réutiliser d’anciennes pages déjà non standard

    • Ce point était déjà traité dans le billet de blog
      Le fonctionnement de PageList a toujours été le même, et même en présence du bug, il ne faisait que voir une taille incorrecte pendant le redimensionnement de capacité
      Il n’y aura pas de différence perceptible en performances
      L’alternative proposée a aussi été envisagée, mais l’approche actuelle est suffisamment étayée par les données de benchmark
      Je peux encore changer d’avis, mais cette fois-ci je me suis concentré sur la correction de la fuite plutôt que sur une remise à plat de l’architecture
    • C’était une chance de pouvoir repérer le problème et le signaler pendant la phase bêta
      C’était en fait un bug reproductible qui provoquait un segfault
    • À noter que Claude Code a redonné de l’attrait à la CLI
      Plus que n’importe quoi d’autre depuis 20 ans
    • Le fil sur la fuite mémoire est ici
  • Excellent article. Merci à mitchellh d’avoir créé Ghostty
    J’ai migré l’an dernier et je ne l’ai jamais regretté
    En revanche, j’ai été un peu surpris que le correctif soit inclus dans une release de fonctionnalité dans plusieurs mois
    Je m’attendais à le voir dans une release de correction de bug

    • C’est déjà inclus dans la dernière nightly build
  • Dès que la discussion sur les pages a commencé, je me suis dit : « ah, c’est du pooling mémoire », puis « ça doit être un ring buffer », et effectivement il s’agissait de réutilisation du scrollback
    J’ai aussi tout de suite deviné où se trouvait le bug — l’endroit où la mémoire des pages n’était pas correctement libérée
    Le diagramme d’alignement mémoire était aussi très réussi
    Cela rappelle une fois de plus que chaque nouvelle tentative introduit une possibilité de fuite

  • J’ai basculé sur Ghostty cette semaine, et j’ai subi un crash OOM pendant le développement d’une application d’interface terminal
    La structure utilisait des icônes UTF8 dans la barre d’onglets, et le terminal plantait immédiatement lors du redimensionnement
    Le problème était facile à reproduire, donc j’étais en train de préparer un bug report, mais cela ressemble beaucoup au problème décrit dans le billet de blog
    J’espère que ce sera résolu

  • Question à @mitchellh — avec quel outil as-tu réalisé la visualisation mémoire, et comme le site fonctionne très bien aussi sur mobile, je suis curieux de connaître la stack utilisée

    • J’ai utilisé du HTML/CSS statique généré par Opus 4.5
      Le code de visualisation était à usage unique, donc j’ai seulement vérifié son exactitude plutôt que sa qualité
      Je sépare les espaces de noms par billet de blog et je ne réutilise rien
      Je vérifie simplement que l’implémentation ne fait rien de bizarre (par ex. miner du bitcoin, exfiltrer des secrets, etc.)
      L’essentiel est de transmettre l’information, et ce type de diagramme rend le contenu beaucoup plus facile à comprendre
  • Je continue de suivre le développement de Ghostty
    Il y a un léger côté sur-ingénieré, mais ce genre de post-mortem sur un bug est une ressource extrêmement précieuse pour les personnes qui aiment le travail d’orfèvre logiciel

    • Je serais curieux de savoir sur quels points cela te donne une impression de sur-ingénierie
  • Je me demande comment un terminal basé sur Rust gérerait ce type d’implémentation sans perte de performances

  • Même sans bien connaître Ghostty ou les émulateurs de terminal, c’était un article facile à comprendre
    Son accessibilité et la pédagogie des explications m’ont marqué

  • Cela m’a rappelé l’importance des bug reports reproductibles

  • J’attends que quelqu’un dise : « si ça avait été écrit en Rust, ça ne serait jamais arrivé »

    • Tu risques d’attendre longtemps
      Rust ne garantit pas la « sécurité contre les fuites mémoire » (leak safety) au niveau du langage
      Même du code Rust sûr peut fuir de la mémoire — ce n’est simplement pas un problème de sûreté
      L’API standard permet même explicitement les fuites, avec Box::leak par exemple
      Rust rend simplement les fuites involontaires plus difficiles à introduire, sans les empêcher complètement