fix(crew): don't kill pane processes when creating new session
KillPaneProcesses was being called on new sessions before respawn, which killed the fresh shell and destroyed the pane. This caused "can't find pane" errors on session creation. Now KillPaneProcesses is only called when restarting in an existing session where Claude/Node processes might be running and ignoring SIGHUP. For new sessions, we just use respawn-pane directly. Also added retry limit and error checking for the stale session recovery path. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,9 @@ import (
|
|||||||
"github.com/steveyegge/gastown/internal/workspace"
|
"github.com/steveyegge/gastown/internal/workspace"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// crewAtRetried tracks if we've already retried after stale session cleanup
|
||||||
|
var crewAtRetried bool
|
||||||
|
|
||||||
func runCrewAt(cmd *cobra.Command, args []string) error {
|
func runCrewAt(cmd *cobra.Command, args []string) error {
|
||||||
var name string
|
var name string
|
||||||
|
|
||||||
@@ -210,19 +213,11 @@ func runCrewAt(cmd *cobra.Command, args []string) error {
|
|||||||
if runtimeConfig.Session != nil && runtimeConfig.Session.ConfigDirEnv != "" && claudeConfigDir != "" {
|
if runtimeConfig.Session != nil && runtimeConfig.Session.ConfigDirEnv != "" && claudeConfigDir != "" {
|
||||||
startupCmd = config.PrependEnv(startupCmd, map[string]string{runtimeConfig.Session.ConfigDirEnv: claudeConfigDir})
|
startupCmd = config.PrependEnv(startupCmd, map[string]string{runtimeConfig.Session.ConfigDirEnv: claudeConfigDir})
|
||||||
}
|
}
|
||||||
// Kill all processes in the pane before respawning to prevent orphan leaks
|
// Note: Don't call KillPaneProcesses here - this is a NEW session with just
|
||||||
// RespawnPane's -k flag only sends SIGHUP which Claude/Node may ignore
|
// a fresh shell. Killing it would destroy the pane before we can respawn.
|
||||||
if err := t.KillPaneProcesses(paneID); err != nil {
|
// KillPaneProcesses is only needed when restarting in an EXISTING session
|
||||||
// Non-fatal but log the warning
|
// where Claude/Node processes might be running and ignoring SIGHUP.
|
||||||
style.PrintWarning("could not kill pane processes: %v", err)
|
|
||||||
}
|
|
||||||
if err := t.RespawnPane(paneID, startupCmd); err != nil {
|
if err := t.RespawnPane(paneID, startupCmd); err != nil {
|
||||||
// If pane is stale (session exists but pane doesn't), recreate the session
|
|
||||||
if strings.Contains(err.Error(), "can't find pane") {
|
|
||||||
fmt.Printf("Stale session detected, recreating...\n")
|
|
||||||
_ = t.KillSession(sessionID)
|
|
||||||
return runCrewAt(cmd, args) // Retry with fresh session
|
|
||||||
}
|
|
||||||
return fmt.Errorf("starting runtime: %w", err)
|
return fmt.Errorf("starting runtime: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,8 +269,15 @@ func runCrewAt(cmd *cobra.Command, args []string) error {
|
|||||||
if err := t.RespawnPane(paneID, startupCmd); err != nil {
|
if err := t.RespawnPane(paneID, startupCmd); err != nil {
|
||||||
// If pane is stale (session exists but pane doesn't), recreate the session
|
// If pane is stale (session exists but pane doesn't), recreate the session
|
||||||
if strings.Contains(err.Error(), "can't find pane") {
|
if strings.Contains(err.Error(), "can't find pane") {
|
||||||
|
if crewAtRetried {
|
||||||
|
return fmt.Errorf("stale session persists after cleanup: %w", err)
|
||||||
|
}
|
||||||
fmt.Printf("Stale session detected, recreating...\n")
|
fmt.Printf("Stale session detected, recreating...\n")
|
||||||
_ = t.KillSession(sessionID)
|
if killErr := t.KillSession(sessionID); killErr != nil {
|
||||||
|
return fmt.Errorf("failed to kill stale session: %w", killErr)
|
||||||
|
}
|
||||||
|
crewAtRetried = true
|
||||||
|
defer func() { crewAtRetried = false }()
|
||||||
return runCrewAt(cmd, args) // Retry with fresh session
|
return runCrewAt(cmd, args) // Retry with fresh session
|
||||||
}
|
}
|
||||||
return fmt.Errorf("restarting runtime: %w", err)
|
return fmt.Errorf("restarting runtime: %w", err)
|
||||||
|
|||||||
Reference in New Issue
Block a user