github / github/copilot-cli

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

Đang mở
#4,805 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

triage
Ngôn ngữ chính
Shell
Star
11.2k
Fork
1.9k
Merge trung bình
14 giờ 16 phút
Pull request đã merge (30 ngày)
6

Mô tả

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.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Bắt đầu bằng cách lần theo việc xử lý session-open đối với ~/.copilot/session-state//inuse..lock và vòng đời của copilot --server. Tái hiện trường hợp bị kết thúc cưỡng bức, sau đó kiểm tra runtime phiên Rust liên quan đến việc thu hồi lock và đăng ký host; lỗi chính được xem là đã hoàn tất khi một PID đã chết hoặc zombie không còn chặn việc mở lại và phiên tiếp tục mà không cần xóa lock thủ công. Các vấn đề về OAuth và events.jsonl nên được xử lý trong phạm vi riêng.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
rust
Lĩnh vực
backend, cli
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Sôi nổi
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
45/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.