https://bz.apache.org/bugzilla/show_bug.cgi?id=59125
Bug ID: 59125 Summary: Client disconnect causes java.lang.IllegalStateException when using WriteListener Product: Tomcat 8 Version: 8.0.30 Hardware: PC Status: NEW Severity: normal Priority: P2 Component: Catalina Assignee: dev@tomcat.apache.org Reporter: j...@northtech.dk Created attachment 33626 --> https://bz.apache.org/bugzilla/attachment.cgi?id=33626&action=edit Servlet using WriteListener and CompletionStage Putting a servlet into request.startAsync() state and using a CompletionStage.whenComplete to call asyncContext.complete() once data has been written using a Servlet 3.1 non-blocking WriteListener causes java.lang.IllegalStateException: Calling [asyncError()] is not valid for a request with Async state [MUST_COMPLETE] if the client disconnects during write. To reproduce, run the attached source as a servlet in Tomcat, hit the servlet address, and close the browser window before the response it written. This causes a 05-Mar-2016 19:06:13.823 SEVERE [http-apr-8080-exec-6] org.apache.catalina.connector.CoyoteAdapter.asyncDispatch Exception while processing an asynchronous request java.lang.IllegalStateException: Calling [asyncError()] is not valid for a request with Async state [MUST_COMPLETE] at org.apache.coyote.AsyncStateMachine.asyncError(AsyncStateMachine.java:351) at org.apache.coyote.http11.AbstractHttp11Processor.action(AbstractHttp11Processor.java:820) at org.apache.coyote.Request.action(Request.java:378) at org.apache.catalina.core.AsyncContextImpl.setErrorState(AsyncContextImpl.java:419) at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:334) at org.apache.coyote.http11.AbstractHttp11Processor.asyncDispatch(AbstractHttp11Processor.java:1716) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:650) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) I suspect this is caused by the fact that the CompletionStage is completed (exceptionally) by the Tomcat thread handling the NIO write, and in turn, the asyncContext.complete() is called by the same thread. This feels like a sensible structure from a Java 8 perspective, chaining asynchronous operations through CompletionStages, and it works when successfully delivering data. If I use a .whenCompleteAsync, forcing the asyncContext.complete() to another thread, no error is triggered, but it seems overkill to switch thread just to call complete(), and it is in any case inconsistent with the structure working when successfully delivering data. -- You are receiving this mail because: You are the assignee for the bug. --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org