Skip to content

Release retained response buffers on discard in NettyWriteResponseFilter - #4349

Open
siddiqueirshad wants to merge 1 commit into
spring-cloud:mainfrom
siddiqueirshad:fix/netty-write-response-filter-discard-leak
Open

siddiqueirshad wants to merge 1 commit into
spring-cloud:mainfrom
siddiqueirshad:fix/netty-write-response-filter-discard-leak

Conversation

@siddiqueirshad

Copy link
Copy Markdown

Fixes #4332

Problem Description

In NettyWriteResponseFilter, the response body stream is created with:

final Flux<DataBuffer> body = connection
        .inbound()
        .receive()
        .retain()
        .map(byteBuf -> wrap(byteBuf, response));
return response.writeWith(body);

receive().retain() increments the reference count of inbound Netty ByteBuf slices. When a client cancels or disconnects mid-response (e.g. mobile/browser connection drop), cleanup() only disposes the connection. Elements in flight between retain() and the outbound response write—including buffers buffered or queued in Reactor operators—are not released, leading to direct memory leak (LEAK: ByteBuf.release() was not called before it's garbage-collected) and pinning PoolChunks.

Solution

Add doOnDiscard handlers to ensure discarded buffers are released upon cancellation or error:

  1. doOnDiscard(ByteBuf.class, ReferenceCountUtil::safeRelease) immediately following retain() to handle discarded raw ByteBuf instances.
  2. doOnDiscard(DataBuffer.class, ...) following map(...) to safely release discarded wrapped DataBuffer instances (catching Throwable to safely tolerate potential concurrent release with FluxReceive.cleanQueue).

@spencergibb spencergibb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a test if possible

@siddiqueirshad

Copy link
Copy Markdown
Author

Hi @spencergibb, added unit test
etainedBuffersAreReleasedOnDiscard\ in \NettyWriteResponseFilterTests\ verifying that retained ByteBuf and DataBuffer instances are safely released when downstream cancels or discards in-flight buffers, and signed off the commit.

…eResponseFilter

Signed-off-by: siddiqui irshad <mohdirshad1306@gmail.com>
@siddiqueirshad
siddiqueirshad force-pushed the fix/netty-write-response-filter-discard-leak branch from 312cac5 to 6eda0ec Compare October 29, 2026 17:37

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NettyWriteResponseFilter leaks retained response buffers when the client cancels mid-response

3 participants