tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Romain Manni-Bucau <rmannibu...@gmail.com>
Subject Re: async and thread constraint
Date Wed, 11 Feb 2015 13:54:11 GMT
that's it I think

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 <markt@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-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message