feat: self-shutdown when the host process exits#1
Merged
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughThe change adds parent-process monitoring to ChangesParent watchdog lifecycle
Package release metadata
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/server.cpp`:
- Around line 178-186: Update PluginServer::Shutdown() to call
StopParentWatchdog() for external callers after signaling the watchdog, ensuring
the watchdog is stopped and joined before shutdown returns. Preserve the
self-call protection in StopParentWatchdog() so the watchdog thread never
attempts to join itself.
- Around line 165-168: Update the server startup flow in Start() to capture
getppid() before any startup or handshake work can reparent the process, then
retain that value for host monitoring. Move the StartParentWatchdog() call to
execute only after startup succeeds, rather than relying on the later host_pid_
assignment.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d4857338-3290-411a-a1c3-755a097d722f
📒 Files selected for processing (3)
include/go_plugin/server.hppsrc/server.cppvcpkg.json
devgianlu
force-pushed
the
feat/parent-death-watchdog
branch
from
July 21, 2026 13:32
b535687 to
0ee54ae
Compare
Add a parent-death watchdog to PluginServer: when the go-plugin host dies without killing the plugin (e.g. the host is SIGKILLed), nothing signals the plugin and Wait() would block forever, orphaning the process. Detect reparenting (getppid changes) and drive Shutdown(), mirroring the Go go-plugin server's built-in orphan protection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
devgianlu
force-pushed
the
feat/parent-death-watchdog
branch
from
July 21, 2026 13:35
0ee54ae to
3639c2a
Compare
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.
Problem
When a go-plugin host dies without killing its plugins — e.g.
volumio5-coreis SIGKILLed — nothing signals the C++ plugin.grpc::Server::Wait()only returns onShutdown(), so the plugin blocks forever and orphans itself; the next host start then spawns a second copy.Go plugins don't have this problem: the hashicorp/go-plugin Go server has built-in orphan protection. The C++ SDK had none — observed on-device with airplay2/qobuz/tidal (all C++) surviving a core SIGKILL while the Go plugins exited cleanly.
Fix
Add a parent-death watchdog to
PluginServer, matching the Go server's built-in behaviour:Start()records the host pid and spawns a watchdog thread.getppid(); on reparenting (host gone) it callsShutdown(), unblockingWait().Shutdown()/ the destructor stop and join the watchdog (condition-variable–woken, so no added shutdown latency).Because this simply unblocks
Wait(), each plugin's existing post-Wait()teardown runs unchanged — no per-plugin code required.Why
getppid()pollingPR_SET_PDEATHSIGraces with the Go host's fork thread (spurious early trigger)./dev/nullwhen backgrounded bystart-stop-daemon, so it would false-trigger immediately.Validation
grpc isn't available on the dev host and plugin builds run inside the SDK container, so the watchdog logic was compile+run-checked standalone against a stub
grpc::Server: clean build, both paths correct (stable parent idles then joins promptly; host-gone triggers immediate self-shutdown), and the double-Shutdown()is safe.Consumers (volumio5-plugin-airplay2/qobuzconnect/tidalconnect) will pick this up via an overlay-port
REFbump after merge.🤖 Generated with Claude Code
Summary by CodeRabbit
Wait()from blocking indefinitely after unexpected host termination.