关闭聊天窗口时的处理机制

当用户发送消息后未收到回复就关闭聊天窗口(终端/Tab),Claude Code 的处理流程。


1. 信号触发

平台 信号 检测方式
Linux / WSL SIGHUP 终端关闭时内核发送
macOS TTY 吊销 无 SIGHUP,靠 30s 轮询检查 process.stdout.writable
Windows SIGTERM 窗口关闭事件
用户主动 Ctrl+C SIGINT 键盘中断

处理入口:gracefulShutdown.tssetupGracefulShutdown()(注册于 entrypoints/init.ts:87)。


2. 取消正在进行的 API 请求

scss 复制代码
SIGHUP/SIGTERM/SIGINT
  → gracefulShutdown()
    → cleanupTerminalModes()       ← 恢复终端模式
    → printResumeHint()            ← 打印 "Resume with: claude --resume <id>"
    → 此时 AbortController 已被触发:
      queryLoop 中的 signal.aborted == true
      → anthropic.beta.messages.create({...params, stream: true}, { signal })
        中的 signal 触发 → SDK 抛出 APIUserAbortError
      → stream 被取消,不再接收后续数据

关键路径:用户发送消息时 onQueryImpl 创建一个 AbortControllerREPL.tsx:4010),其 signal 传入 queryModel() → 传给 Anthropic SDK 的 messages.create() 作为 abort signal。shutdown 时该 controller 被 abort,SDK 中断 HTTP 流。


3. 刷新会话持久化

typescript 复制代码
// gracefulShutdown.ts:445
await runCleanupFunctions()
  → Project.flush()                    ← 将内存中 100ms 队列的待写入消息刷到 JSONL
  → Project.reAppendSessionMetadata()  ← 重新写入 session 元数据到文件尾部

已发送的用户消息已收到的部分助手回复(如果有)会被写入 JSONL。如果一条消息都没收到,则只记录用户消息。


4. 执行 SessionEnd hooks

typescript 复制代码
// gracefulShutdown.ts:473
await executeSessionEndHooks(reason, { signal, timeoutMs })

允许用户配置的 SessionEnd hooks 执行(默认 1.5s 超时)。


5. failsafe 兜底

typescript 复制代码
// gracefulShutdown.ts:417
failsafeTimer = setTimeout(
  () => { cleanupTerminalModes(); printResumeHint(); forceExit(code); },
  Math.max(5000, sessionEndTimeoutMs + 3500),
)

若上述异步清理挂起超过 5 秒(或 hook timeout + 3.5s),强制退出进程。


6. 退出后

  • 打印 Resume this session with: claude --resume <sessionId> 提示
  • 进程 exit code = 129 (SIGHUP) / 143 (SIGTERM) / 0 (Ctrl+C)
  • JSONL 文件保留在磁盘上供后续 resume
  • 消息已部分写入 JSONL --- resume 后会看到已发送的消息,但回复可能不完整或不存在(取决于当时流到了哪里)

关键要点

问题 答案
已发送的消息会丢吗? 不会 --- runCleanupFunctions() 会将内存队列 Flush 到 JSONL
已收到的部分回复会保存吗? --- 已 yield 的 assistant message 片段已写入
API 会继续处理吗? 不会 --- abort signal 取消后,API 收到 TCP 断开继续处理但结果被丢弃
能恢复会话继续吗? 可以 --- claude --resume <sessionId> 重新加载 JSONL 恢复上下文继续对话
相关推荐
武子康4 小时前
🔥 codex-plugin-cc 原理全拆:四层桥接 + JSON-RPC 2.0 + JSONL + 后台任务状态机
人工智能·llm·claude
kyriewen17 小时前
看了微软几万人用AI编程的数据——效率涨24%的代价没人提
前端·ai编程·claude
武子康1 天前
OpenAI 把 Codex 接进 Claude Code:Coding Agent 从单兵工具进入协作系统
人工智能·openai·claude
喜欢天文的1 天前
一个桌面应用,如何把 7 个 AI 编程工具全部"中间人"掉——CC Switch 深度拆解(上)
claude
洛卡卡了1 天前
Claude Code 项目级 Skill:团队协作场景下的使用场景
人工智能·后端·claude
Lazy_zheng2 天前
TDD 实战:Claude Code Superpowers 保姆级教程14 个 Skills 全解析 + 实战开发
前端·claude·vibecoding
plainGeekDev3 天前
多步流水线 + HereDoc:一条脚本完成全自动内容生产
aigc·ai编程·claude
码哥字节3 天前
spec-superflow 上手指南:6 平台安装
claude
小狼1833 天前
实践3|用 Claude Code 从需求文档走到集成测试打通真数据库
claude
冬奇Lab3 天前
开源项目第157期:archify — 用自然语言生成可主题切换、高分辨率导出的架构图
人工智能·架构·claude