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
Leaked ClientHttp2Stream when canceling duplex streams #2184
Comments
@murgatroid99 I can't see how #2187 would cause the listener to not be holding a reference, what am I missing? I understand it's worthwhile to be consistent with the other listeners, but wouldn't it be better to replace If we look at the Ultimately the session is not closed for some reason. I could not correlate the session with an open session on the server side but this is because I have no way of identifying which session belongs to which |
I made that change based on the information provided. You showed a screenshot with a single retainer, so I took action regarding that single retainer. Does your heapdump still show however many leaked Changing grpc-js calls |
Which makes sense I guess, but I don't understand why data is not being read. The stream is in flowing mode so it should be emitting data events until the stream is drained, no? |
It's possible that the session needs more tracking, this issue is interesting: nodejs/node#42710 |
The stream flow is connected to the stream returned by the gRPC API. If you have that stream in flowing mode and you are still experiencing this leak, then there may be a disconnect somewhere internally. It is unlikely that that linked Node issue is related. That one is about sessions leaking on the server, while this is about streams leaking on the client. |
I think I see the issue. Normally the API-level stream flow is connected to the http2 stream by a cycle of the API-level stream requesting a message, and the http2 stream outputting a message, triggering the API-level stream to request another message. That cycle is broken when the code processing the http2 stream's output stops outputting messages after the call ends, leaving the stream in a paused state forever. |
Do you think #1652 is related to this leak, or is it just another problem you are having? |
I suspect that the double free is triggered by cancel and that the fix put in place triggers it more frequently. This is still a bug with node though, but my feeling is that grpc-js is not production ready unless node http2 is also production ready and becuase grpc-js doesn't need to rely on node's http2 implementation, it should still be an open related issue that people who are looking to us this library should be aware of. |
First, I have released #2193 in grpc-js version 1.6.10.
I can see now how these would be connected. Fixing a memory leak inherently causes resources to be freed more consistently, which would make it more likely for a double free bug to be triggered.
grpc-js absolutely does need to rely on Node's http2 implementation. That is one of the main reasons the library exists at all. |
I am upgrading a codebase from native grpc to grpc-js. When using grpc-js I see a memory leak affecting duplex streams which is caused by unclosed
ClientHttp2Stream
instances on the caller side of duplex streams. My best guess at the cause of the problem is that the client cancels the request and the underlyingClientHttp2Stream
waits indefinitely (or until the socket is closed) for trailers that never arrive. So while the the leak appears on the client side, it's possibly caused by buggy server side behavior.I don't have a deterministic reproduction, some fraction of calls leak when cancelling them, so I don't know what state the connection needs to be in to cause it to leak.
Environment
Additional context
Related to #1339
Heapdump shows leaked
Http2CallStreams
(shown with distance -)Http2CallStream
instances are leaked through the boundthis
on the theClientHttp2Stream
trailers event listenerWe can see that the calls were cancelled on the client side looking at the
finalStatus
The text was updated successfully, but these errors were encountered: