fix(thread): detach pool worker threads — 8MB stack leaked per exited worker (true-async/server#93)#174
Merged
Merged
Conversation
…its 8MB stack (true-async/server#93) libuv_start_thread discards the uv_thread_t handle and nothing ever joins these threads, so each exited joinable worker kept its stack and TCB for the life of the process. One-shot for a normal pool teardown, but ThreadPool::reload() retires a full cohort per rotation: +16MB VmSize and ~60KB RSS per rotation, growing linearly (measured across a 539-rotation soak). uv_thread_detach right after create returns the stacks to the OS: VmSize is now flat across rotations and the residual RSS drift drops to the by-design channel-registry retention (~1.4KB/rotation, freed at thread shutdown). thread_pool/thread/fs_watcher suites 163/163.
…rue-async/server#93) uv_thread_detach landed in libuv 1.50.0, not 1.45 — the CI pins (1.45/1.48) predate it and the Linux matrix failed with an implicit declaration. Align everything with the release builds, which already run libuv 1.52.1: - config.m4: minimum bumped 1.45.0 -> 1.50.0 (error message names uv_thread_detach as the reason) - build-linux / coverage / build / debug-* workflows: source-built libuv pinned 1.52.1, cache keys updated - nightly-io-chaos: ubuntu-24.04 apt libuv (1.48) is no longer enough — build from source like the rest - libuv_reactor.c: plain uv_thread_detach, no platform ifdef
…1.52.1 (true-async/server#93)" This reverts commit 7f6ad78.
…ch needs libuv >= 1.50 (true-async/server#93)
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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.
libuv_start_threaddiscards theuv_thread_thandle and nothing ever joins these threads: every exited joinable worker kept its 8MB stack + TCB forever. Invisible to valgrind (not a malloc), one-shot for normal pool teardown — butThreadPool::reload()retires a whole cohort per rotation, so a hot-reload soak grew +16MB VmSize / ~60KB RSS per rotation, linearly (measured over 539 rotations while stress-testingHttpServer::reload()).Fix:
uv_thread_detachright after a successful create (same pattern as the process-watcher threads in this file). Nothing can join these threads anyway — the handle was never stored.After: VmSize flat across rotations; residual RSS drift is the by-design channel-registry retention (~1.4KB/rotation, freed at thread shutdown).
Suites: thread_pool + thread + fs_watcher 163/163 green.