fix: Mark sessions as ended on cleanup to prevent stale registry entries#11
Open
greghughespdx wants to merge 2 commits into
Open
fix: Mark sessions as ended on cleanup to prevent stale registry entries#11greghughespdx wants to merge 2 commits into
greghughespdx wants to merge 2 commits into
Conversation
Problem: - When Claude sessions ended, cleanup() removed socket files but never marked sessions as inactive in the registry database - This left stale "active" entries that caused BrokenPipeError spam when slack_listener tried to send to non-existent sockets Solution: - Add END_SESSION command handler to session_registry.py - Add end_session() method to RegistryClient in wrapper - Modify cleanup() to mark session as ended BEFORE removing socket - Add idempotency guard to prevent double cleanup - Register SIGTERM/SIGINT handlers and atexit for graceful shutdown - Add defense-in-depth socket existence check in slack_listener Changes: - core/session_registry.py: Add END_SESSION command (~10 lines) - core/claude_wrapper_hybrid.py: Add end_session(), modify cleanup(), add signal handlers (~70 lines) - core/slack_listener.py: Add socket existence validation (~8 lines) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: end_session() silently fails when registry socket doesn't exist at cleanup time, leaving sessions in 'active' state. Changes: 1. RegistryClient.end_session(): - Removed premature socket existence check - Let connect() fail naturally with proper error handling - Changed exception type to be more specific 2. HybridPTYWrapper.cleanup(): - Try socket-based END_SESSION first - If that fails, use direct database access as fallback - Import RegistryDatabase and call db.end_session() directly - Make failures visible with stderr output and logging Verification: Sessions should now correctly show status='ended' in database even when registry socket is unavailable during cleanup. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
greghughespdx
marked this pull request as ready for review
January 11, 2026 03:21
Author
|
Thanks again for the cool wrapper. Great stuff! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When Claude sessions end, they leave stale "active" entries in the registry database. This can cause
slack_listenerto repeatedly attempt sending to non-existent sockets, resulting inBrokenPipeErrorspam in logs.This PR ensures sessions are properly marked as
status='ended'when the wrapper exits.Problem
cleanup()removed socket files but never updated the registry databaseslack_listenercontinued trying to send messages to dead socketsSolution
1. Add END_SESSION command to registry (
session_registry.py)New command handler that marks a session as ended without archiving the Slack thread (preserving thread for history).
2. Enhanced wrapper cleanup (
claude_wrapper_hybrid.py)end_session()method toRegistryClientcleanup()to mark session as ended BEFORE removing socket3. Defense-in-depth in listener (
slack_listener.py)Files Changed
core/session_registry.pycore/claude_wrapper_hybrid.pycore/slack_listener.pyTesting
claudesshowsstatus='ended'after session exitBreaking Changes
None - existing installations continue to work. Sessions that were previously left as "active" will now correctly show as "ended".