Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

unixTerminal: input is silently queued forever when libuv threadpool completions stop arriving (CustomWriteStream has no watchdog)

未关闭
#939 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

@nireak 已经在做这个了。

开始于 2026年8月18日。

  • #956 来自 @nireak —— 未关闭

评估

难度
4/5
预计耗时
3-5 天
新手友好度
52/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
冷清
技术栈
electron, node.js, typescript
领域
cli

调研方向

从 CustomWriteStream.write() 和 _processWriteQueue() 开始,重点关注 fs.write 完成后队列如何继续推进。运行基于 FIFO 的确定性复现,并检查 threadpool 回调停止到达时的队列行为。Done 应包含针对停滞输入的明确定义的恢复或失败信号,并由回归测试提供支持。

由索引模型根据 Issue 内容生成。

描述

Environment

  • node-pty 1.1.0 (CustomWriteStream write path from #833)
  • Electron app (pty host runs in a utility process), macOS 15 / darwin arm64

Issue

CustomWriteStream.write() queues data and relies on the async fs.write completion callback to advance the queue:

  • write() only starts processing when the queue transitions 0 → 1
  • _processWriteQueue() issues one fs.write and continues from its callback

fs.write completes on the libuv threadpool. If the pool stops delivering completions — which we observed live in production: all 4 workers idle in pthread_cond_wait, submitted work never picked up, event loop perfectly healthy — the callback never fires, the queue head never advances, and every subsequent write() appends to the queue forever. There is no error, no timeout, and no log: from the embedder's perspective the terminal simply stops accepting input while output (event-loop reads) keeps flowing. Terminal.write() returns void, so the embedder cannot observe or mitigate this from outside.

We confirmed this mechanism while investigating Orca's long-running "terminal intermittently stops accepting input" issue (stablyai/orca#8104). In the live wedged process, _writeQueue held every lost keystroke with the first task still at offset: 0, and hot-patching write to fs.writeSync restored input instantly — the fd was fine, only the threadpool path was dead.

We're investigating the Electron/libuv threadpool wedge separately. This issue is about how node-pty behaves when it happens: input stays queued indefinitely with no error and no recovery path.

Deterministic repro

The wedge can be simulated exactly by pinning every threadpool worker with a FIFO reader-open (blocks in open() until a writer appears):

const fs = require('fs');
const pty = require('node-pty');
const { execFileSync } = require('child_process');

execFileSync('mkfifo', ['/tmp/stall.fifo']);
const p = pty.spawn('/bin/sh', ['-c', 'read line; echo "GOT:$line"'], {});
p.onData((d) => process.stdout.write(d));

setTimeout(() => {
  for (let i = 0; i < 6; i++) fs.open('/tmp/stall.fifo', 'r', () => {});
  setTimeout(() => {
    p.write('hello\n');           // never reaches the shell
    fs.stat('/tmp', () => console.log('pool alive')); // never prints
  }, 300);
}, 300);
主要语言
TypeScript
星标
2k
派生
341
平均合并
1 天 1 小时
30 天内合并 PR
7

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

microsoft/node-pty 的其他 Issue

查看 microsoft/node-pty 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。