feat: add graceful shutdown via SIGTERM/SIGINT#67
Draft
toddr-bot wants to merge 1 commit into
Draft
Conversation
Bind() now installs SIGTERM and SIGINT handlers that set the Done flag, allowing the accept loop to exit cleanly. Previously, these signals killed the daemon immediately — the "Server terminating" log message never fired and sockets were not properly closed. Also fixes the preforking parent to use $exit flag instead of die in signal handlers, which is cleaner and actually uses the $exit variable as originally designed. Adds t/signal.t with pipe-synchronized fork tests verifying both SIGTERM and SIGINT trigger graceful shutdown. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
What
Bind() now handles SIGTERM and SIGINT gracefully instead of dying immediately.
Why
Previously, sending SIGTERM to a Net::Daemon process killed it without cleanup — the "Server terminating" log never fired, sockets weren't closed, and the process gave no indication of an orderly shutdown. This is the expected behavior for any production daemon.
Also, the
$Net::Daemon::exitvariable was declared but never actually used — the preforking parent's signal handlers useddieinstead. This wires up the original design.How
$SIG{TERM}and$SIG{INT}handlers in Bind() that call$self->Done(1), breaking the accept loop naturally via the existingwhile (!$self->Done())condition.$exit = 1instead ofdie— cleaner and consistent with the variable's intended purpose.Testing
t/signal.twith 6 tests: fork-based tests for both SIGTERM and SIGINT graceful shutdown (pipe-synchronized), plus direct Done() flag verification.🤖 Generated with Claude Code
Quality Report
Changes: 2 files changed, 172 insertions(+), 2 deletions(-)
Code scan: clean
Tests: passed (OK)
Branch hygiene: clean
Generated by Kōan post-mission quality pipeline