Repository navigation
fix(collab): unref the session-eviction interval so it can't keep the process alive - #8
Merged
Merged
Conversation
… process alive createCollabManager() started a ref'd 5-minute setInterval for session eviction and never cleared or unref'd it (the leading underscore on the variable was the tell). After `dune serve` received SIGTERM, closed its listener and printed "shutdown complete", that one timer kept the process alive forever at 0% CPU: an idle dune process with no listener. A second SIGTERM ended it. Found by recording who created each live timer after shutdown: this interval, created in mount() via createCollabManager, was the only one. Deno.unrefTimer() it: housekeeping must never decide process lifetime. There is no shutdown hook to clear it from (the manager has no dispose and core has no plugin-shutdown hook), and once unref'd there is nothing left to clear. The regression test runs in a subprocess because "does the process exit on its own?" is the property: it creates a collab manager and does nothing else, and must exit. Against the old code it hangs until the test's kill timeout; with the fix it exits in well under a second. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 22, 2026
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
After
dune servereceives SIGTERM it closes the listener and printsshutdown complete, but the process never exits: it sits at 0% CPU forever with no port. That is where a lot of "idle dune processes" come from. A second SIGTERM ends it.Cause
createCollabManager()starts a 5-minutesetIntervalfor session eviction (src/collab/manager.ts) that is never cleared or unref'd (the variable was even named_evictionTimer). I found it by recording the creator of every live timer after shutdown in a scratch copy of core'sserve.ts: this interval, created viamount()→createCollabManager, was the only live timer, andprocess.getActiveResourcesInfo()showed exactly oneTimeout.plugin-inline-edit's equivalent GC timer already calls.unref().Fix
Deno.unrefTimer(evictionTimer). Housekeeping should never decide process lifetime. There is no shutdown hook to clear it from (the manager has no dispose, core has no plugin-shutdown hook), and once unref'd there is nothing left to clear. It still fires normally while the process is alive.Tests
tests/collab/eviction_timer_test.tsruns in a subprocess, because "does the process exit on its own?" is the property under test; an in-process check cannot see a ref'd timer. It creates a collab manager and does nothing else, and must exit. Against the old code it hangs until the test's 60 s kill timeout and fails; with the fix it passes in ~75 ms.deno task checkclean;deno task test: 239 passed, 0 failed@dune/coresoservealso exits explicitly after shutdown, so no plugin timer can hold the process (separate PR).Not verified
plugin-inline-edithas several timers; its GC interval is unref'd, but an active editing session's awareness intervals could in principle linger. I haven't tested that; the coreDeno.exitchange covers it regardless.Bumps to 3.1.3 with a CHANGELOG entry.
🤖 Generated with Claude Code