In an async scenario (request.startAsync), when the client goes away, trying to write to the response raises an IOException. If I then call asyncContext.complete() in order to finalize and clean up the request, soon after the following exception occurs: java.lang.IllegalStateException: Calling [asyncError()] is not valid for a request with Async state [COMPLETING] at org.apache.coyote.AsyncStateMachine.asyncError(AsyncStateMachine.java:304) at org.apache.coyote.http11.AbstractHttp11Processor.action(AbstractHttp11Processor.java:793) at org.apache.coyote.Request.action(Request.java:373) at org.apache.catalina.core.AsyncContextImpl.setErrorState(AsyncContextImpl.java:441) at org.apache.catalina.connector.CoyoteAdapter.asyncDispatch(CoyoteAdapter.java:312) at org.apache.coyote.http11.AbstractHttp11Processor.asyncDispatch(AbstractHttp11Processor.java:1509) at org.apache.coyote.http11.Http11NioProcessor.asyncDispatch(Http11NioProcessor.java:221) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:619) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1581) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1540) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:722) It looks like an attempt to maybe to send an error event to AsyncListener's but asyncContext.complete has already been called. Is calling asyncContext.complete() a reasonable way to handle an IOException from the response in order to finalize the request and release any resorces associated with it?
This is a question for the users list if you want to discuss this further (and possibly the Servlet EG as I don't see a clear definition of how an app is expected to handle this in the spec). I'm assuming that the I/O operation that triggers the error does not occur on a container thread. If it occurs in a container thread let Tomcat handle it. Looking at the Tomcat source code, a dispatch to a simple error page should trigger an error when it tries to write to the response which in turn should trigger the onError method of any registered AsyncListener allowing you to do the clean-up.
Okay, I see. It looks like one has to dispatch before calling asyncContext.complete(). I opened this ticket because of the exception but I didn't realize it was illegal ot call complete() from a non-container thread. Maybe that can be detected and rejected with a message to that extent.
(In reply to comment #2) > Okay, I see. It looks like one has to dispatch before calling > asyncContext.complete(). In this case you need the dispatch to get the request back onto a container thread where the error handling can deal with the error. It is this bit I am not 100% is what is intended by the spec but I can't find any clear definitions. > I opened this ticket because of the exception but I > didn't realize it was illegal ot call complete() from a non-container > thread. Maybe that can be detected and rejected with a message to that > extent. It is perfectly valid to call complete() from a non-container thread. Again, the users list is the place to discuss this.
I've been pondering this and having thought about the question you asked on the Servlet spec users list, I have reached the conclusion that allowing complete() makes the most sense here. I'm re-opening this to make this change for 7.0.41 The EG may ultimately come to a different conclusion. We'll deal with that if it happens.
OK, thanks. For what it's worth, from brief experimentation calling complete() in this scenario on Jetty and Glassfish doesn't cause any exceptions. Not sure that means it works but if it doesn't it could be considered a bug since it completes silently.
I think some other changes might have fixed this. Please can you re-test with the latest trunk.
I can confirm the exception no longer appears in the logs. Thanks for fixing this!
(In reply to comment #4) > I'm re-opening this to make this change for 7.0.41 I backported the test case to Tomcat 7 in r1634259. The test case passes successfully.