1 pontos por GN⁺ 2026-01-11 | 1 comentários | Compartilhar no WhatsApp
  • Foi descoberto um vazamento grave no emulador de terminal Ghostty que, quando executado por longos períodos, podia consumir dezenas de GB de memória
  • A causa do problema era a lógica não padronizada de reutilização de páginas de memória na struct PageList, na qual munmap não era chamado, fazendo com que memória não liberada se acumulasse
  • Como o Claude Code CLI gera com frequência saídas de grafos com múltiplos code points, o uso de páginas não padronizadas aumentou, expondo o vazamento em grande escala
  • A correção foi alterada para não reutilizar páginas não padronizadas e liberá-las imediatamente, e o rastreamento e a validação do vazamento foram feitos com o uso do recurso de tags de VM do macOS
  • Essa correção é considerada a solução para o maior problema de vazamento do Ghostty e deve ser incluída em uma futura versão (1.3)

Visão geral do vazamento de memória do Ghostty

  • Alguns usuários relataram casos em que o Ghostty consumia mais de 37 GB de memória após ficar em execução por muito tempo
    • O vazamento existia pelo menos desde a versão 1.0, e aplicativos CLI recentes passaram a satisfazer certas condições que expuseram o problema
  • A correção já foi mesclada no GitHub e deve ser incluída nas builds nightly e na versão estável 1.3

Estrutura do PageList e forma de gerenciamento de memória

  • O Ghostty usa uma estrutura de lista duplamente ligada chamada PageList para armazenar o conteúdo do terminal
    • Cada página inclui dados como caracteres, estilos e hyperlinks
  • As páginas são alocadas com mmap e reutilizadas por meio de um pool de páginas de tamanho padrão
    • Páginas com tamanho igual ou inferior ao padrão retornam ao pool
    • Páginas de tamanho não padrão devem ser liberadas diretamente com munmap
  • A estrutura em si funciona corretamente, mas um bug na lógica de otimização causava o vazamento

Otimização do scrollback e causa do bug

  • Quando o Ghostty ultrapassa scrollback-limit, ele faz uma otimização que reutiliza a página mais antiga
    • O desempenho melhora porque apenas os ponteiros são ajustados, sem alocar uma nova página
  • O problema é que, nesse processo, apenas os metadados da página não padronizada eram alterados para o tamanho padrão, enquanto a memória real permanecia a mesma
    • Depois, ao liberar, ela era confundida com uma página padrão e munmap não era chamado
  • Como resultado, páginas não padronizadas não eram liberadas e se acumulavam, causando um grande vazamento de memória em execuções longas

Claude Code e a exposição do vazamento em grande escala

  • O Claude Code CLI gera com frequência saídas de grafos com múltiplos code points, o que aumenta a frequência de uso de páginas não padronizadas
    • Além disso, como há muita saída no scrollback, o vazamento se acumula rapidamente
  • Pelo design do Ghostty, páginas não padronizadas deveriam ocorrer raramente, mas as características do Claude Code fizeram com que o vazamento fosse reproduzido em grande volume
  • O desenvolvedor deixou claro que esse bug não é um problema do Claude Code, mas uma falha na lógica interna do Ghostty

Conteúdo da correção

  • A solução foi não reutilizar páginas não padronizadas e liberá-las imediatamente com munmap
    • Ao encontrar uma página não padronizada durante o scrollback, uma nova página padrão é realocada a partir do pool
  • Alguns usuários sugeriram uma estratégia de reutilização de páginas não padronizadas, mas por enquanto foi aplicada primeiro uma correção simples e segura
  • Exemplo de código da correção:
    if (first.data.memory.len > std_size) {
        self.destroyNode(first);
        break :prune;
    }
    

Rastreando o vazamento com tags de VM

  • Foi usado o recurso de tags de VM do kernel Mach no macOS para atribuir tags específicas às alocações de memória do PageList
    • Durante a depuração, isso permite identificar com clareza as áreas de memória do Ghostty
    • Também ajudou bastante a rastrear a causa do vazamento e validar a correção
  • Com esse recurso, foi possível confirmar visualmente se a memória relacionada ao PageList estava sendo liberada

Sistema de prevenção de vazamentos de memória do Ghostty

  • O Ghostty detecta e previne vazamentos de várias formas
    • Uso do alocador com detecção de vazamentos do Zig em builds de depuração e testes unitários
    • Execução de toda a suíte de testes com valgrind no CI
    • Inspeção de vazamentos no código Swift com o macOS Instruments
    • PRs relacionados a GTK são validados com testes de GUI no Valgrind
  • Esse vazamento, porém, só ocorria sob condições específicas, então os testes existentes não conseguiram reproduzi-lo
    • Um novo caso de teste foi adicionado para evitar regressões

Conclusão

  • Este caso foi confirmado como o maior vazamento de memória já encontrado no Ghostty
  • Mesmo após a correção, o problema continuará sendo monitorado por meio de relatos de usuários e testes de reprodução
  • Os dados de diagnóstico e os casos reproduzíveis fornecidos pela comunidade tiveram papel decisivo na resolução
  • Reforça-se que garantir um ambiente reproduzível é essencial para resolver vazamentos de memória

1 comentários

 
GN⁺ 2026-01-11
Comentários do Hacker News
  • Excelente notícia. Parabéns a todos que participaram da correção do problema
    Esse bug já tinha sido mencionado neste tópico na semana passada
    Parece que o Claude Code ajudou a expor esse bug para mais usuários, mas houve gente como eu que passou pelo mesmo problema mesmo sem usar Claude Code
    O critério para uma página ser classificada como “não padrão (non-standard)” não é tão preto no branco quanto parece
    Também acho que para quem usa configurações como scrollback-limit = 0, o vazamento pode ter acontecido com mais frequência
    Fica a sensação de que a forma como foi corrigido pode acabar apagando e recriando páginas não padrão sem necessidade, então talvez desse para reutilizar páginas antigas que já eram não padrão

    • Essa parte já foi abordada no post do blog
      O comportamento de PageList sempre foi o mesmo, e mesmo quando havia bug ele só via um tamanho incorreto durante o redimensionamento de capacidade
      Não deve haver mudança perceptível de desempenho
      A alternativa sugerida também foi considerada, mas a abordagem atual está bem sustentada por dados de benchmark
      Posso até mudar de ideia no futuro, mas desta vez foquei em corrigir o vazamento em vez de mudar toda a visão de mundo
    • Foi sorte conseguir encontrar o problema e reportá-lo ainda na fase beta
      Era, de fato, um bug reproduzível que causava segfault
    • Aliás, o Claude Code fez a CLI voltar a parecer algo empolgante
      Deixa a CLI com cara de novidade mais do que qualquer coisa nos últimos 20 anos
    • O tópico sobre o vazamento de memória está aqui
  • Ótimo texto. Obrigado ao mitchellh por criar o Ghostty
    Migrei no ano passado e não me arrependi nem um pouco
    Só achei um pouco surpreendente que a correção vá entrar numa release de funcionalidade daqui a alguns meses
    Eu esperava que entrasse numa release de correção de bugs

    • Já está incluída na nightly build mais recente
  • Assim que começou a falar de páginas, pensei “ah, é pooling de memória”, e depois “deve ser um buffer circular”, e no fim era mesmo reutilização do scrollback
    Também imaginei na hora onde estava o bug — na parte que não liberava corretamente a memória das páginas
    O diagrama de alinhamento de memória também ficou excelente
    Isso relembra como toda tentativa nova pode introduzir possibilidades de vazamento

  • Mudei para o Ghostty esta semana e, enquanto desenvolvia um app de UI para terminal, tive um crash por OOM
    A estrutura usava ícones UTF8 na barra de abas, e ao redimensionar o terminal o crash acontecia imediatamente
    Era tão fácil de reproduzir que eu já estava preparando um bug report, mas parece muito parecido com o problema explicado no post do blog
    Espero que seja resolvido

  • Pergunta para @mitchellh — que ferramenta foi usada para criar a visualização de memória? E, como o site funciona bem até no celular, fiquei curioso sobre a stack usada

    • Foi usado HTML/CSS estático gerado com Opus 4.5
      O código da visualização era descartável, então só validei a correção dele, não a qualidade
      Eu separo namespaces por post no blog e não reutilizo isso
      Só confirmei que a implementação não fazia nada estranho (como minerar bitcoin, vazar segredos etc.)
      O principal é transmitir a informação, e esse tipo de diagrama deixa o conteúdo muito mais fácil de entender
  • Continuo acompanhando o desenvolvimento do Ghostty
    Passa um pouco uma sensação de overengineering, mas esse tipo de post-mortem de bug é material valiosíssimo para quem ama capricho técnico

    • Fiquei curioso: em que sentido você sentiu overengineering?
  • Se fosse um terminal em Rust, fico curioso sobre como esse tipo de implementação seria feito sem perda de desempenho

  • Mesmo para quem não entende muito de Ghostty ou de emuladores de terminal, foi um texto fácil de acompanhar
    A acessibilidade e a didática da explicação chamaram atenção

  • Isso reforça a importância de um bug report reproduzível

  • Estou esperando alguém dizer “isso não teria acontecido se fosse em Rust”

    • Vai esperar bastante tempo
      Rust não garante "segurança contra vazamento de memória (leak safety)" no nível da linguagem
      Mesmo código Rust seguro pode vazar memória — só que isso não é um problema de segurança
      A própria API padrão permite vazamentos de forma explícita, como em Box::leak
      Rust apenas dificulta a criação de vazamentos não intencionais, mas não os impede completamente