环境
- Qoder 1.27.1(macOS arm64)
- macOS 25.5.0
- ptyhost 进程(
Qoder Helper,node-pty)连续运行约 22 小时
现象
系统 Terminal.app 与 VS Code 集成终端均无法新建窗口/标签页:
[forkpty: Device not configured]
[未能创建新的进程和打开伪终端(pseudo-tty)。]
只有重启 Mac 或彻底退出 Qoder 才能恢复,之后继续使用会复发。
根因
macOS 内核 pty 上限为 511(kern.tty.ptmx_max)。ptyhost 每次 spawn 一个 shell 进程就分配一个 pty,子进程正常退出后 master fd 从不关闭,持续累积直到占满全表:
# pty 表已满:动态节点数 = 内核上限
$ ls /dev/ttys[0-9a-f][0-9a-f][0-9a-f] | wc -l
511
# 全部 511 个 master fd 均由 ptyhost 持有
$ lsof /dev/ptmx | awk 'NR>1 {print $1, $2}' | sort | uniq -c | sort -rn
511 Qoder 27685
$ lsof -p 27685 | grep -c /dev/ptmx
511
关键证据:日志与泄漏数严格对应
~/Library/Application Support/Qoder/logs/<session>/ptyhost.log 中共 510 条 Process exited 记录(id 1–511,全部 exitCode: 0),加上当前活跃的 1 个会话 = 511,与泄漏的 master fd 数完全一致:
2026-08-31 12:21:26.124 [info] [PtyService] Initializing, pid: 27685, graceTime: 60000
2026-08-31 12:21:32.200 [info] [PtyService] Process exited, id: 1, exitCode: 0
...
2026-09-01 10:20:10.734 [info] [PtyService] Process exited, id: 511, exitCode: 0
即:每一个已退出的 shell 进程,其 master fd 都没有被释放。泄漏速率与使用强度一致(重度使用 Agent 的 Bash 工具时约每小时 30–66 个,夜间闲置时为 0),一个工作日左右即填满 511 上限,导致整机终端不可用。
复现步骤
- 启动 Qoder,正常使用会 spawn shell 的功能(Agent 执行 Bash 命令 / 打开关闭集成终端)
- 观察 master fd 数单调增长,进程退出后不下降:
lsof -p <ptyhost_pid> | grep -c /dev/ptmx
- 累计到 511 后,系统所有应用的 forkpty 均失败
期望行为
子进程退出后应关闭对应的 master fd。推测是 node-pty 的 exit/close 路径未释放句柄,或 terminal session 对象未被 dispose/GC。
其他
ptyhost 启动时还有一条报错,不确定是否与泄漏相关:
[error] Failed to set sticky bit on /private/var/folders/.../T/<user>-qoder-zsh: ENOENT: no such file or directory, chmod '...'
临时规避
彻底退出 Qoder(⌘Q)即可释放全部 master fd,无需重启系统。
环境
Qoder Helper,node-pty)连续运行约 22 小时现象
系统 Terminal.app 与 VS Code 集成终端均无法新建窗口/标签页:
只有重启 Mac 或彻底退出 Qoder 才能恢复,之后继续使用会复发。
根因
macOS 内核 pty 上限为 511(
kern.tty.ptmx_max)。ptyhost 每次 spawn 一个 shell 进程就分配一个 pty,子进程正常退出后 master fd 从不关闭,持续累积直到占满全表:关键证据:日志与泄漏数严格对应
~/Library/Application Support/Qoder/logs/<session>/ptyhost.log中共 510 条Process exited记录(id 1–511,全部exitCode: 0),加上当前活跃的 1 个会话 = 511,与泄漏的 master fd 数完全一致:即:每一个已退出的 shell 进程,其 master fd 都没有被释放。泄漏速率与使用强度一致(重度使用 Agent 的 Bash 工具时约每小时 30–66 个,夜间闲置时为 0),一个工作日左右即填满 511 上限,导致整机终端不可用。
复现步骤
期望行为
子进程退出后应关闭对应的 master fd。推测是 node-pty 的 exit/close 路径未释放句柄,或 terminal session 对象未被 dispose/GC。
其他
ptyhost 启动时还有一条报错,不确定是否与泄漏相关:
临时规避
彻底退出 Qoder(⌘Q)即可释放全部 master fd,无需重启系统。