jsr369-experts@servlet-spec.java.net

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

From: 정의근 <Eugene>
Date: Wed, 10 Dec 2014 10:20:23 +0900

On Tue, Dec 9, 2014 at 8:13 AM, Stuart Douglas <stuart.w.douglas_at_gmail.com>
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.
>
> Stuart
>
>
>
+1

For AsyncContext.dispatch methods, there is the explanation.

" .... If this method is called before the container-initiated dispatch
that called startAsync has returned to the container, the dispatch
operation will be delayed until after the container-initiated dispatch has
returned to the container. ..... "

I also think AsyncContext.start() should have same requirement.



>
>
>
>> Ed
>>
>>