-
Notifications
You must be signed in to change notification settings - Fork 1.8k
fix(NODE-5588): recursive calls to next cause memory leak #3841
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import type { Document } from '../bson'; | ||
import { type Document, Long } from '../bson'; | ||
import { MongoInvalidArgumentError, MongoTailableCursorError } from '../error'; | ||
import type { ExplainVerbosityLike } from '../explain'; | ||
import type { MongoClient } from '../mongo_client'; | ||
|
@@ -101,7 +101,9 @@ export class FindCursor<TSchema = any> extends AbstractCursor<TSchema> { | |
limit && limit > 0 && numReturned + batchSize > limit ? limit - numReturned : batchSize; | ||
|
||
if (batchSize <= 0) { | ||
this.close().finally(() => callback()); | ||
this.close().finally(() => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this change just for consistency in return from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea, it is for result consistency, I may be able to revert it if I make sure the logic is nullish safe in next but the contract should have been either throw or result and when we make _getMore actually async that will be the case for the promise's resolution type. This code path also specifically claims it is for legacy servers which we don't support, I'm fairly certain this is only triggered by mock server tests. |
||
callback(undefined, { cursor: { id: Long.ZERO, nextBatch: [] } }) | ||
); | ||
return; | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes much more sense to me to be a property of the cursor itself instead of passing a cursor to a function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did we intentionally change the semantics of
isDead
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nevermind, I see that now in the description. But I'm still unsure why the logic was changed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to exit the loop and enter clean-up logic at the correct times. The prior logic didn't account for a cursor already being closed, or killed, so the loop would attempt a getMore on a killed cursor id. This same "exit" condition applies to all the places the cursorIsDead helper was being used.