all green with the trunk. That you very much.
Romain Manni-Bucau @rmannibucau http://www.tomitribe.com http://rmannibucau.wordpress.com https://github.com/rmannibucau 2015-02-11 15:31 GMT+01:00 Mark Thomas <ma...@apache.org>: > On 11/02/2015 13:54, Romain Manni-Bucau wrote: >> that's it I think > > OK. Patch applied to trunk and 8.0.x. Let us know how you get on. > > Mark > > >> >> If you want servlet code let's do it (wanted to avoid code in mail >> since I never manage to format it well): >> >> 1) request 1 (start the async context) does: >> >> // field context has type AsyncContext >> context = req.startAsync(req, resp); >> context.addListener(this); // not important for us but it is mainly to >> handle errors etc >> context.setTimeout(valueFromAnywhere); >> >> 2) request 2 does in its thread: >> >> // i skip some jaxrs impl internals like getting the response to push >> to the client for request 1 etc >> context.dispatch(); >> >> And that's all in term of servlet API then you go back in servlet >> chain and end on JAXRS servlet (or filter) which identified this >> dispatch as a continuation and returns the expected data instead of >> doing again request 1 call. >> >> >> In term of tomcat calls we end up in >> org.apache.catalina.core.AsyncContextImpl#dispatch(javax.servlet.ServletContext, >> java.lang.String) and then >> this.request.getCoyoteRequest().action(ActionCode.ASYNC_DISPATCH, >> null);. >> >> Finally we are in >> org.apache.coyote.http11.AbstractHttp11Processor#action which does >> >> if (asyncStateMachine.asyncDispatch()) { >> endpoint.processSocket(this.socketWrapper, SocketStatus.OPEN_READ, true); >> } >> >> and org.apache.coyote.AsyncStateMachine#asyncDispatch checks >> ContainerThreadMarker.isContainerThread() which is obviously true >> since request 2 is a normal request so dispatch is skipped and >> response is never sent (well not as expected and we get a timeout). >> >> >> >> Romain Manni-Bucau >> @rmannibucau >> http://www.tomitribe.com >> http://rmannibucau.wordpress.com >> https://github.com/rmannibucau >> >> >> 2015-02-11 14:27 GMT+01:00 Mark Thomas <ma...@apache.org>: >>> On 11/02/2015 09:35, Romain Manni-Bucau wrote: >>>> Ok, let's look a jaxrs 2 sample and bind underlying implementation: >>>> >>>> @Path("touch") >>>> @ApplicationScoped >>>> public class Endpoint { >>>> private volatile AsyncResponse current; >>>> >>>> @GET >>>> public void async(@Suspended final AsyncResponse response) { >>>> if (current == null) { >>>> current = response; >>>> } else { >>>> throw new IllegalStateException("we shouldnt go here >>>> back since"); >>>> } >>>> } >>>> >>>> @POST >>>> @Path("answer") >>>> public void async(final String response) { >>>> current.resume(response /* response content */); // spec >>>> doesnt mandate a new thread here but tomcat does >>>> } >>>> } >>>> >>>> So we have 2 methods: >>>> 1) GET: this initiate a request. JAXRS implementation uses servlet >>>> container to get an AsyncContext no more >>>> 2) POST: the JAXRS AsyncResponse#resume method will just call servlet >>>> AsyncContext#dispatch >>>> >>>> Issue is:dispatch is called in the ThreadLocal environment/context of >>>> POST request so resume/dispatch inherit from it. Finally when you go >>>> to the async dispatch in Coyoterequest you have a marker bound in >>>> ContainerThreadMarker (the POST one) so resume/dispatch is ignored but >>>> actually it should work. >>>> >>>> Is it clearer? >>> >>> Not really for me. The description is assuming a familiarity with JAXRS2 >>> that I don't have. Reading between the lines of what you have written I >>> think I have found a problem but I am not sure it is the problem you are >>> trying to describe. >>> >>> Consider the following which is described purely in terms of Servlet async: >>> >>> The first HTTP request (Req1) calls startAsync which creates the >>> AsyncContext (AC1), stashes AC1 somewhere and then returns. >>> >>> The client then waits for the response (Res1). >>> >>> >>> Some time later (but before the AsyncContext and client read timeout) a >>> new HTTP request (Req2) retrieves the AsyncContext and calls dispatch(). >>> >>> This dispatch() *always* needs to be on a new container thread because >>> the current container thread is processing Req2/Res2 and the dispatch is >>> for Req1/Res1. >>> >>> The bug is the test introduced in r1594198 is that the dispatch() was >>> processed in the context of Req2/Res2. >>> >>> >>> Note in all of the above I am ignoring how/where the AsyncContext is >>> stashed and retrieved. >>> >>> >>> I think I can put together a test case for the above. If this is the >>> problem you are seeing then the patch should be fairly easy. The part >>> that will take the time is reviewing the other Async states affected by >>> r1594198 to determine if the same problem might occur for any of them. >>> >>> Mark >>> >>> >>> --------------------------------------------------------------------- >>> To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org >>> For additional commands, e-mail: dev-h...@tomcat.apache.org >>> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org >> For additional commands, e-mail: dev-h...@tomcat.apache.org >> > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org > For additional commands, e-mail: dev-h...@tomcat.apache.org > --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org