fix(ClientRequest): remove passthrough socket listeners on close#755
fix(ClientRequest): remove passthrough socket listeners on close#755kettanaito merged 5 commits intomswjs:mainfrom
Conversation
When passthrough mode is used, the MockHttpSocket attaches event listeners to the original socket but never removes them when the socket closes. This causes memory leaks, especially noticeable in long-running processes with Node.js 20+. This fix calls socket.removeAllListeners() in the close event handler to properly clean up all listeners attached to the original socket. Fixes mswjs/msw#2537
|
Thanks for working on this, @Stanzilla. This looks great. One issue here is that the test you've added passes even if your fix is reverted. I'm trying to add a direct test on the socket listeners instead, but that proves problematic since request's |
DiscoveryAfter some digging, I discovered that we were incorrectly handling closure forwarding between the mock and the passthrough sockets. We always forward passthrough closures as client-facing closures (in the We also had a bug where we were listening to the I've fixed that, removed your test, added a new test that asserts directly on the passthrough socket, and things seems to pass now. |
|
Now, the only thing left to do is to get rid of Update: Turned out, we already had |
|
Awesome, thank you for getting it over the finish line! |
|
Sadly, the release is currently blocked by #759. I will get to it at the beginning of the year. |
Released: v0.41.0 🎉This has been released in v0.41.0. Get these changes by running the following command: Predictable release automation by Release. |
Summary
This PR fixes a memory leak that occurs when using passthrough mode in Node.js 20+.
The Problem
When
MockHttpSocket.passthrough()is called, event listeners are attached to the original socket (lookup, connect, secureConnect, secure, session, ready, drain, data, error, resume, timeout, prefinish, finish, close, end) but they are never removed when the socket closes.This causes memory leaks in long-running processes, as reported in mswjs/msw#2537.
The Fix
Call
socket.removeAllListeners()in the close event handler before emitting the close event to the MockHttpSocket. This ensures all listeners attached to the original socket are properly cleaned up.Test
Added a regression test that makes many passthrough requests and verifies no
MaxListenersExceededWarningis emitted.Fixes mswjs/msw#2537