fix: wrap StopAll plugin Stop calls in panic recovery (PILOT-247)#5
Conversation
…247) StopAll iterates started plugins in reverse and calls queue[i].Stop(ctx) directly, while StartAll wraps each Start in startWithPanicRecovery. A plugin panicking during shutdown (nil dereference, channel-send on closed channel, etc.) propagates the panic through StopAll, crashing the daemon mid-teardown — previously-stopped plugins are gone, not-yet-stopped plugins keep running orphaned, and on-disk state may be half-written. Add stopWithPanicRecovery mirroring the existing startWithPanicRecovery pattern: defer recover() converts a Stop panic to a fmt.Errorf, collected alongside normal Stop errors. Every service still gets its Stop call invoked even when an earlier service panics. Closes PILOT-247
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
🦞 Matthew PR Check — #5 PILOT-247Status
Scope
Reviews
🕐 2026-05-29 20:31 UTC · Matthew PR Worker |
🦞 Matthew Explain — #5 PILOT-247What
FixAdds Verification
Diff stat
🕐 2026-05-29 20:31 UTC · Matthew PR Worker |
What failed
StopAlliterates started plugins in reverse and callsqueue[i].Stop(ctx)directly, whileStartAllwraps eachStartinstartWithPanicRecovery. A plugin panicking during shutdown (nil dereference, channel-send on closed channel, etc.) propagates the panic up throughStopAll, crashing the daemon mid-teardown.Why this fix
Add
stopWithPanicRecoverymirroring the existingstartWithPanicRecoverypattern: adefer recover()converts aStoppanic to afmt.Errorf, collected alongside normalStoperrors. Every service still gets itsStopcall invoked even when an earlier service panics.Verification
git diff --stat
Closes PILOT-247