-
-
Notifications
You must be signed in to change notification settings - Fork 988
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
Avoid possible memory leak in compress middleware #919
Conversation
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.
LGTM
Thanks for the detailed report and additional test cases. Really nice work!
@VojtechVitek @pkieltyka Thanks for the review and merging the PR 🙏 Do we have a rough estimation of when the new release containing these changes will be created? We would love to pull the fix as soon as possible. Thinking now if we should point to the commit hash from the |
@Neurostep can you |
@VojtechVitek That makes sense 👍 We will check changes from the |
@VojtechVitek Just following up here. We have deployed the Thanks again for the reviews and quick turnaround 🙏 |
Hi @Neurostep, this is great! Thanks you for reporting back! I'll release v5.0.13 shortly. 🎉 |
I think something might be wrong with f10dc4a Using the compression middleware, i get 'extra bytes' at the end of the document:
This does not happen if i rebuild the binary with 5.0.12 (or drop the compression middleware)
|
Description
In one of the HTTP services I am working on, we use the
compress
middleware provided bychi
. We use standardgzip, deflate
compression alongside withbrotli
compression.The important aspect of the HTTP endpoint that uses the
compression
middleware is that the content may or may not be of a compressible type, servingjson
andHTML
alongsidepng
andjpg
.For the
brotli
compression we use the official CGO wrapper. The following code snippet is used to set the encoder:After enabling the
brotli
compression in the production environment, we noticed a memory leak in the service although there was no any issues withgzip
compression.After the investigation, we noticed no memory leak indicated by the Go runtime profiles. After this we started looking into the
brotli
library implementation.Instrumented with the bcc tools (BPF Compiler Collection) we were able to find the leak:
It is clear from the report we are leaking the memory instantiated by the brotli writer. Looking at the source code of the compress middleware, we should call the underlying Close of the CGO writer which in turn should free up the C-allocated memory. We checked if the BrotliEncoderDestroyInstance is being called using the
funccount-bpfcc
:Turned out, the
BrotliEncoderDestroyInstance
function is not being called at the same rate asBrotliEncoderCreateInstance
which explains the leak.After carefully looking into the go-chi middleware I realized we are calling the Close function returned by the writer() function, and writer() function returns instantiated writer only if the content is compressible.
In this PR we are trying to close the underlying
Writer
if it satisfies theWriteCloser
interface, no matter if the content being served is compressible or not.Related links