Bug 49698 - AsyncContext timeout always return http 500
AsyncContext timeout always return http 500
Status: RESOLVED FIXED
Product: Tomcat 7
Classification: Unclassified
Component: Catalina
trunk
PC All
: P2 major (vote)
: ---
Assigned To: Tomcat Developers Mailing List
:
Depends on:
Blocks:
  Show dependency tree
 
Reported: 2010-08-03 22:42 UTC by heyoulin
Modified: 2010-08-28 07:09 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description heyoulin 2010-08-03 22:42:38 UTC
Whatever asynclistener timeout call complete response always return http 500.
Comment 1 Mark Thomas 2010-08-04 07:09:57 UTC
Which version are you using?

There were a number of fixes in this area included in 7.0.2 (currently being voted on for release).

Whilst the release vote is in progress, you can get a copy for testing from here:
http://people.apache.org/~markt/dev/tomcat-7/v7.0.2/

Note that this is NOT an official release.
Comment 2 heyoulin 2010-08-04 12:02:52 UTC
(In reply to comment #1)
> Which version are you using?
> There were a number of fixes in this area included in 7.0.2 (currently being
> voted on for release).
> Whilst the release vote is in progress, you can get a copy for testing from
> here:
> http://people.apache.org/~markt/dev/tomcat-7/v7.0.2/
> Note that this is NOT an official release.

I build from svn sources. From the sources:
public void doInternalDispatch() throws ServletException, IOException {
        if (this.state.compareAndSet(AsyncState.TIMING_OUT, AsyncState.COMPLETING)) {
            log.debug("TIMING OUT!");
            boolean listenerInvoked = false;
            for (AsyncListenerWrapper listener : listeners) {
                listener.fireOnTimeout(event);
                listenerInvoked = true;
            }
            if (listenerInvoked) {
                // Listener should have called complete
                if (state.get() != AsyncState.NOT_STARTED) {
                    ((HttpServletResponse)servletResponse).setStatus(500);
                    doInternalComplete(true);
                }
           .......

When timeout AsyncState is COMPLETING. But complete method do nothing to COMPLETING state:
public void complete() {
        if (log.isDebugEnabled()) {
            log.debug("AsyncContext Complete Called["+state.get()+"; "+request.getRequestURI()+"?"+request.getQueryString()+"]", new DebugException());
        }
        if (state.get()==AsyncState.COMPLETING) {
            //do nothing
        }

So always return http500. It has changed since svn revision 966548.In revision 960692 is below:

ublic void doInternalDispatch() throws ServletException, IOException {
        if (this.state.compareAndSet(AsyncState.TIMING_OUT, AsyncState.COMPLETING)) {
            log.debug("TIMING OUT!");
            boolean listenerInvoked = false;
            for (AsyncListenerWrapper listener : listeners) {
                listener.fireOnTimeout(event);
                listenerInvoked = true;
            }
            if (!listenerInvoked) {
                ((HttpServletResponse)servletResponse).setStatus(500);
            }
            doInternalComplete(true);
Comment 3 Mark Thomas 2010-08-04 12:35:27 UTC
You are required by the spec to implement a listener to handle the timeout.
Comment 4 heyoulin 2010-08-04 13:03:05 UTC
(In reply to comment #3)
> You are required by the spec to implement a listener to handle the timeout.
I have a listener to handle the timeout.
public void onTimeout(AsyncEvent event) throws IOException {
		event.getAsyncContext().complete();
	}

When implement event.getAsyncContext().complete() actually tomcat do nothing.AsyncState is still in COMPLETING.So return http500.

So how to handle the timeout to make AsyncState to NOT_STARTED only using servlet 3.0 api?
Comment 5 Mark Thomas 2010-08-04 13:09:49 UTC
OK, let me take a look.
Comment 6 Mark Thomas 2010-08-28 07:09:09 UTC
Yep. It was a bug in the state machine. I have fixed this for 7.0.x and it will be included in 7.0.3 onwards.

Thanks for the report.