Skip to content

fix: wrap StopAll plugin Stop calls in panic recovery (PILOT-247)#5

Merged
TeoSlayer merged 2 commits into
mainfrom
openclaw/pilot-247-20260529-202711
May 29, 2026
Merged

fix: wrap StopAll plugin Stop calls in panic recovery (PILOT-247)#5
TeoSlayer merged 2 commits into
mainfrom
openclaw/pilot-247-20260529-202711

Conversation

@matthew-pilot
Copy link
Copy Markdown
Collaborator

What failed

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 up through StopAll, crashing the daemon mid-teardown.

Why this fix

Add stopWithPanicRecovery mirroring the existing startWithPanicRecovery pattern: a 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.

Verification

go build ./...   # clean
go vet ./...     # clean
go test ./...    # all pass (13/13 packages)

git diff --stat

coreapi/lifecycle.go              | 32 +++++++++++++--
coreapi/zz_panic_recovery_test.go | 82 ++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+), 4 deletions(-)

Closes PILOT-247

…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
@matthew-pilot matthew-pilot added the matthew-fix-larger Medium-scope fix (≤10 files, ≤200 LoC) — operator review with diff stat label May 29, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@matthew-pilot
Copy link
Copy Markdown
Collaborator Author

🦞 Matthew PR Check — #5 PILOT-247

Status

  • State: OPEN · MERGEABLE
  • CI: 2/2 green (test ✅, codecov/patch ✅)
  • Canary: not yet triggered
  • Jira: PILOT-247

Scope

  • matthew-fix-larger — 2 files (+110, −4)
  • Files: coreapi/lifecycle.go (+28/−4), coreapi/zz_panic_recovery_test.go (+82/0)

Reviews

  • None yet — awaiting operator

🕐 2026-05-29 20:31 UTC · Matthew PR Worker

@matthew-pilot
Copy link
Copy Markdown
Collaborator Author

🦞 Matthew Explain — #5 PILOT-247

What

StopAll iterates started plugins in reverse and calls queue[i].Stop(ctx) directly — unlike StartAll, which wraps each Start in startWithPanicRecovery. This means a plugin that panics during shutdown (nil dereference, send-on-closed-channel, etc.) propagates the panic through StopAll, crashing the daemon mid-teardown.

Fix

Adds stopWithPanicRecovery mirroring the existing startWithPanicRecovery pattern. A defer recover() converts Stop panics to fmt.Errorf, collected alongside normal Stop errors. Every service still gets its Stop call invoked even when an earlier service panics.

Verification

go build ./...   → clean
go vet ./...     → clean
go test ./...    → all pass (13/13 packages)
  • New dedicated test: coreapi/zz_panic_recovery_test.go (+82 lines) covers panic-in-Stop for both single and multi-plugin scenarios.

Diff stat

File +
coreapi/lifecycle.go 28 4
coreapi/zz_panic_recovery_test.go 82 0
Total 110 4

🕐 2026-05-29 20:31 UTC · Matthew PR Worker

@TeoSlayer TeoSlayer merged commit 42893fa into main May 29, 2026
1 check passed
@TeoSlayer TeoSlayer deleted the openclaw/pilot-247-20260529-202711 branch May 29, 2026 21:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

matthew-fix-larger Medium-scope fix (≤10 files, ≤200 LoC) — operator review with diff stat

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants