From 474d5201823b99e1fefc60bd45759e58fe486534 Mon Sep 17 00:00:00 2001 From: Brian Clozel Date: Fri, 13 Feb 2026 18:33:47 +0100 Subject: [PATCH] Fix MultipartParser & PartGenerator memory leak Prior to this commit, the reactive `MultipartParser` and `PartGenerator` types were leaking memory at runtime in specific cases: * many HTTP clients must send multipart requests to be parsed and close the connection while uploading * the `PartGenerator` must be configured to write file parts to temporary files on disk * concurrency, upload speed must be important to trigger cases where the file system is not fast enough to consume incoming buffers The `MultipartParser` parses and emits `BodyToken` to its sink (here, the `PartGenerator`). By definition, Reactor's `FluxSink` when created with `Flux.create(FluxSink)` will use a "buffer" strategy and will queue emitted elements if they cannot be consumed. Here, the cancellation signal does dispose internal states in the `MultiPartParser` and `PartGenerator` but does not clear the internal queue in `FluxSink`. This commit ensures that an operation is registered to release buffers on the discard event. Fixes gh-36262 --- .../springframework/http/codec/multipart/PartGenerator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-web/src/main/java/org/springframework/http/codec/multipart/PartGenerator.java b/spring-web/src/main/java/org/springframework/http/codec/multipart/PartGenerator.java index f34a702d92c..8c741cbbf3e 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/multipart/PartGenerator.java +++ b/spring-web/src/main/java/org/springframework/http/codec/multipart/PartGenerator.java @@ -99,7 +99,8 @@ final class PartGenerator extends BaseSubscriber { sink.onCancel(generator); sink.onRequest(l -> generator.requestToken()); - tokens.subscribe(generator); + tokens.doOnDiscard(MultipartParser.BodyToken.class, bodyToken -> DataBufferUtils.release(bodyToken.buffer())) + .subscribe(generator); }); }