fix(net-tcp-server): prevent use-after-free crash in UvLoopHolder destructor#3919
Open
Ante042 wants to merge 1 commit into
Open
fix(net-tcp-server): prevent use-after-free crash in UvLoopHolder destructor#3919Ante042 wants to merge 1 commit into
Ante042 wants to merge 1 commit into
Conversation
…se-after-free in UvLoopHolder destructor
The destructor previously created a stack-allocated uv_async_t and called
uv_close() on it after m_thread.join(). By that point the loop thread had
already destroyed the loop (m_loop = {}), leaving the handle in a corrupt
state. libuv's uv_close then hit assert(0) in its type-switch because the
handle type was no longer valid.
The fix:
- Reuses the existing m_async member to wake the loop thread instead of
creating a temporary stack-allocated handle.
- Closes m_async from within the loop thread (where libuv requires it)
and runs the loop one final time to process the close callback before
the loop is destroyed.
- Removes the post-join uv_close call that operated on a dead loop.
Crash signature: "Assertion failed: 0 (../deps/uv/src/unix/core.c: uv_close: 234)"
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.
Summary
UvLoopHolder::~UvLoopHolder()can crash withAssertion failed: 0 (../deps/uv/src/unix/core.c: uv_close: 234)due to a race condition during shutdown.Root cause
The destructor creates a stack-allocated
uv_async_t, registers it with the loop, sends a signal, then callsm_thread.join(). The loop thread seesm_shouldExit == true, destroys the loop (m_loop = {}), and exits. Afterjoin()returns, the destructor callsuv_close()on the stack-allocated handle — but the loop is already destroyed and the handle's internal type field is corrupt. libuv'suv_closehits the default branch in its type-switch and asserts.Fix
m_asyncmember to wake the loop thread — no stack-allocated handle needed.m_asyncfrom within the loop thread (where libuv requires handle closure to happen) and run the loop one final time to process the close callback.uv_close()call that operated on a dead loop.Observed impact
This crash was observed on a production FXServer (Linux, 64-slot) running artifacts 27055 and 27722. The crash dump signature:
The bug exists in all current artifacts — the file has never been modified since creation.
Testing
The fix is a minimal, targeted change (9 lines added, 12 removed) to a single file. The async handle lifecycle now follows libuv's threading rules: handles are closed from the thread that owns the loop, before the loop is destroyed.