Repository navigation
Fix crash in the GC roots server on fd reuse - #672
Conversation
The GC roots server started a thread per client connection and only afterwards inserted it into the `connections` map keyed by the client fd. The client thread's cleanup handler erases its own entry from that map, so if a client disconnected immediately, the cleanup could run before the insert. The cleanup then found nothing to erase, the fd was closed, and the server inserted a finished-but-joinable thread under a now-closed fd number. When a later client got the same fd number from accept(), the server tried to insert under an existing key. std::map::insert doesn't overwrite, so the temporary pair holding the new (joinable) std::thread was destroyed, which calls std::terminate(). This showed up in Sentry as a SIGABRT in nix-daemon with no exception in flight, and another thread blocked on the `connections` lock in its cleanup handler. Fix this by holding the `connections` lock while starting the client thread and inserting it. The cleanup handler can't run until the entry exists, and the fd is only closed after the cleanup, so fd numbers can no longer collide. Also assert that the insert didn't hit an existing key. Assisted-by: Claude Fable 5.1 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (1)
Included review availability: This review used your included allowance. 4 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour. 📝 WalkthroughWalkthroughThe GC socket server now holds the ChangesGC Connection Registration
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~8 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to The change synchronizes client registration with cleanup, preventing the stale-entry race behind the reported crash. No unresolved merge risk remains. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
Motivation
Fixes a
std::terminate()crash (SIGABRT) innix-daemonduring garbage collection, seen in Sentry (issue 7679852086, 3.23.0).Context
The GC roots server spawned a thread per client and only afterwards inserted it into the
connectionsmap keyed by fd. If a client disconnected immediately, the thread's cleanup handler ran before the insert, leaving a stale entry for a closed fd. When a later client reused that fd number, the duplicate-key insert destroyed a joinablestd::thread, which callsstd::terminate().The fix holds the
connectionslock while starting and registering the thread, so the cleanup handler can't run before the entry exists. See the commit message for details.🤖 Generated with Claude Code
Summary by CodeRabbit