1 điểm bởi GN⁺ 2026-01-11 | 1 bình luận | Chia sẻ qua WhatsApp
  • Trình giả lập terminal Ghostty được phát hiện có lỗi rò rỉ nghiêm trọng khiến nó chiếm dụng hàng chục GB bộ nhớ khi chạy trong thời gian dài
  • Nguyên nhân là do trong logic tái sử dụng các trang bộ nhớ không theo chuẩn của cấu trúc PageList, munmap không được gọi nên bộ nhớ không được giải phóng bị tích lũy dần
  • Claude Code CLI thường xuyên tạo đầu ra đồ thị đa code point, làm tăng tần suất sử dụng các trang không theo chuẩn, khiến lỗi rò rỉ bộc lộ ở quy mô lớn
  • Bản sửa đổi đã thay đổi để không tái sử dụng các trang không theo chuẩn mà giải phóng chúng ngay lập tức, đồng thời tận dụng tính năng VM tag của macOS để theo dõi và xác minh lỗi rò rỉ
  • Bản sửa này được đánh giá là đã giải quyết vấn đề rò rỉ lớn nhất của Ghostty và dự kiến sẽ được đưa vào bản phát hành sắp tới (1.3)

Tổng quan về lỗi rò rỉ bộ nhớ của Ghostty

  • Một số người dùng đã báo cáo trường hợp Ghostty sử dụng hơn 37GB bộ nhớ sau khi chạy trong thời gian dài
    • Lỗi rò rỉ này tồn tại ít nhất từ phiên bản 1.0, và gần đây các ứng dụng CLI đã thỏa mãn một số điều kiện nhất định để làm lộ vấn đề
  • Bản sửa đã được gộp vào GitHub và dự kiến sẽ có trong bản dựng nightly cũng như bản phát hành chính thức 1.3

Cấu trúc PageList và cách quản lý bộ nhớ

  • Ghostty sử dụng một cấu trúc danh sách liên kết đôi tên là PageList để lưu nội dung terminal
    • Mỗi trang chứa dữ liệu như ký tự, kiểu dáng, siêu liên kết, v.v.
  • Các trang được cấp phát bằng mmap và được tái sử dụng thông qua pool các trang kích thước chuẩn
    • Các trang có kích thước không vượt quá chuẩn sẽ được trả về pool
    • Các trang có kích thước không chuẩn phải được giải phóng trực tiếp bằng munmap
  • Bản thân cấu trúc này là bình thường, nhưng lỗi trong logic tối ưu hóa đã gây ra rò rỉ

Tối ưu hóa scrollback và nguyên nhân phát sinh lỗi

  • Khi vượt quá scrollback-limit, Ghostty thực hiện tối ưu hóa tái sử dụng trang cũ nhất
    • Chỉ điều chỉnh con trỏ thay vì cấp phát trang mới để cải thiện hiệu năng
  • Vấn đề là trong quá trình này, nó chỉ đổi metadata của trang không chuẩn thành kích thước chuẩn trong khi vùng nhớ thực tế vẫn giữ nguyên
    • Sau đó khi giải phóng, trang bị nhầm là trang chuẩn nên munmap không được gọi
  • Kết quả là các trang không chuẩn không được giải phóng mà tiếp tục tích lũy, gây ra rò rỉ bộ nhớ lớn khi chạy lâu dài

Claude Code và việc lỗi rò rỉ bộc lộ trên diện rộng

  • Claude Code CLI thường xuyên tạo đầu ra đồ thị đa code point, làm tăng tần suất sử dụng các trang không chuẩn
    • Ngoài ra, lượng đầu ra scrollback lớn khiến lỗi rò rỉ tích lũy nhanh hơn
  • Theo thiết kế của Ghostty, các trang không chuẩn lẽ ra phải hiếm khi xuất hiện, nhưng do đặc tính của Claude Code nên lỗi rò rỉ được tái hiện với số lượng lớn
  • Nhà phát triển nhấn mạnh rằng đây không phải lỗi của Claude Code mà là khiếm khuyết trong logic nội bộ của Ghostty

Nội dung bản sửa

  • Giải pháp là không tái sử dụng các trang không chuẩn mà giải phóng ngay (munmap)
    • Khi phát hiện trang không chuẩn trong scrollback, một trang chuẩn mới sẽ được cấp phát lại từ pool
  • Một số người dùng đã đề xuất chiến lược tái sử dụng trang không chuẩn, nhưng hiện tại bản sửa đơn giản và an toàn được ưu tiên áp dụng trước
  • Ví dụ mã sửa:
    if (first.data.memory.len > std_size) {
        self.destroyNode(first);
        break :prune;
    }
    

Theo dõi lỗi rò rỉ bằng VM tag

  • Sử dụng tính năng VM tag của nhân Mach trên macOS để gắn thẻ cụ thể cho phần cấp phát bộ nhớ của PageList
    • Khi debug có thể nhận diện rõ vùng bộ nhớ của Ghostty
    • Rất hữu ích trong việc lần theo nguyên nhân rò rỉ và xác minh bản sửa
  • Nhờ tính năng này có thể xác nhận trực quan việc bộ nhớ liên quan đến PageList có được giải phóng hay không

Cơ chế phòng chống rò rỉ bộ nhớ của Ghostty

  • Ghostty phát hiện và ngăn ngừa rò rỉ theo nhiều cách khác nhau
    • Dùng allocator phát hiện rò rỉ của Zig trong bản dựng debug và unit test
    • Chạy toàn bộ bài kiểm thử bằng valgrind trong CI
    • Kiểm tra rò rỉ của mã Swift bằng macOS Instruments
    • Các PR liên quan đến GTK được xác minh bằng Valgrind GUI test
  • Lỗi rò rỉ lần này chỉ xảy ra trong những điều kiện cụ thể nên các bài kiểm thử hiện có không tái hiện được
    • Một test case mới đã được thêm vào để ngăn ngừa hồi quy

Kết luận

  • Đây được xác nhận là trường hợp rò rỉ bộ nhớ lớn nhất từng được ghi nhận trong Ghostty
  • Sau khi sửa, vấn đề vẫn sẽ tiếp tục được theo dõi thông qua báo cáo từ người dùng và các bài kiểm thử tái hiện
  • Dữ liệu chẩn đoán và các trường hợp tái hiện do cộng đồng cung cấp đã đóng vai trò quyết định trong việc giải quyết vấn đề
  • Bài học được nhấn mạnh là việc có một môi trường có thể tái hiện được là chìa khóa để xử lý lỗi rò rỉ bộ nhớ

1 bình luận

 
GN⁺ 2026-01-11
Ý kiến trên Hacker News
  • Thật sự là một tin rất đáng mừng. Xin gửi lời tán dương tới tất cả những người đã tham gia giải quyết vấn đề này
    Đây là lỗi đã được nhắc đến từ tuần trước trong chuỗi này
    Có vẻ Claude Code là chất xúc tác khiến lỗi này lộ ra với nhiều người dùng hơn, nhưng cũng có những người như tôi chưa từng dùng Claude Code mà vẫn gặp đúng vấn đề đó
    Tiêu chí để một trang bị phân loại là “không tiêu chuẩn (non-standard)” hóa ra không hề kiểu trắng đen rõ ràng như tôi nghĩ
    Tôi cũng nghĩ rằng với những người dùng cấu hình như scrollback-limit = 0, tình trạng rò rỉ có thể đã xảy ra thường xuyên hơn
    Cách sửa hiện tại có thể sẽ xóa rồi tạo lại các trang không tiêu chuẩn một cách không cần thiết, nên tôi vẫn hơi tiếc là liệu có thể tái sử dụng các trang cũ vốn đã không tiêu chuẩn hay không

    • Phần đó đã được đề cập trong bài blog rồi
      Cách PageList hoạt động từ trước đến nay vẫn vậy, và ngay cả khi có lỗi thì nó cũng chỉ nhìn nhầm kích thước trong lúc điều chỉnh dung lượng thôi
      Sẽ không có thay đổi nào có thể cảm nhận được về hiệu năng
      Phương án thay thế bạn đề xuất cũng đã được cân nhắc, nhưng cách tiếp cận hiện tại đã được dữ liệu benchmark hậu thuẫn đủ mạnh
      Tôi vẫn có thể đổi ý, nhưng lần này tôi tập trung vào sửa rò rỉ hơn là thay đổi cả thế giới quan
    • Thật may là có thể phát hiện và báo cáo vấn đề khi còn ở giai đoạn beta
      Đây thực sự là một lỗi có thể tái hiện và gây ra segfault
    • Nhân tiện, nhờ Claude Code mà CLI lại trở nên hấp dẫn trở lại
      Nó khiến CLI trông mới mẻ hơn bất cứ thứ gì tôi thấy trong 20 năm qua
    • Chuỗi thảo luận về rò rỉ bộ nhớ nằm ở đây
  • Bài viết rất tuyệt. Cảm ơn mitchellh vì đã tạo ra Ghostty
    Tôi đã chuyển sang dùng từ năm ngoái và chưa từng hối hận
    Chỉ hơi bất ngờ là bản sửa sẽ được đưa vào một bản phát hành tính năng sau vài tháng
    Tôi cứ nghĩ nó sẽ nằm trong một bản phát hành sửa lỗi

    • Nó đã có sẵn trong nightly build mới nhất rồi
  • Ngay khi thấy nhắc đến các trang, tôi đã nghĩ “à, chắc là memory pooling”, rồi lại nghĩ “chắc là ring buffer”, và đúng là chuyện tái sử dụng scrollback
    Tôi cũng đoán ngay được lỗi nằm ở đâu — phần không giải phóng bộ nhớ của trang đúng cách
    Sơ đồ căn chỉnh bộ nhớ cũng rất đẹp
    Điều này lại nhắc tôi rằng mỗi lần thử một cách làm mới thì khả năng rò rỉ lại xuất hiện

  • Tuần này tôi mới chuyển sang Ghostty, và đã gặp OOM crash khi phát triển một ứng dụng UI cho terminal
    Cấu trúc của tôi dùng biểu tượng UTF8 trong thanh tab, và ứng dụng bị crash ngay khi thay đổi kích thước terminal
    Việc tái hiện rất dễ nên tôi đang chuẩn bị báo cáo lỗi, nhưng nó trông rất giống với vấn đề được giải thích trong bài blog
    Hy vọng chuyện này sẽ được giải quyết

  • Tôi đã hỏi @mitchellh — anh ấy dùng công cụ gì để làm phần trực quan hóa bộ nhớ, và website hoạt động tốt cả trên di động nên tôi tò mò về stack được dùng

    • Tôi dùng HTML/CSS tĩnh được tạo bằng Opus 4.5
      Mã cho phần trực quan hóa chỉ là đồ dùng một lần nên tôi chỉ kiểm tra độ chính xác chứ không đặt nặng chất lượng
      Tôi tách namespace theo từng bài blog và không tái sử dụng
      Tôi chỉ xác nhận là phần triển khai không làm trò kỳ quặc nào (ví dụ: đào Bitcoin, rò rỉ bí mật, v.v.)
      Điều cốt lõi là truyền đạt thông tin, và những sơ đồ như thế này giúp nội dung dễ hiểu hơn nhiều
  • Tôi vẫn đang tiếp tục theo dõi quá trình phát triển của Ghostty
    Có hơi cảm giác overengineering một chút, nhưng những bài hậu kiểm lỗi như thế này là tư liệu cực kỳ giá trị với những ai yêu sự thủ công tinh xảo

    • Tôi tò mò không biết ở khía cạnh nào mà bạn thấy nó là overengineering
  • Tôi tò mò nếu là terminal viết bằng Rust thì người ta sẽ xử lý kiểu triển khai này thế nào mà không bị tổn thất hiệu năng

  • Đây là một bài viết dễ hiểu ngay cả với người không rành về Ghostty hay terminal emulator
    Tôi rất ấn tượng với cách giải thích thân thiện và dễ tiếp cận

  • Điều này lại làm tôi cảm nhận rõ tầm quan trọng của một báo cáo lỗi có thể tái hiện được

  • Tôi đang chờ ai đó nói rằng “nếu dùng Rust thì đã không xảy ra chuyện này”

    • Có lẽ sẽ phải chờ lâu đấy
      Rust không bảo đảm “an toàn trước rò rỉ bộ nhớ (leak safety)” ở cấp độ ngôn ngữ
      Ngay cả mã Rust an toàn cũng có thể làm rò rỉ bộ nhớ — chỉ là đó không phải vấn đề về an toàn
      Ngay trong API chuẩn cũng có những thứ cho phép rò rỉ một cách tường minh như Box::leak
      Rust chỉ khiến việc tạo ra rò rỉ ngoài ý muốn trở nên khó hơn, chứ không thể ngăn chặn hoàn toàn