jsr369-experts@servlet-spec.java.net

[jsr369-experts] Re: [servlet-spec users] Re: Clarification of threading requirements of section 6.2.3

From: Stuart Douglas <stuart.w.douglas_at_gmail.com>
Date: Tue, 09 Dec 2014 10:13:59 +1100

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.

Stuart




>
> Ed
>