-
Notifications
You must be signed in to change notification settings - Fork 578
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open handles detected in Jest when using MockAgent #1614
Comments
Thanks for reporting and for the repro. I tracked this problem to a garbage collector issue. The following test always pass: import { MockAgent, request } from 'undici'
it('reproduces with globalDispatcher', async () => {
let mockAgent = new MockAgent()
let client = mockAgent.get('http://test.com')
client.intercept({ path: '/foo' }).reply(200, 'mockResponse')
const result = await request('http://test.com/foo', { dispatcher: mockAgent }).then((x) => x.body.text())
expect(result).toBe('mockResponse')
await mockAgent.close()
mockAgent = null
client = null
gc()
await new Promise((resolve) => setTimeout(resolve, 1000))
gc()
}) Having said this, we should be able to clean everything up when Lines 51 to 56 in 6a87bfb
|
I don't know if it's even possible to fix this, because by the time |
@mcollina since it's a test thing and we don't care about performance, can we add nextTick or other delay magic prior to resolving close promise? |
unfortunately a process.nextTick is not enough :(. |
@mcollina is it possible to somehow listen to the destroy event from that close? or there is nothing to subscribe to? |
Jest listen to the destroy hook, which relies on a C++ finalizer, which is triggered by the V8 garbage collector. I think our fix is to avoid making |
ran into the same issue with any sort of dispatcher or fetch during tests - essentially GC doesn't kick in, FinalizationRegistry isn't called and resources aren't cleaned up despite close() / destroy() on the dispatcher being called. Easy trick is to use --expose-gc + force gc manually, then resources are disposed of. Not sure what can be done to avoid this? May not be entirely related, but I think pino transport may have the same issue as it also depends on the FinalizationRegistry |
@AVVS I think #1614 (comment) would work. |
@mcollina I've tested no inheritance from AsyncResource + internal property to track it and either set it to null or manually emitDestroy(), but it didn't help much. Used |
Truly a rabbit hole on this one. one bit that was missing from the investigation is that code coverage generation was enabled, specifically, native v8 code generation. I turned off manual gc, disabled code coverage and lo and behold process would exit on it's own just fine. Next I've tried to use v8.takeCoverage() / v8.stopCoverage() and this seem to be working, fine, too. Potential workaround, just, in case someone stumbles upon this: v8.takeCoverage() // writes the report
v8.stopCoverage() // frees the resources & coincidentally references to whatever is holding the
// process opened (in my case TLSWraps) Call that after all of your tests have completed |
@AVVS not sure if it affects somehow your tests or not, but I've found this problem while trying to understand why I see hundreds of UNDICI_REQUEST resources in why-is-node-running report. |
Bug Description
When testing using MockAgent in Jest, open handles are detected.
Reproducible By
I have created a minimal reproduction repository here: undici-open-handles. The README will provide all the guidance you need to reproduce the issue.
Expected Behavior
Having made a request using the MockAgent, and closed the MockAgent, no handles should be left open.
Logs & Screenshots
If you run the reproduction repository, you'll have the full logs, but here is a sample:
Environment
Additional context
I attempted to investigate the implementation of MockAgent, and dig into the stack trace provided by Jest's
detectOpenHandles
. The issue seems to be to do with theAsyncResource
extended byRequestHandler
not getting cleaned up correctly. But I am not familiar with howAsyncResource
should be used and I can't immediately see what the issue is.The text was updated successfully, but these errors were encountered: