Romain Manni-Bucau created CXF-7037:
---------------------------------------
Summary: @Suspended can be broken on tomcat
Key: CXF-7037
URL: https://issues.apache.org/jira/browse/CXF-7037
Project: CXF
Issue Type: Bug
Affects Versions: 3.1.7
Reporter: Romain Manni-Bucau
For AsyncContext usages, tomcat ensures the non container threads wait for the
container thread to exit the execution (the one starting the async context) to
avoid concurrency issue.
For cxf it means you can resume() in a user thread on an AsyncResponse while
you execute AsyncResponseImpl.suspendContinuationIfNeeded().
This can lead to a lock preventing the request to complete.
Here is a sample thread:
{code}
"managed-thread-3@7750" daemon prio=5 tid=0x48 nid=NA waiting
java.lang.Thread.State: WAITING
blocks http-nio-24622-exec-3@7702
at java.lang.Object.wait(Object.java:-1)
at java.lang.Object.wait(Object.java:502)
at
org.apache.coyote.AsyncStateMachine.pauseNonContainerThread(AsyncStateMachine.java:452)
at
org.apache.coyote.AsyncStateMachine.asyncDispatch(AsyncStateMachine.java:315)
at
org.apache.coyote.http11.Http11Processor.action(Http11Processor.java:858)
at org.apache.coyote.Request.action(Request.java:390)
at
org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:203)
- locked <0x21ed> (a java.lang.Object)
at
org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:171)
at
org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:165)
at
org.apache.openejb.server.httpd.EEFilter$AsynContextWrapper.dispatch(EEFilter.java:171)
at
org.apache.cxf.transport.http.Servlet3ContinuationProvider$Servlet3Continuation.redispatch(Servlet3ContinuationProvider.java:125)
at
org.apache.cxf.transport.http.Servlet3ContinuationProvider$Servlet3Continuation.resume(Servlet3ContinuationProvider.java:131)
at
org.apache.cxf.jaxrs.impl.AsyncResponseImpl.doResumeFinal(AsyncResponseImpl.java:96)
- locked <0x2196> (a org.apache.cxf.jaxrs.impl.AsyncResponseImpl)
at
org.apache.cxf.jaxrs.impl.AsyncResponseImpl.doResume(AsyncResponseImpl.java:89)
at
org.apache.cxf.jaxrs.impl.AsyncResponseImpl.resume(AsyncResponseImpl.java:73)
at
com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor.lambda$async$0(AsyncInterceptor.java:63)
at
com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$$Lambda$55.375198754.run(Unknown
Source:-1)
at
com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$TransactionProvider.run(AsyncInterceptor.java:148)
at sun.reflect.GeneratedMethodAccessor95.invoke(Unknown Source:-1)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at
org.apache.webbeans.intercept.AbstractInvocationContext.directProceed(AbstractInvocationContext.java:113)
at
org.apache.webbeans.intercept.AbstractInvocationContext.proceed(AbstractInvocationContext.java:106)
at
org.apache.webbeans.intercept.InterceptorInvocationContext.proceed(InterceptorInvocationContext.java:67)
at
org.apache.openejb.cdi.transactional.InterceptorBase.intercept(InterceptorBase.java:66)
at
org.apache.openejb.cdi.transactional.RequiredInterceptor.intercept(RequiredInterceptor.java:35)
at sun.reflect.GeneratedMethodAccessor85.invoke(Unknown Source:-1)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at
org.apache.webbeans.component.InterceptorBean.intercept(InterceptorBean.java:136)
at
org.apache.webbeans.intercept.InterceptorInvocationContext.proceed(InterceptorInvocationContext.java:63)
at
org.apache.webbeans.intercept.DefaultInterceptorHandler.invoke(DefaultInterceptorHandler.java:139)
at
com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$TransactionProvider$$OwbInterceptProxy0.run(com/github/rmannibucau/rblog/jaxrs/async/AsyncInterceptor$TransactionProvider.java:-1)
at
com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$TransactionProvider$$OwbNormalScopeProxy0.run(com/github/rmannibucau/rblog/jaxrs/async/AsyncInterceptor$TransactionProvider.java:-1)
at
com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$Metas.lambda$runInTransaction$6(AsyncInterceptor.java:130)
at
com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$Metas$$Lambda$56.1727885795.run(Unknown
Source:-1)
at
com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$Metas.lambda$toJaxRs$7(AsyncInterceptor.java:136)
at
com.github.rmannibucau.rblog.jaxrs.async.AsyncInterceptor$Metas$$Lambda$57.1956863343.run(Unknown
Source:-1)
at org.apache.openejb.threads.task.CURunnable$1.call(CURunnable.java:35)
at org.apache.openejb.threads.task.CURunnable$1.call(CURunnable.java:32)
at org.apache.openejb.threads.task.CUTask.invoke(CUTask.java:89)
at org.apache.openejb.threads.task.CURunnable.run(CURunnable.java:32)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
"http-nio-24622-exec-3@7702" daemon prio=5 tid=0x41 nid=NA waiting for monitor
entry
java.lang.Thread.State: BLOCKED
waiting for managed-thread-3@7750 to release lock on <0x2196> (a
org.apache.cxf.jaxrs.impl.AsyncResponseImpl)
at
org.apache.cxf.jaxrs.impl.AsyncResponseImpl.suspendContinuationIfNeeded(AsyncResponseImpl.java:263)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:191)
{code}
Solution would be to not synchronize both method and probably move to a
volatile state
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)