Turn 完成、Turn 中断和 Session Shutdown 是三个不同清理等级。普通 Turn 完成不会关闭 MCP 或杀掉所有后台 terminal;Interrupt 收走当前 Task,但 Thread 继续服务;只有 Session teardown 才关闭线程级长期资源。
资源按所有者分层
| 资源 | 所有者 | Turn 结束 | Session Shutdown |
|---|---|---|---|
| 模型 stream / tool future | RunningTask token tree | 结束或取消 | 先 abort active task |
| Git enrichment | TurnMetadataState | finish/abort 均取消 | 随 active task 清理 |
| UnifiedExec background process | ProcessManager | 可继续存在 | terminate all |
| Realtime conversation | RealtimeManager | 独立于普通 Turn | shutdown |
| Code Mode worker/session | CodeModeService | worker按 Turn 结束 | service shutdown |
| MCP prewarm/runtime | SessionServices | 跨 Turn 复用 | stop worker + close runtime |
| Guardian review session | Guardian manager | 按审查需要 | shutdown |
| LiveThread writer | Thread 生命周期 | flush terminal | shutdown writer |
shutdown_session_runtime 的真实顺序
Session teardown 先 abort startup prewarm 和 realtime,再 Interrupt active Task;随后清空 UnifiedExec 进程,关闭 Code Mode,停止 MCP prewarm。MCP refresh 使用的 gate 要先 acquire,随后 close gate并 shutdown runtime,防止刷新任务与关闭并发重建连接。最后关闭 Guardian 并运行 session-end hooks。
async def shutdown_session_runtime(session):
if prewarm := await take_startup_prewarm():
await prewarm.abort()
await realtime.shutdown()
await abort_all_tasks(INTERRUPTED)
await unified_exec.terminate_all_processes()
await code_mode.shutdown()
await stop_mcp_prewarm_worker()
async with mcp_refresh.acquire():
mcp_refresh.close()
await mcp_runtime.shutdown()
await guardian.shutdown()
await run_session_end_hooks()
ThreadStop lifecycle 在 runtime resources 停止后执行,使 extension contributor 能观察最终 thread/session stores。显式 Shutdown 随后关闭 LiveThread writer、发 ShutdownComplete 并结束 rollout trace。Submission channel 自然关闭也会运行 runtime teardown 和 ThreadStop;其完成信号由 submission loop termination future 解析。
ProcessManager 为什么先 drain map 再 terminate
terminate_all_processes 在锁内 drain 所有 ProcessEntry并清 reserved ids,然后释放锁,逐个注销网络审批并 terminate。若持有进程表锁等待操作系统终止,exit watcher或审批清理可能也需要这把锁,造成阻塞。
async def terminate_all(manager):
async with manager.process_store.lock() as store:
entries = list(store.processes.values())
store.processes.clear()
store.reserved_ids.clear()
for entry in entries:
await unregister_network_approval(entry)
entry.process.terminate()
从 map 先移除还防止新的 write_stdin 获得一个正在关闭的 process handle。物理退出由 process 的 cancellation/termination 和 watcher继续收尾。
评论
登录后即可评论