Skip to content

Session close and server shutdown leave session-scoped resources alive #1246

Open

Description

@morluto

Problem

Several session-scoped resources are only released by explicit per-resource close paths or full process disposal. When a session is archived or the daemon/server shuts down, live sessions and related server-side state can remain active longer than intended.

Observed cleanup gaps:

  • server shutdown disposes the DI graph without first closing live agent sessions
  • terminal records and pty processes are not cleaned up when a session closes
  • filesystem watcher entries are not disposed when a session closes
  • WebSocket broadcast per-session buffers, journal state, and in-flight turn tracking are not removed when a session closes
  • tool-call start timestamps can remain after interrupted/aborted turns

Expected behavior

Session archive and server shutdown should use the normal session/resource cleanup paths so session-owned processes, watchers, buffers, journals, and turn bookkeeping are released promptly.

Proposed fix

  • add a bulk live-session close path and call it during server shutdown before DI disposal
  • subscribe session-scoped services to session close events
  • drop per-session terminal, fs watcher, and WebSocket broadcast state on close
  • clear tool-call timing state on turn boundaries/abort paths

Scope

This issue is limited to session lifecycle cleanup. Longer-term retention policies for completed background tasks/subagents and unrelated timeout hardening can be handled in separate follow-ups.

Activity

  1. zhiyuan1i commented on Oct 19, 2026

    @zhiyuan1i

    A related minimal reproduction on 2.2.0:

    1. Create a session and subscribe to its WebSocket events.
    2. Submit a prompt and confirm that turn/prompt events arrive normally.
    3. Call POST /api/v1/sessions/{id}:archive, then POST /api/v1/sessions/{id}:restore.
    4. Re-subscribe to the session. A fresh WebSocket connection gives the same result.
    5. Submit another prompt.

    The prompt is accepted and completes: GET /api/v1/sessions/{id}/status returns busy=false. However, no turn.started, assistant.delta, thinking.delta, turn.ended, or prompt.completed events arrive. Only session.meta.updated is observed. A newly created session works normally.

    Expected: restoring a session also restores its event stream. Actual: the restored session executes prompts without emitting their events.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions