blog
Trang nén Mac nhảy từ 5% lên 30% vì một vòng lặp chờ log
Một subagent của Claude Code chờ log e2e bằng vòng lặp đọc /dev/zero. Một process bash phình tới 47,7 GB, số trang nén của Mac nhảy từ 5% lên 30% giới hạn trong khi RAM vẫn báo trống 71%.
- Ngày đăng
Ngày 02/11/2026, số trang trong bộ nén của Mac tôi nhảy từ 5% lên 30% giới hạn chỉ trong vài phút, trong khi RAM vẫn báo khả dụng 71%. Thủ phạm là một process bash do subagent của Claude Code tự sinh ra để chờ log, và vmmap báo Physical footprint của nó là 47,7 GB trên một máy 32 GB.
Đây là bài thứ ba trong chuỗi về giới hạn số trang nén của macOS, sau kernel panic data.kalloc.1024 và vụ WebKit của Playwright. Lần này máy không panic, nhưng nguyên nhân khác hẳn 2 lần trước.
13:05 đến 13:14: trang nén từ 5% lên 30%, RAM vẫn trống 71%
Máy là Mac Studio 32 GB, macOS 26, khoảng 10 phiên Claude Code chạy song song trong tmux. Dashboard theo dõi báo "Trang nén" từ 5% lên 27 đến 30% giới hạn trong khoảng 13:05 đến 13:14.
Giới hạn đó là sysctl vm.compressor.pages_compressed_limit, trên máy này bằng 13.192.448 trang. Mốc 85% là ngưỡng script canh xin khởi động lại, còn 100% là panic như vụ 31/10.
Các chỉ số khác trong cùng lúc không có gì bất thường:
| Chỉ số | Giá trị |
|---|---|
| RAM khả dụng | 71% |
| Áp lực bộ nhớ | mức 1 |
| Dung lượng bộ nén | 6,5 GB |
| IOSurface | 384, đứng yên |
IOSurface đứng yên nghĩa là lần này không phải WebKit như vụ 31/10. Chỉ có một dòng lạ trong danh sách process chiếm nhiều bộ nhớ: bash 5,3G.
Thủ phạm: vòng lặp chờ log của một subagent
Một subagent của một phiên dự án đang chờ bộ e2e chạy xong, nên nó viết vòng lặp này:
for i in $(seq 1 55); do
grep -qE "passed" e2e-full.log && break
read -t 9 < /dev/zero || true
done
Ý của nó là ngủ 9 giây giữa 2 lần kiểm log. Nó không dùng sleep vì harness của Claude Code chặn lệnh sleep chạy foreground, nên model tự chế cách chờ khác.
Vì sao bash phình tới 47,7 GB mà RAM vẫn báo trống
read đọc cho tới khi gặp ký tự xuống dòng. /dev/zero chỉ trả byte 0 và không bao giờ có xuống dòng, nên bash gom byte 0 vào buffer suốt 9 giây của mỗi vòng, cho tới khi -t 9 ngắt.
vmmap --summary của process bash đó cho Physical footprint là 47,7 GB. RSS chỉ 5,3 GB, đúng con số bash 5,3G ở danh sách process chiếm nhiều bộ nhớ, vì phần còn lại đã bị nén.
Trang toàn số 0 nén cực tốt. Vì thế RAM vẫn "trống", bộ nén chỉ phình tới 6,5 GB, và chỉ có số trang trong bộ nén tăng vọt.
Truy ra process bằng ps và vmmap
Khi trang nén tăng mà RAM và IOSurface đều bình thường, tìm process bash con của claude:
ps -axo pid,ppid,rss,etime,command -m | head
vmmap --summary <pid> | grep "Physical footprint"
Tham số lệnh của process bash đó hiện ngay read -t 9 < /dev/zero. Cờ -m sắp xếp theo bộ nhớ, và etime cho biết nó chạy được bao lâu.
Không kill được: chờ vòng lặp tự kết thúc
Lệnh kill process bash bị auto mode của Claude Code chặn, lý do "Interfere With Workloads".
13:14 vòng lặp xong, trang nén về 7%. Từ 13:14 đến 13:19 là lượt chờ cuối của subagent: trang nén lên 15% rồi về 6%.
Cách sửa: hook chặn đọc /dev/zero, không dặn trong prompt
Dặn subagent "đừng chờ bằng /dev/zero" không đủ, vì lời dặn trong prompt không chặn được một agent đang tìm đường lách. Hook thì chặn được, kể cả subagent.
Hook PreToolUse ram-gate giờ luôn deny lệnh Bash đọc /dev/zero hoặc /dev/urandom vào read hay vào biến:
read … < /dev/zerocat /dev/zero | read$(< /dev/zero)$(cat /dev/urandom)
Lệnh có giới hạn kích thước vẫn qua: head -c N /dev/urandom, dd … count=N.
Cái giá: hook khớp theo chuỗi trong lệnh, nên chuỗi đó nằm dưới dạng chữ (pattern của grep, heredoc) cũng bị chặn nhầm.
Cách chờ đúng
- Chạy lệnh dài ở nền rồi đợi thông báo khi nó thoát.
- Hoặc dùng
Monitorvới vònguntilkiểm điều kiện.
Bài học: chỉ số RAM trống nói dối, luật cứng phải nằm trong hook
- Chỉ số "RAM trống" nói dối khi dữ liệu toàn số 0. Phải theo dõi số trang nén trên giới hạn, không chỉ dung lượng bộ nén.
- Cùng một con số trang nén tăng có thể do kernel (IOSurface ở vụ 31/10) hoặc do một process người dùng.
pscộngvmmapphân biệt được 2 trường hợp trong vài giây. - Agent tự chế cách lách luật:
sleepbị chặn thì thànhread < /dev/zero. - Luật cần cưỡng chế thì đặt bằng hook, vì hook chặn cả subagent còn lời dặn thì không.
Bài viết liên quan
tất cả bài viết →- Mac còn 65% RAM vẫn sắp panic: bộ nén, IOSurface và WebKit của PlaywrightMac Studio 32 GB panic với 100% of compressed pages limit, rồi tối cùng ngày suýt panic lần hai khi RAM vẫn báo trống 65%. Thứ bị đầy là số trang trong bộ nén, và thủ phạm là IOSurface do WebKit của Playwright để lại trong kernel.đọc tiếp →
- Kernel panic data.kalloc.1024 trên Mac khi chạy nhiều phiên Claude CodeMac Studio 32 GB chạy khoảng 20 phiên Claude Code tự khởi động lại 5 lần vì vùng nhớ kernel data.kalloc.1024 rò tới khoảng 20 GB. Cách theo dõi bằng zprint, vì sao bản cài npm làm rò nhanh hơn, và 3 bước đã chặn được nó.đọc tiếp →
- REA: cho agent dịch ngược phần mềm, rồi kiểm luôn cái oracleREA cho coding agent đọc một chương trình không có source, xuống tới machine code, rồi dựng lại tính năng đó bằng code của mình. Bản dựng lại đúng hay sai do oracle quyết định, và oracle cũng là code, cũng có bug.đọc tiếp →
- Top 10 skill Claude Code nên cài, xếp theo sao GitHub: bộ nào làm gì, bộ nào đè lên nhau10 bộ skill cho Claude Code có nhiều sao GitHub nhất tại 29/10/2026: Superpowers, Matt Pocock Skills, Karpathy Skills, Anthropic Skills, Ponytail, UI UX Pro Max, Graphify, Caveman, Agent Skills, Taste Skill. Mỗi bộ có lệnh cài, việc nó làm và chỗ nó trùng với bộ khác.đọc tiếp →