Skip to content

HubClient: Process+Pipe deadlock when curl stdout exceeds pipe buffer #10

Description

@NorveraFlorent

menubar/HubClient.swift 三处用同一个死锁配方调 curl:

  • enrichScanResults() line 74-85 → GET /instances
  • fetchHubChannels() line 134-143 → GET /channels
  • getUsedTags() line 162-171 → GET /instances
try task.run()
task.waitUntilExit()                                       // ① 等 curl 退出
let data = pipe.fileHandleForReading.readDataToEndOfFile() // ② 再读

当 stdout 超过 Darwin pipe buffer(典型 16-64KB,非确定性),curl 在 write() 阻塞 → launcher 在 waitUntilExit() 也阻塞 → 永久死锁。setTag / setDescription (line 261, 277) 用 nullDevice 不读不等,不受影响

级联效应

enrichScanResults 死锁后,SessionScanner.swift:90onEnrich?() 同步调用永不返回 → scanActiveSessions 卡死 → scanSessionsInBackground 中 line 105+ 的 scan-sessions.py 子进程从未被调用(用 trace wrapper 实测 5 分钟内 0 次触发);isScanning=true 永久保持,后续 30s timer 全 skip;UI 显示「0 条会话」且通道按钮隐藏(hubEverOnline=false)。

复现

让 hub /instances 返回 > 64KB JSON(长期运行的机器上累积 ~500+ known instances;或本地 mock 一个返回 100KB 的 endpoint),打开 launcher → sample <pid> 3 显示 100% 时间在 enrichScanResults,UI 空。

建议修法

最小改(每个 callsite 一行):

try task.run()
let data = pipe.fileHandleForReading.readDataToEndOfFile()  // 先读干 pipe
task.waitUntilExit()

对 curl 安全(curl 关 stdout 后 readDataToEndOfFile 立即返回)。

附加防线:curl args 加 --max-time 5——现在只有 --connect-timeout 2,read 阶段无上限。

环境

  • forge-launcher: HEAD (cd7a153)
  • macOS 25.5.0 (Darwin arm64)
  • 关联:forge-hub /instances unbounded growth issue(同时提交)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions