Repository navigation
fix(serve): exit explicitly after a graceful shutdown - #38
Merged
Merged
Conversation
On SIGTERM `dune serve` closed the listener, drained, printed "shutdown complete" and then simply returned, leaving the process alive for as long as the event loop had work. One ref'd plugin timer (plugin-admin's collab eviction setInterval, fixed in 3.1.3) was enough to keep it alive forever at 0% CPU with no listener: an "idle" dune process, which a second SIGTERM was needed to end. Roughly 45 of them had piled up on a developer machine. Exit explicitly once the drain is done, in both the single-site and multi-site paths. By then the listener is closed and in-flight requests are drained (or the drain deadline has passed); there is nothing left worth waiting for, and core should not depend on every plugin unref'ing its timers. The existing graceful-shutdown tests re-implement their helpers locally and never run the real command, which is how this went unnoticed. The new test runs the real `dune serve` as a subprocess with a plugin that holds a ref'd timer (so it does not depend on which plugin-admin version is installed), sends one SIGTERM, and requires a clean exit. Against the old code it is still alive 15 s later and fails; with the fix it passes in under a second. The multi-site path has the same change but no end-to-end test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 22, 2026
Merged
…e shutdown path Co-Authored-By: Claude Sonnet 5.5 <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.
Fixes #47
Problem
After SIGTERM,
dune servecloses the listener, drains, printsshutdown complete... and then just returns. The process stays alive for as long as the event loop has any work. One ref'd plugin timer is enough to keep it running forever at 0% CPU with no listener: an "idle" instance that a second SIGTERM is needed to end. About 45 of them had piled up on a developer machine.The trigger found there was
@dune/plugin-admin's collab evictionsetInterval(fixed separately in duneorg/plugin-admin#8), but core should not depend on every plugin unref'ing its timers.Fix
exitAfterShutdown()(Deno.exit(0)) once the drain is done, in both the single-site and multi-site paths. By then the listener is closed and in-flight requests are drained (or the drain deadline has passed); there is nothing left worth waiting for.Tests
The existing graceful-shutdown tests re-implement their helpers locally and never run the real command, which is how this went unnoticed.
tests/cli/serve_exit_after_shutdown_test.tsruns the realdune serveas a subprocess with a plugin that holds a ref'd timer (so it doesn't depend on which plugin-admin version is installed), sends one SIGTERM, and requires a clean exit (code 0,shutdown completeprinted). Against the old code the process is still alive 15 s later and the test fails; with the fix it passes in under a second.deno task checkclean;deno task test: 1877 passed, 0 faileddune serveagainst aconfig/sites.yamlfixture (checked to fail when the multi-siteexitAfterShutdown()call is removed).Context
Reproduced and root-caused before fixing: one SIGTERM leaves
servelistening on nothing and alive for 24 s+ (a second SIGTERM ends it);process.getActiveResourcesInfo()after shutdown showed exactly oneTimeout, and recording timer creators showed it came from plugin-admin 3.1.2'screateCollabManager.CHANGELOG entry is under the single
[Unreleased]section; no version bump (released together with the other pending changes).🤖 Generated with Claude Code