[
https://issues.apache.org/jira/browse/CXF-8926?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18087777#comment-18087777
]
Freeman Yue Fang commented on CXF-8926:
---------------------------------------
I am revisiting this issue and I can reproduce the MTOM attachment hang problem
with latest CXF versions. I will attach the MTOMAttachmentStallTest.java which
demonstrate this problem.
The root cause is when a CXF client sends a large MTOM attachment using
HttpClientHTTPConduit (Java 11+ HttpClient), the attachment bytes are written
through a PipedOutputStream → PipedInputStream pipe. The Java HttpClient reads
from the PipedInputStream on its own thread and pushes bytes to the TCP socket.
When the server accepts the TCP connection but never reads
1. The server's TCP receive buffer fills (~4 MB on macOS)
2. The client's TCP send buffer fills (~4 MB)
3. Java's HttpClient backs off — it stops consuming from the PipedInputStream
4. The 4 KB PipedInputStream buffer fills up
5. PipedOutputStream.write() calls PipedInputStream.receive(), which calls
awaitSpace() and blocks on Object.wait() — indefinitely
The receiveTimeout configured on HTTPClientPolicy is set as
HttpRequest.timeout() on the Java HttpClient, but that timeout only fires after
the response phase begins — it cannot reach back and unblock a
PipedOutputStream.write() that is already stuck in awaitSpace().
I'm working on a solution.
Freeman
> MTOM - Lock while processing attachment
> ---------------------------------------
>
> Key: CXF-8926
> URL: https://issues.apache.org/jira/browse/CXF-8926
> Project: CXF
> Issue Type: Bug
> Reporter: wilfried
> Assignee: Freeman Yue Fang
> Priority: Major
>
> I'm currently implementing a SOAP client to send document with CXF 4.0.1 (the
> application is quarkus based).
> My client is working fine when firewall is open between my machine and the
> target server, but in case firewall is closed (for QA environment for
> example), I was expecting to get a timeout, but it's not the case. The SOAP
> client stops its execution to the interceptor *AttachmentOutEndingInterceptor
> *and waits indefinitely.
> After profiling the application, I found out a lock as shown by the below
> thread dump:
> {code:java}
> "executor-thread-2" #296 daemon prio=5 os_prio=0 cpu=31.25ms elapsed=201.04s
> tid=0x0000019f9cd475d0 nid=0x5cf8 in Object.wait() [0x0000009645dfe000]
> java.lang.Thread.State: TIMED_WAITING (on object monitor)
> at java.lang.Object.wait([email protected]/Native Method)
> - waiting on <no object reference available>
> at
> java.io.PipedInputStream.awaitSpace([email protected]/PipedInputStream.java:273)
> at
> java.io.PipedInputStream.receive([email protected]/PipedInputStream.java:231)
> - locked <0x0000000613854b08> (a java.io.PipedInputStream)
> at
> java.io.PipedOutputStream.write([email protected]/PipedOutputStream.java:150)
> at
> org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:51)
> at
> org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:69)
> at
> org.apache.cxf.io.CacheAndWriteOutputStream.write(CacheAndWriteOutputStream.java:81)
> at jakarta.activation.DataHandler.writeTo(DataHandler.java:283)
> at
> org.apache.cxf.attachment.AttachmentSerializer.writeAttachments(AttachmentSerializer.java:318)
> at
> org.apache.cxf.interceptor.AttachmentOutInterceptor$AttachmentOutEndingInterceptor.handleMessage(AttachmentOutInterceptor.java:126)
> at
> org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:307)
> - locked <0x0000000613856e30> (a
> org.apache.cxf.phase.PhaseInterceptorChain)
> at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:528)
> at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:439)
> at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:354)
> at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:312)
> at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
> at
> org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:140)
> at jdk.proxy7.$Proxy235.addMessage(jdk.proxy7/Unknown Source)
> at
> lu.etat.ci.fwt.soap.SOAPTestController.callSaySomethingMtomSecuredCIDUT(SOAPTestController.java:138)
> at
> lu.etat.ci.fwt.soap.SOAPTestController$quarkusrestinvoker$callSaySomethingMtomSecuredCIDUT_1b14f2d5ed1a4d42c824e7582903a9f19063cae3.invoke(Unknown
> Source)
> at
> org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
> at
> io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
> at
> org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
> at
> io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
> at
> org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
> at
> org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1512)
> at
> org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
> at
> org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
> at
> io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
> at java.lang.Thread.run([email protected]/Thread.java:833)
> {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)