fs: fix close listener leak in FileHandle streams - #64227
Conversation
b433fb3 to
c4a165a
Compare
Fixes: nodejs#64214 Signed-off-by: y1d7ng <y1d7ng@yeah.net>
Fixes: nodejs#64214 Signed-off-by: y1d7ng <y1d7ng@yeah.net>
| function cleanup() { | ||
| options.fd.removeListener('close', onclose); | ||
| options.fd[kUnref](); | ||
| } | ||
| stream.once('end', cleanup); | ||
| stream.once('finish', cleanup); | ||
| stream.once('error', cleanup); |
There was a problem hiding this comment.
@Y1D7NG should we removeListener for all 3 in cleanup, so we don't leave these hanging as well?
| function cleanup() { | |
| options.fd.removeListener('close', onclose); | |
| options.fd[kUnref](); | |
| } | |
| stream.once('end', cleanup); | |
| stream.once('finish', cleanup); | |
| stream.once('error', cleanup); | |
| function cleanup() { | |
| options.fd.removeListener('close', onclose); | |
| stream.removeListener('end', cleanup); | |
| stream.removeListener('finish', cleanup); | |
| stream.removeListener('error', cleanup); | |
| options.fd[kUnref](); | |
| } | |
| stream.once('end', cleanup); | |
| stream.once('finish', cleanup); | |
| stream.once('error', cleanup); |
There was a problem hiding this comment.
From what I'm aware of for similar functions, it's common practice to (intentionally) leave these listeners dangling on the stream and rely on normal garbage collection to tidy it all up in the end.
There was some discussion on this stuff in #35452. In this case, the duplex stuff doesn't apply so I'd personally say it doesn't need the special handling that was eventually added there.
There was a problem hiding this comment.
Thanks for bringing that, that's interesting. Unsure how to proceed then. @nodejs/streams is the current behavior as expected?
There was a problem hiding this comment.
to be clear: in my comment I'm only talking about the events on the stream (end/finish/error) - removing the close listener from the file descriptor (i.e. the purpose of this PR) is definitely necessary.
There was a problem hiding this comment.
There are 2 approvals and a green CI.
Could this PR be landed, or does it need clarification of the above comments first?
There was a problem hiding this comment.
My comments are non-blocking, although I don't see it hurting waiting extra time to get insights from the right team tho.
There was a problem hiding this comment.
I think the listeners can be left to normal garbage collection
fix: #64214
When autoClose is false, FileHandle.createReadStream registers a close listener on the handle. That listener is not removed after the stream finishes normally, so creating streams repeatedly on the same handle accumulates listeners.
In importFd, when autoClose is false, remove that listener and perform the corresponding unref cleanup when the stream ends (on end for read streams, on finish for write streams) or on error.