On 08/12/2014 23:13, Stuart Douglas wrote:
>
>
> Edward Burns wrote:
>>>>>>> On Tue, 09 Dec 2014 08:04:50 +1100, Stuart
>>>>>>> Douglas<sdouglas_at_redhat.com> said:
>>
>> MT> Section 6.2.3 includes the following text:
>> MT> <quote>
>> MT> A Filter and the target servlet or resource at the end of the filter
>> MT> chain must execute in the same invocation thread.
>> MT> </quote>
>> MT>
>> MT> As a result of a bug raised against Apache Tomcat [1] I am seeking
>> MT> clarification of the meaning of that sentence.
>> MT>
>> MT> As written, the meaning seems unambiguous. However, does it apply
>> when
>> MT> the request is in asynchronous mode? To put it another way is the
>> MT> following legal?
>> MT> - filter calls ServletRequest.startAsync()
>> MT> - filter calls AsyncContext.start(Runnable)
>> MT> - That Runnable called FilterChain.doFilter()
>>
>> SD> Another potential problem with doing this is that
>> AsyncContext.start()
>> SD> does not wait for the current call stack to return to the
>> container (at
>> SD> least it is not required to). This means that you will have two
>> threads
>> SD> potentially modifying the response, which is not thread safe.
>>
>> SD> We could modify the behaviour of AsyncContext.start() to wait for
>> the
>> SD> request to return to the container before actually running the task.
>>
>> SD> I think that this is actually a real thread safety problem in the
>> SD> Servlet API, any code that uses AsyncContext.start() and then
>> wants to
>> SD> modify the response cannot be sure the original call stack has
>> returned,
>> SD> and could potentially have thread safety issues.
>>
>> Being new to this spec, I went looking for some catch-all text that
>> calls out these obvious thread safety issues. Indeed, there is section
>> 2.3.3.4 Thread Safety:
>>
>> Spec> Other than the startAsync and complete methods, implementations of
>> Spec> the request and response objects are not guaranteed to be thread
>> Spec> safe. This means that they should either only be used within the
>> Spec> scope of the request handling thread or the application must
>> Spec> ensure that access to the request and response objects are thread
>> Spec> safe.
>>
>> Spec> If a thread created by the application uses the container-managed
>> Spec> objects, such as the request or response object, those objects
>> Spec> must be accessed only within the object's life cycle as
>> Spec> defined in sections Section 3.12, "Lifetime of the Request
>> Spec> Object" on page 3-31and Section 5.7, "Lifetime of the
>> Spec> Response Object" on page 5-50 respectively. Be aware that
>> Spec> other than the startAsync, and complete methods, the request and
>> Spec> response objects are not thread safe. If those objects were
>> Spec> accessed in the multiple threads, the access should be
>> Spec> synchronized or be done through a wrapper to add the thread
>> Spec> safety, for instance, synchronizing the call of the methods to
>> Spec> access the request attribute, or using a local output stream for
>> Spec> the response object within a thread.
>>
>> Need we say more?
>
> I guess my main concern here is that there is not really any way to hand
> off to another thread so that only one thread can be using the
> request/response at a time.
>
> Basically I am talking about some kind of AsyncContext.delayStart()
> construct that will not dispatch the task until the current call stack
> has returned to the container (or just change the semantics of start()
> to match). This will make sure that only one thread is using the request
> and response, without needing to resort to synchronization or other
> thread safety constructs.
I don't see the issue here. Once startAsync() has been called the
container has no need to access the request or the response (until
dispatch() or complete() is called so thread-safe access to these
objects is simply an application concern.
Mark