You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Péter Gergely Horváth <pe...@gmail.com> on 2016/12/05 13:40:45 UTC

Re: Thread-safety of javax.servlet.Servlet#getServletConfig()

Hi Chris,

Thanks your four input: this question is somewhere in-between... :)

We have *definitely* seen cases, where a piece of code like the one below
sometimes (a couple of times from tens of thousands of successfully
serviced requests) found the stored field to be null - with a
NullPointerException being thrown on the first access of the fooBarService
 field.

@WebServlet("/open")
public class FooBarServlet extends HttpServlet {

    private FooBarService fooBarService;
  @Override
    public void init() throws ServletException {
        try {
            ApplicationContext applicationContext =
                    (ApplicationContext)
getServletContext().getAttribute("springContext");
            fooBarService =
                    applicationContext.getBean("fooBarService",
FooBarService.class);

        } catch (Exception ex) {
            // wrap any exceptions to ServletException so as to comply with
Servlet contract
            throw new ServletException("Initialization failed with
exception", ex);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
        processRequest(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException, IOException {
        processRequest(request, response);
    }

    private void processRequest(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {

        List<FooBar> = fooBarService.getFooBars(); /// we have seen NPEs
thrown from here
/// ...
    }


For the first glance, it seemed to be obvious that it must have been a
threading issue, which could easily be solved by adding volatile to the
stored fooBarService field.

However, I was more than confused seeing
that javax.servlet.GenericServlet#config uses the same approach by simply
storing the ServletConfig into a field and reading it later on without any
locking etc.

I quickly scanned through the Servlet specs and Catalina codes, but cannot
really locate any explicit reference to thread-safety of
javax.servlet.GenericServlet#getServletConfig, that is where the question
originates.

I would by much obliged if you had any inputs, ideas regarding this, or on
the approach one could take to confirm it on his/her own.

Thanks,
Peter


On Mon, Nov 28, 2016 at 6:45 PM, Christopher Schultz <
chris@christopherschultz.net> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
>
> Péter,
>
> On 11/28/16 11:01 AM, Péter Gergely Horváth wrote:
> > Thank you very much for your feedback, but I think there is a
> > slight misunderstanding here: I know the order in which a servlet
> > is initialized and put into service, and this question is not
> > related to that. It's related to the _visibility_ of the field.
> >
> > The question is about the thread safety of the field access: if
> > you carefully check the details of
> > javax.servlet.GenericServlet#config and compare the implementation
> > to the sample "NoVisibility" from the book Java Concurrency in
> > Practice, then it is seems to follow the same pattern, which is
> > "not thread-safe because the value field is accessed from both get
> > and set without synchronization. Among other hazards, it is
> > susceptible to stale values: if one thread calls set, other threads
> > calling get may or may not see that update." [1].
> >
> > Personally, I would like to understand why this implementation is
> > not (if not) susceptible to the stale values phenomenon [2]; there
> > might be someone, who can point me to the right direction.
>
> I think you are correct that there is a theoretical multi-threaded
> race-condition, here. The container may initialize the servlet in one
> thread and service e.g. the first request in another thread, and the
> ServletContext reference might not be written to main memory and then
> read-back by the request-processing thread.
>
> Potential fixes for this would be either to define the ServletContext
> member to be volatile or to use synchronized methods.'
>
> Adding synchronization to the init() method would not be a problem at
> all: there is very little monitor contention at that stage and the
> container would only expect to call that method a single time. Adding
> synchronization to the getServletContext method, though, might
> represent a reduction in performance, since getServletContext gets
> called many times during the lifetime of a Servlet, and from many thread
> s.
>
> Likewise, marking the ServletContext member as "volatile" would
> necessarily require a slow main-memory read every time
> getServletContext is called.
>
> I suspect simple analysis above is the reason for no multithreaded
> protection being placed on the ServletContext member in question.
>
> Péter, is this an academic discussion, or have you in fact seen a case
> where a servlet has been initialized and yet the first thread to
> process a request receives a null value when calling getServletContext?
>
> - -chris
>
> > On Mon, Nov 28, 2016 at 6:08 AM, andreas <an...@junius.info>
> > wrote:
> >
> >> ---- On Fri, 25 Nov 2016 23:02:00 +0930 Péter Gergely Horváth
> >> wrote ----
> >>> Hi All,
> >>>
> >>> I am wondering why calling
> >>> javax.servlet.Servlet#getServletConfig() is thread safe: if you
> >>> check the implementation in javax.servlet.GenericServlet from
> >>> servlet API 3.0.1, you see the
> >> following:
> >>>
> >>> package javax.servlet;
> >>>
> >>> // lines omitted
> >>>
> >>> public abstract class GenericServlet implements Servlet,
> >>> ServletConfig, java.io.Serializable { // lines omitted
> >>>
> >>> private transient ServletConfig config;
> >>>
> >>> // lines omitted
> >>>
> >>> public void init(ServletConfig config) throws ServletException
> >>> { this.config = config; this.init(); }
> >>>
> >>> // lines omitted
> >>>
> >>> public ServletConfig getServletConfig() { return config; } //
> >>> lines omitted }
> >>>
> >>>
> >>> The field config is written in init(ServletConfig) without any
> >>> synchronization, locking or config being volatile, while
> >> getServletConfig()
> >>> could be called anytime from any later worker thread of the
> >>> servlet container. I took a quick look into Tomcat/Catalina
> >>> code base, however I see no indication of the servlet container
> >>> performing any magic, which would guarantee thread safe access
> >>> to field config through getServletConfig() from e.g.
> >>> javax.servlet.GenericServlet#service(ServletRequest,
> >>> ServletResponse) and the corresponding methods in
> >>> javax.servlet.http.HttpServlet.
> >>>
> >>> Am I missing something here? What will guarantee that if Thread
> >>> A is used to init(ServletConfig) then Thread B calling
> >>> getServletConfig() will see the correct state of the field
> >>> config (Java "happens-before"), and not
> >> e.g.
> >>> null?
> >>>
> >>> I am asking this because I have seen some legacy code, where a
> >>> servlet stored something into a field inside the init() method,
> >>> which was then
> >> used
> >>> from within a javax.servlet.http.HttpServlet#doGet or
> >>> javax.servlet.http.HttpServlet#doPost method, without
> >>> synchronization of any kind like this:
> >>>
> >>> public class FoobarServlet extends HttpServlet {
> >>>
> >>> private FoobarService foobarService;
> >>>
> >>> @Override public void init() throws ServletException {
> >>> this.foobarService = // ... acquire foobarService } protected
> >>> void doGet(HttpServletRequest request, HttpServletResponse
> >>> response) throws ServletException, IOException { List<Foobar>
> >>> foobars = this.foobarService.getFoobars(); // read the field
> >>> WITHOUT synchronization // ... } // ... Is this approach
> >>> (having no synchronization, locking or the field being
> >>> volatile) correct? I assumed it is not, seeing something like
> >>> that in the servlet API is quite confusing.
> >>>
> >>>
> >>> What do you think?
> >>>
> >>> Thanks, Peter
> >>
> >>
> >> A Servlet will process requests only if it is fully initialized,
> >> i.e. init has been executed. The init method gets called only
> >> once and the servlet config won't change afterwards. I don't
> >> think there is need for synchronization. The same is probably
> >> valid for your own objects. Problems arise when individual
> >> requests change the state of these objects.
> >>
> >> Andy
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >> ---------------------------------------------------------------------
> >>
> >>
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> >> For additional commands, e-mail: users-help@tomcat.apache.org
> >>
> >>
> >
> -----BEGIN PGP SIGNATURE-----
> Comment: GPGTools - http://gpgtools.org
> Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
>
> iQIcBAEBCAAGBQJYPG0dAAoJEBzwKT+lPKRYkLUP/3JrIPCjIsmw4o71nmZUeN4r
> 0rt1ccflgjFUmpff5Pt9kHWJR60tga+sFT0jQ7LEvggbua1SoXV4y4MDINgEQ/Uu
> ek0aiDRR0n8xXxUWcx7P8Jjmn5yyOGUrFVw029dD55XT6ArYz7gaAUnowRKB6DR+
> RT84yO14TlRZx8DDLoxegmUpmXDpoHZyPKGGYWDhNepiU00X1YmFg/G3CiXJEjzd
> B3GBewhE8nh9GZsqfg7U1V9EBQI+8jeI/GxRTSnsUwWDKvH7Ja6ffiLtAS+3mnWD
> Ad2/wTbY7RT9ybT+thgvXkKJEKx+rVZrazb7QSgqq8Otv/aeMVLh16z2sxt6uuMy
> fffKRwNUL12cKr8KdNvUnb4PVStVF8fnRxAW1M90axzFvxeoLOJJZXtS6TBy+MjE
> eeMbjFV2wJw2y+66YWrvyCglyQU4c2ab5H0JuBINJ5oD1DSdTks0dW2rZvIm6pYp
> kCQTLSbZFjePksoNw6gxDo5XQW1SczWbTG2lYwEjfm3eeyHRnaRgiV4LPBPsx5Zy
> 7QFZJVGSFug2pgKTKErugoQs8z4gFCrryvebbGYgtvlsdJRk5Ldnl6uG0KabAEVU
> PedppbSTPPkE8Ym+/YTTpJ4Bo5NMjkoYySWnWpBLof5sJ1hkjkURc4cBiFw4vqZO
> K7WcPH4LDk5J5HzFiTIS
> =DLPe
> -----END PGP SIGNATURE-----
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>

Re: Thread-safety of javax.servlet.Servlet#getServletConfig()

Posted by "Terence M. Bandoian" <te...@tmbsw.com>.
On 12/5/2016 7:40 AM, P�ter Gergely Horv�th wrote:
> Hi Chris,
>
> Thanks your four input: this question is somewhere in-between... :)
>
> We have *definitely* seen cases, where a piece of code like the one below
> sometimes (a couple of times from tens of thousands of successfully
> serviced requests) found the stored field to be null - with a
> NullPointerException being thrown on the first access of the fooBarService
>   field.
>
> @WebServlet("/open")
> public class FooBarServlet extends HttpServlet {
>
>      private FooBarService fooBarService;
>    @Override
>      public void init() throws ServletException {
>          try {
>              ApplicationContext applicationContext =
>                      (ApplicationContext)
> getServletContext().getAttribute("springContext");
>              fooBarService =
>                      applicationContext.getBean("fooBarService",
> FooBarService.class);
>
>          } catch (Exception ex) {
>              // wrap any exceptions to ServletException so as to comply with
> Servlet contract
>              throw new ServletException("Initialization failed with
> exception", ex);


Does this exception ever occur?

-Terence Bandoian


>          }
>      }
>
>      protected void doGet(HttpServletRequest request, HttpServletResponse
> response) throws ServletException, IOException {
>          processRequest(request, response);
>      }
>
>      protected void doPost(HttpServletRequest request, HttpServletResponse
> response) throws ServletException, IOException {
>          processRequest(request, response);
>      }
>
>      private void processRequest(HttpServletRequest request,
> HttpServletResponse response) throws IOException, ServletException {
>
>          List<FooBar> = fooBarService.getFooBars(); /// we have seen NPEs
> thrown from here
> /// ...
>      }
>
>
> For the first glance, it seemed to be obvious that it must have been a
> threading issue, which could easily be solved by adding volatile to the
> stored fooBarService field.
>
> However, I was more than confused seeing
> that javax.servlet.GenericServlet#config uses the same approach by simply
> storing the ServletConfig into a field and reading it later on without any
> locking etc.
>
> I quickly scanned through the Servlet specs and Catalina codes, but cannot
> really locate any explicit reference to thread-safety of
> javax.servlet.GenericServlet#getServletConfig, that is where the question
> originates.
>
> I would by much obliged if you had any inputs, ideas regarding this, or on
> the approach one could take to confirm it on his/her own.
>
> Thanks,
> Peter
>
>
> On Mon, Nov 28, 2016 at 6:45 PM, Christopher Schultz <
> chris@christopherschultz.net> wrote:
>
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA256
>>
>> P�ter,
>>
>> On 11/28/16 11:01 AM, P�ter Gergely Horv�th wrote:
>>> Thank you very much for your feedback, but I think there is a
>>> slight misunderstanding here: I know the order in which a servlet
>>> is initialized and put into service, and this question is not
>>> related to that. It's related to the _visibility_ of the field.
>>>
>>> The question is about the thread safety of the field access: if
>>> you carefully check the details of
>>> javax.servlet.GenericServlet#config and compare the implementation
>>> to the sample "NoVisibility" from the book Java Concurrency in
>>> Practice, then it is seems to follow the same pattern, which is
>>> "not thread-safe because the value field is accessed from both get
>>> and set without synchronization. Among other hazards, it is
>>> susceptible to stale values: if one thread calls set, other threads
>>> calling get may or may not see that update." [1].
>>>
>>> Personally, I would like to understand why this implementation is
>>> not (if not) susceptible to the stale values phenomenon [2]; there
>>> might be someone, who can point me to the right direction.
>> I think you are correct that there is a theoretical multi-threaded
>> race-condition, here. The container may initialize the servlet in one
>> thread and service e.g. the first request in another thread, and the
>> ServletContext reference might not be written to main memory and then
>> read-back by the request-processing thread.
>>
>> Potential fixes for this would be either to define the ServletContext
>> member to be volatile or to use synchronized methods.'
>>
>> Adding synchronization to the init() method would not be a problem at
>> all: there is very little monitor contention at that stage and the
>> container would only expect to call that method a single time. Adding
>> synchronization to the getServletContext method, though, might
>> represent a reduction in performance, since getServletContext gets
>> called many times during the lifetime of a Servlet, and from many thread
>> s.
>>
>> Likewise, marking the ServletContext member as "volatile" would
>> necessarily require a slow main-memory read every time
>> getServletContext is called.
>>
>> I suspect simple analysis above is the reason for no multithreaded
>> protection being placed on the ServletContext member in question.
>>
>> P�ter, is this an academic discussion, or have you in fact seen a case
>> where a servlet has been initialized and yet the first thread to
>> process a request receives a null value when calling getServletContext?
>>
>> - -chris
>>
>>> On Mon, Nov 28, 2016 at 6:08 AM, andreas <an...@junius.info>
>>> wrote:
>>>
>>>> ---- On Fri, 25 Nov 2016 23:02:00 +0930 P�ter Gergely Horv�th
>>>> wrote ----
>>>>> Hi All,
>>>>>
>>>>> I am wondering why calling
>>>>> javax.servlet.Servlet#getServletConfig() is thread safe: if you
>>>>> check the implementation in javax.servlet.GenericServlet from
>>>>> servlet API 3.0.1, you see the
>>>> following:
>>>>> package javax.servlet;
>>>>>
>>>>> // lines omitted
>>>>>
>>>>> public abstract class GenericServlet implements Servlet,
>>>>> ServletConfig, java.io.Serializable { // lines omitted
>>>>>
>>>>> private transient ServletConfig config;
>>>>>
>>>>> // lines omitted
>>>>>
>>>>> public void init(ServletConfig config) throws ServletException
>>>>> { this.config = config; this.init(); }
>>>>>
>>>>> // lines omitted
>>>>>
>>>>> public ServletConfig getServletConfig() { return config; } //
>>>>> lines omitted }
>>>>>
>>>>>
>>>>> The field config is written in init(ServletConfig) without any
>>>>> synchronization, locking or config being volatile, while
>>>> getServletConfig()
>>>>> could be called anytime from any later worker thread of the
>>>>> servlet container. I took a quick look into Tomcat/Catalina
>>>>> code base, however I see no indication of the servlet container
>>>>> performing any magic, which would guarantee thread safe access
>>>>> to field config through getServletConfig() from e.g.
>>>>> javax.servlet.GenericServlet#service(ServletRequest,
>>>>> ServletResponse) and the corresponding methods in
>>>>> javax.servlet.http.HttpServlet.
>>>>>
>>>>> Am I missing something here? What will guarantee that if Thread
>>>>> A is used to init(ServletConfig) then Thread B calling
>>>>> getServletConfig() will see the correct state of the field
>>>>> config (Java "happens-before"), and not
>>>> e.g.
>>>>> null?
>>>>>
>>>>> I am asking this because I have seen some legacy code, where a
>>>>> servlet stored something into a field inside the init() method,
>>>>> which was then
>>>> used
>>>>> from within a javax.servlet.http.HttpServlet#doGet or
>>>>> javax.servlet.http.HttpServlet#doPost method, without
>>>>> synchronization of any kind like this:
>>>>>
>>>>> public class FoobarServlet extends HttpServlet {
>>>>>
>>>>> private FoobarService foobarService;
>>>>>
>>>>> @Override public void init() throws ServletException {
>>>>> this.foobarService = // ... acquire foobarService } protected
>>>>> void doGet(HttpServletRequest request, HttpServletResponse
>>>>> response) throws ServletException, IOException { List<Foobar>
>>>>> foobars = this.foobarService.getFoobars(); // read the field
>>>>> WITHOUT synchronization // ... } // ... Is this approach
>>>>> (having no synchronization, locking or the field being
>>>>> volatile) correct? I assumed it is not, seeing something like
>>>>> that in the servlet API is quite confusing.
>>>>>
>>>>>
>>>>> What do you think?
>>>>>
>>>>> Thanks, Peter
>>>>
>>>> A Servlet will process requests only if it is fully initialized,
>>>> i.e. init has been executed. The init method gets called only
>>>> once and the servlet config won't change afterwards. I don't
>>>> think there is need for synchronization. The same is probably
>>>> valid for your own objects. Problems arise when individual
>>>> requests change the state of these objects.
>>>>
>>>> Andy
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>>
>>>>
>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>>>> For additional commands, e-mail: users-help@tomcat.apache.org
>>>>
>>>>
>> -----BEGIN PGP SIGNATURE-----
>> Comment: GPGTools - http://gpgtools.org
>> Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
>>
>> iQIcBAEBCAAGBQJYPG0dAAoJEBzwKT+lPKRYkLUP/3JrIPCjIsmw4o71nmZUeN4r
>> 0rt1ccflgjFUmpff5Pt9kHWJR60tga+sFT0jQ7LEvggbua1SoXV4y4MDINgEQ/Uu
>> ek0aiDRR0n8xXxUWcx7P8Jjmn5yyOGUrFVw029dD55XT6ArYz7gaAUnowRKB6DR+
>> RT84yO14TlRZx8DDLoxegmUpmXDpoHZyPKGGYWDhNepiU00X1YmFg/G3CiXJEjzd
>> B3GBewhE8nh9GZsqfg7U1V9EBQI+8jeI/GxRTSnsUwWDKvH7Ja6ffiLtAS+3mnWD
>> Ad2/wTbY7RT9ybT+thgvXkKJEKx+rVZrazb7QSgqq8Otv/aeMVLh16z2sxt6uuMy
>> fffKRwNUL12cKr8KdNvUnb4PVStVF8fnRxAW1M90axzFvxeoLOJJZXtS6TBy+MjE
>> eeMbjFV2wJw2y+66YWrvyCglyQU4c2ab5H0JuBINJ5oD1DSdTks0dW2rZvIm6pYp
>> kCQTLSbZFjePksoNw6gxDo5XQW1SczWbTG2lYwEjfm3eeyHRnaRgiV4LPBPsx5Zy
>> 7QFZJVGSFug2pgKTKErugoQs8z4gFCrryvebbGYgtvlsdJRk5Ldnl6uG0KabAEVU
>> PedppbSTPPkE8Ym+/YTTpJ4Bo5NMjkoYySWnWpBLof5sJ1hkjkURc4cBiFw4vqZO
>> K7WcPH4LDk5J5HzFiTIS
>> =DLPe
>> -----END PGP SIGNATURE-----
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: users-help@tomcat.apache.org
>>
>>


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


Re: Thread-safety of javax.servlet.Servlet#getServletConfig()

Posted by Mark Thomas <ma...@apache.org>.
On 05/12/2016 13:40, P�ter Gergely Horv�th wrote:
> Hi Chris,
> 
> Thanks your four input: this question is somewhere in-between... :)
> 
> We have *definitely* seen cases, where a piece of code like the one below
> sometimes (a couple of times from tens of thousands of successfully
> serviced requests) found the stored field to be null - with a
> NullPointerException being thrown on the first access of the fooBarService
>  field.
> 
> @WebServlet("/open")
> public class FooBarServlet extends HttpServlet {
> 
>     private FooBarService fooBarService;
>   @Override
>     public void init() throws ServletException {
>         try {
>             ApplicationContext applicationContext =
>                     (ApplicationContext)
> getServletContext().getAttribute("springContext");
>             fooBarService =
>                     applicationContext.getBean("fooBarService",
> FooBarService.class);
> 
>         } catch (Exception ex) {
>             // wrap any exceptions to ServletException so as to comply with
> Servlet contract
>             throw new ServletException("Initialization failed with
> exception", ex);
>         }
>     }
> 
>     protected void doGet(HttpServletRequest request, HttpServletResponse
> response) throws ServletException, IOException {
>         processRequest(request, response);
>     }
> 
>     protected void doPost(HttpServletRequest request, HttpServletResponse
> response) throws ServletException, IOException {
>         processRequest(request, response);
>     }
> 
>     private void processRequest(HttpServletRequest request,
> HttpServletResponse response) throws IOException, ServletException {
> 
>         List<FooBar> = fooBarService.getFooBars(); /// we have seen NPEs
> thrown from here
> /// ...
>     }
> 
> 
> For the first glance, it seemed to be obvious that it must have been a
> threading issue, which could easily be solved by adding volatile to the
> stored fooBarService field.
> 
> However, I was more than confused seeing
> that javax.servlet.GenericServlet#config uses the same approach by simply
> storing the ServletConfig into a field and reading it later on without any
> locking etc.
> 
> I quickly scanned through the Servlet specs and Catalina codes, but cannot
> really locate any explicit reference to thread-safety of
> javax.servlet.GenericServlet#getServletConfig, that is where the question
> originates.
> 
> I would by much obliged if you had any inputs, ideas regarding this, or on
> the approach one could take to confirm it on his/her own.

In theory, it is a problem.

In practise, I'd be surprised if anyone was ever troubled by it.

Since it appears you did hit this issue, open a bug report and we'll get
Tomcat's implementation fixed.

Mark


> 
> Thanks,
> Peter
> 
> 
> On Mon, Nov 28, 2016 at 6:45 PM, Christopher Schultz <
> chris@christopherschultz.net> wrote:
> 
> P�ter,
> 
> On 11/28/16 11:01 AM, P�ter Gergely Horv�th wrote:
>>>> Thank you very much for your feedback, but I think there is a
>>>> slight misunderstanding here: I know the order in which a servlet
>>>> is initialized and put into service, and this question is not
>>>> related to that. It's related to the _visibility_ of the field.
>>>>
>>>> The question is about the thread safety of the field access: if
>>>> you carefully check the details of
>>>> javax.servlet.GenericServlet#config and compare the implementation
>>>> to the sample "NoVisibility" from the book Java Concurrency in
>>>> Practice, then it is seems to follow the same pattern, which is
>>>> "not thread-safe because the value field is accessed from both get
>>>> and set without synchronization. Among other hazards, it is
>>>> susceptible to stale values: if one thread calls set, other threads
>>>> calling get may or may not see that update." [1].
>>>>
>>>> Personally, I would like to understand why this implementation is
>>>> not (if not) susceptible to the stale values phenomenon [2]; there
>>>> might be someone, who can point me to the right direction.
> 
> I think you are correct that there is a theoretical multi-threaded
> race-condition, here. The container may initialize the servlet in one
> thread and service e.g. the first request in another thread, and the
> ServletContext reference might not be written to main memory and then
> read-back by the request-processing thread.
> 
> Potential fixes for this would be either to define the ServletContext
> member to be volatile or to use synchronized methods.'
> 
> Adding synchronization to the init() method would not be a problem at
> all: there is very little monitor contention at that stage and the
> container would only expect to call that method a single time. Adding
> synchronization to the getServletContext method, though, might
> represent a reduction in performance, since getServletContext gets
> called many times during the lifetime of a Servlet, and from many thread
> s.
> 
> Likewise, marking the ServletContext member as "volatile" would
> necessarily require a slow main-memory read every time
> getServletContext is called.
> 
> I suspect simple analysis above is the reason for no multithreaded
> protection being placed on the ServletContext member in question.
> 
> P�ter, is this an academic discussion, or have you in fact seen a case
> where a servlet has been initialized and yet the first thread to
> process a request receives a null value when calling getServletContext?
> 
> -chris
> 
>>>> On Mon, Nov 28, 2016 at 6:08 AM, andreas <an...@junius.info>
>>>> wrote:
>>>>
>>>>> ---- On Fri, 25 Nov 2016 23:02:00 +0930 P�ter Gergely Horv�th
>>>>> wrote ----
>>>>>> Hi All,
>>>>>>
>>>>>> I am wondering why calling
>>>>>> javax.servlet.Servlet#getServletConfig() is thread safe: if you
>>>>>> check the implementation in javax.servlet.GenericServlet from
>>>>>> servlet API 3.0.1, you see the
>>>>> following:
>>>>>>
>>>>>> package javax.servlet;
>>>>>>
>>>>>> // lines omitted
>>>>>>
>>>>>> public abstract class GenericServlet implements Servlet,
>>>>>> ServletConfig, java.io.Serializable { // lines omitted
>>>>>>
>>>>>> private transient ServletConfig config;
>>>>>>
>>>>>> // lines omitted
>>>>>>
>>>>>> public void init(ServletConfig config) throws ServletException
>>>>>> { this.config = config; this.init(); }
>>>>>>
>>>>>> // lines omitted
>>>>>>
>>>>>> public ServletConfig getServletConfig() { return config; } //
>>>>>> lines omitted }
>>>>>>
>>>>>>
>>>>>> The field config is written in init(ServletConfig) without any
>>>>>> synchronization, locking or config being volatile, while
>>>>> getServletConfig()
>>>>>> could be called anytime from any later worker thread of the
>>>>>> servlet container. I took a quick look into Tomcat/Catalina
>>>>>> code base, however I see no indication of the servlet container
>>>>>> performing any magic, which would guarantee thread safe access
>>>>>> to field config through getServletConfig() from e.g.
>>>>>> javax.servlet.GenericServlet#service(ServletRequest,
>>>>>> ServletResponse) and the corresponding methods in
>>>>>> javax.servlet.http.HttpServlet.
>>>>>>
>>>>>> Am I missing something here? What will guarantee that if Thread
>>>>>> A is used to init(ServletConfig) then Thread B calling
>>>>>> getServletConfig() will see the correct state of the field
>>>>>> config (Java "happens-before"), and not
>>>>> e.g.
>>>>>> null?
>>>>>>
>>>>>> I am asking this because I have seen some legacy code, where a
>>>>>> servlet stored something into a field inside the init() method,
>>>>>> which was then
>>>>> used
>>>>>> from within a javax.servlet.http.HttpServlet#doGet or
>>>>>> javax.servlet.http.HttpServlet#doPost method, without
>>>>>> synchronization of any kind like this:
>>>>>>
>>>>>> public class FoobarServlet extends HttpServlet {
>>>>>>
>>>>>> private FoobarService foobarService;
>>>>>>
>>>>>> @Override public void init() throws ServletException {
>>>>>> this.foobarService = // ... acquire foobarService } protected
>>>>>> void doGet(HttpServletRequest request, HttpServletResponse
>>>>>> response) throws ServletException, IOException { List<Foobar>
>>>>>> foobars = this.foobarService.getFoobars(); // read the field
>>>>>> WITHOUT synchronization // ... } // ... Is this approach
>>>>>> (having no synchronization, locking or the field being
>>>>>> volatile) correct? I assumed it is not, seeing something like
>>>>>> that in the servlet API is quite confusing.
>>>>>>
>>>>>>
>>>>>> What do you think?
>>>>>>
>>>>>> Thanks, Peter
>>>>>
>>>>>
>>>>> A Servlet will process requests only if it is fully initialized,
>>>>> i.e. init has been executed. The init method gets called only
>>>>> once and the servlet config won't change afterwards. I don't
>>>>> think there is need for synchronization. The same is probably
>>>>> valid for your own objects. Problems arise when individual
>>>>> requests change the state of these objects.
>>>>>
>>>>> Andy
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>>
>>>>>
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>>>>> For additional commands, e-mail: users-help@tomcat.apache.org
>>>>>
>>>>>
>>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
>> For additional commands, e-mail: users-help@tomcat.apache.org
>>
>>
> 


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