fix(shutdown): kill entire process tree to prevent orphaned Claude processes
The previous implementation used `pkill -P pid` which only kills direct children. When Claude spawns subprocesses (like node workers), those grandchild processes would become orphaned (PPID=1) when their parent was killed, causing them to survive `gt shutdown -fa`. The fix recursively finds all descendant processes and kills them in deepest-first order, ensuring no process becomes orphaned during shutdown. Fixes: gt-wd3ce Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
committed by
beads/crew/emma
parent
4ee1a4472d
commit
1043f00d06
@@ -527,3 +527,28 @@ func TestHasClaudeChild(t *testing.T) {
|
||||
t.Error("hasClaudeChild should return false for nonexistent PID")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllDescendants(t *testing.T) {
|
||||
// Test the getAllDescendants helper function
|
||||
|
||||
// Test with nonexistent PID - should return empty slice
|
||||
got := getAllDescendants("999999999")
|
||||
if len(got) != 0 {
|
||||
t.Errorf("getAllDescendants(nonexistent) = %v, want empty slice", got)
|
||||
}
|
||||
|
||||
// Test with PID 1 (init/launchd) - should find some descendants
|
||||
// Note: We can't test exact PIDs, just that the function doesn't panic
|
||||
// and returns reasonable results
|
||||
descendants := getAllDescendants("1")
|
||||
t.Logf("getAllDescendants(\"1\") found %d descendants", len(descendants))
|
||||
|
||||
// Verify returned PIDs are all numeric strings
|
||||
for _, pid := range descendants {
|
||||
for _, c := range pid {
|
||||
if c < '0' || c > '9' {
|
||||
t.Errorf("getAllDescendants returned non-numeric PID: %q", pid)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user