github / github/copilot-cli

Sessions become unrevivable: a stale `inuse.<pid>.lock` from a crashed host is never reclaimed on open

未关闭
#4,805 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

triage
主要语言
Shell
星标
11.2k
派生
1.9k
平均合并
14 小时 16 分钟
30 天内合并 PR
6

描述

Describe the bug

Several saved sessions became impossible to reopen ("crashed out / unrevivable"). On investigation the session data was not corrupt — the append-only events.jsonl replayed cleanly and the engine logged a successful resume. The sessions were blocked by runtime/lifecycle issues, not data loss.

The primary cause is stale lock handling. Each live session writes ~/.copilot/session-state/<id>/inuse.<pid>.lock. When the owning copilot --server process exits uncleanly (crash, force-quit, OS kill), the lock file is left behind. On the next open, the session is treated as in-use / unrevivable instead of checking whether that PID is still alive.

Scanning one local store, 14 of 184 sessions (~8%) carried a fault signature; 8 held an inuse.<pid>.lock whose PID was dead. Deleting the stale lock made each session openable again, and the app then spawned a fresh host and resumed normally — confirming the data was fine and only the lock blocked recovery.

Three related lifecycle defects compound the impact (details under Additional context):

  1. Orphaned engine host after a failed UI attach — the engine resumes but no session host registers, leaving a live server holding the lock (which then becomes defect #1 on the next attempt).
  2. MCP OAuth timeouts block session readiness — resume stalls ~5 minutes on OAuth callback timeout before the session is interactive, so users abort.
  3. Unbounded events.jsonl makes replay hang on large/old sessions (appears to overlap #4251).
Affected version

1.0.83 (copilot --server --stdio --no-auto-update)

Steps to reproduce the behavior

Primary defect (stale lock not reclaimed):

  1. Open a session, then hard-kill its copilot --server process to simulate a crash / force-quit (kill -9 <pid>).
  2. Confirm ~/.copilot/session-state/<id>/inuse.<pid>.lock remains, now pointing at a dead PID.
  3. Try to reopen the session → it does not revive.
  4. rm the stale lock file → the session reopens and resumes cleanly (a fresh host is spawned and events.jsonl replays without error).
Expected behavior

On open, if the lock's PID is dead or a zombie, the app should reclaim the session automatically rather than treating it as in-use. A liveness check combined with a PID start-time comparison avoids the classic PID-reuse race. Recoverable work should never be gated behind a leftover lock file that only manual filesystem surgery can clear.

Additional context
  • OS: macOS · shell: zsh

Defect 2 — orphaned engine host after a failed UI attach. Engine log from a single resume: the host never registers, yet the engine reports the session resumed, so the process lingers as an orphan holding the lock:

[WARNING] [rust:copilot_runtime::session::pending_request_flow] pending-request event was not delivered to the session host
          {"error":"GenericFailure, no session host is registered for session <id>"}
...
[INFO]  Resumed session: <id>        (logged repeatedly)

Suggested fix: tie the engine host's lifetime to successful UI host registration; if registration fails/times out, tear the host down and release the lock.

Defect 3 — MCP OAuth timeouts block resume (~5 min). With several MCP servers configured, resume stalls until interactive OAuth flows time out. MCP init begins at 20:27, first hard failures at 20:32:

[ERROR] [rust:mcp_engine::session_authorizer] OAuth login failed after returning its authorization URL
        {"server_name":"...","error":"OAuth callback timeout"}

During that window the session looks hung and users abort — observed as sessions whose only recent events were resume → abort (user_initiated) → shutdown, twice in a row. Suggested fix: make MCP init lazy / non-blocking; never gate session interactivity on MCP OAuth.

Defect 4 — unbounded events.jsonl. The append-only log grows without bound; worst local session reached 38.6 MB / ~13k events with 42 compaction cycles (173 re-injected system.message events ≈ 10.7 MB). Reopening replays the whole log, so large sessions hang on open even though nothing is corrupt. This looks like the same root cause as #4251; noting here for linkage. Suggested fix: snapshot-and-truncate the event log at compaction so replay cost stays bounded.

Possibly related: #4020 (session falsely "already in use by another client"), #4098 (truncated/concatenated events on resume), #4138 (resume compaction hangs), #4251 (large-session resume OOM/hang).

All four are addressable without changing the on-disk event format. Defects 1–2 turn recoverable work into apparent data loss; 3–4 make large/older sessions feel dead on open.

贡献指南

打开贡献指南

从这里开始

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

调研方向

首先跟踪 ~/.copilot/session-state//inuse..lock 的 session-open 处理以及 copilot --server 的生命周期。复现强制终止的情况,然后检查 Rust 会话运行时中与锁回收和主机注册相关的部分;当已死亡或处于 zombie 状态的 PID 不再阻止重新打开,并且会话无需手动移除锁即可恢复时,主要缺陷就算完成修复。OAuth 和 events.jsonl 相关问题应作为独立范围处理。

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

评估

技术栈
rust
领域
backend, cli
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
活跃
描述清晰度
基本清楚
新手友好度
45/100

把新 issue 发到你的邮箱

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