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

Reply via email to