From 79f487013e7273da73828cb88485c49d8838a6f1 Mon Sep 17 00:00:00 2001 From: Norbert Date: Fri, 19 Jun 2026 10:35:15 +0200 Subject: [PATCH] Make Pipe serialization-completion flags volatile serializationComplete and rawSerializationComplete are written under synchronized(this) / no lock, but read in consume()/consumePostActions() while holding the ReentrantLock 'lock'. Because the fields are not volatile and the write and read paths use different monitors, the JMM provides no happens-before edge between them. On the content-altering out path (outputBuffer != null) the consumer can therefore observe a stale completion flag at the empty-buffer boundary and either complete the response early (truncation) or fail to suspend the encoder (short/spliced body), corrupting responses at ~8 KB multiples under load. The pure-relay path is unaffected because it gates on producerCompleted, which is published under the same 'lock'. Marking both flags volatile establishes happens-before for every read and write independent of which lock is held, closing the visibility gap with no change to locking behavior. See wso2/api-manager#5099 for the full analysis. --- .../main/java/org/apache/synapse/transport/passthru/Pipe.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/Pipe.java b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/Pipe.java index a13403bd16..d8d3804b59 100644 --- a/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/Pipe.java +++ b/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/passthru/Pipe.java @@ -96,9 +96,9 @@ public boolean isProducerCompleted() { private BaseConfiguration baseConfig; - private boolean serializationComplete = false; + private volatile boolean serializationComplete = false; - private boolean rawSerializationComplete = false; + private volatile boolean rawSerializationComplete = false; private boolean hasHttpProducer = true;