You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Raymond <pp...@hotmail.com> on 2005/03/12 08:24:41 UTC

strange bug: global created twice

Hi Tapestry Users,

There's a strange bug happening with our production Tapestry app (it never 
happened in the testing environment).

The log file of the app shows that the Global object was created twice 
(actually the "protected engine.createGlobal(cycle)" method was called 
twice, sometimes even called many times) when the app was initializing. The 
extra Global object was found to die after 10 hours (by seeing the log 
statement in the Global object's finalize() method). And the webapp 
continues to run normally. But some internal states were messed up because 
we use the global object's private fields to store many application states 
and datetime value for various periodic jobs.

Our production environment is quite busy and whenever the app is undeployed 
and redeployed for a few minutes we could see in the Tomcat log many failed 
requests. So I suspect perhaps the problem was the webapp received several 
concurrent requests before it fully initialized itself when the app was 
creating the Engine object. So createGlobal might be called twice and the 2 
global objects may be used by different threads. A global object died when 
no more thread was referencing it.

We are using Tomcat 5.028 with jdk 1.4.2_06 on a qutie slow machine.

Has anyone experienced similar problem? Does it mean that the createGlobal 
method is not thread-safe? Any solution?

Thanks very much for help.
Raymond 

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: strange bug: global created twice

Posted by Hanson Char <ha...@gmail.com>.
The proposed quick fix can be further optimized by moving the
servletContext.setAttribute outside the synchronized block:

    private final int[] LOCK_GLOBAL = {};

    protected void setupForRequest(RequestContext context)
    {
...
        boolean isGlobalCreated = false;
        
        synchronized(LOCK_GLOBAL) {
            if (_global == null)
            {
                _global = createGlobal(context);
                isGlobalCreated = true;
            }
        }
        if (isGlobalCreated) {
            String name = GLOBAL_NAME + ":" + servletName;
            servletContext.setAttribute(name, _global);
        }
...
   }

    public Object getGlobal()
    {
        synchronized(LOCK_GLOBAL) {
            return _global;
        }
    }

H

On Sun, 13 Mar 2005 02:56:47 +1100, Hanson Char <ha...@gmail.com> wrote:
> Also, to be completely thread-safe, the AbstractEngine.getGlobal
> method also needs synchronization (to avoid the caller to ever get
> access to a partially initialized global object.)
> 
>     public Object getGlobal()
>     {
>         synchronized(LOCK_GLOBAL) {
>             return _global;
>         }
>     }
> 
> H
> 
> On Sat, 12 Mar 2005 21:43:07 +1100, Hanson Char <ha...@gmail.com> wrote:
> > The logic within the synchronzied block can be further simplified into:
> >
> >         synchronized(LOCK_GLOBAL) {
> >             if (_global == null)
> >             {
> >                 String name = GLOBAL_NAME + ":" + servletName;
> >                 _global = createGlobal(context);
> >                 servletContext.setAttribute(name, _global);
> >             }
> >         }
> >
> > H
> >
> > On Sat, 12 Mar 2005 21:33:24 +1100, Hanson Char <ha...@gmail.com> wrote:
> > > From a cursory look at the AbstractEngine.java of Tapestry 3.0.2, it
> > > does seem the initialization of _global is not thread-safe.  A quick
> > > fix would be to add a lock and synchronize on it.
> > >
> > > Example:
> > >
> > >     // add a lock monitor for _global
> > >     private final int[] LOCK_GLOBAL = {};
> > >
> > > ...
> > >         synchronized(LOCK_GLOBAL) {
> > >             if (_global == null)
> > >             {
> > >                 String name = GLOBAL_NAME + ":" + servletName;
> > >
> > >                 _global = servletContext.getAttribute(name);
> > >
> > >                 if (_global == null)
> > >                 {
> > >                     _global = createGlobal(context);
> > >
> > >                     servletContext.setAttribute(name, _global);
> > >                 }
> > >             }
> > >         }
> > >
> > > H
> > >
> > >
> > > On Sat, 12 Mar 2005 15:24:41 +0800, Raymond <pp...@hotmail.com> wrote:
> > > > Hi Tapestry Users,
> > > >
> > > > There's a strange bug happening with our production Tapestry app (it never
> > > > happened in the testing environment).
> > > >
> > > > The log file of the app shows that the Global object was created twice
> > > > (actually the "protected engine.createGlobal(cycle)" method was called
> > > > twice, sometimes even called many times) when the app was initializing. The
> > > > extra Global object was found to die after 10 hours (by seeing the log
> > > > statement in the Global object's finalize() method). And the webapp
> > > > continues to run normally. But some internal states were messed up because
> > > > we use the global object's private fields to store many application states
> > > > and datetime value for various periodic jobs.
> > > >
> > > > Our production environment is quite busy and whenever the app is undeployed
> > > > and redeployed for a few minutes we could see in the Tomcat log many failed
> > > > requests. So I suspect perhaps the problem was the webapp received several
> > > > concurrent requests before it fully initialized itself when the app was
> > > > creating the Engine object. So createGlobal might be called twice and the 2
> > > > global objects may be used by different threads. A global object died when
> > > > no more thread was referencing it.
> > > >
> > > > We are using Tomcat 5.028 with jdk 1.4.2_06 on a qutie slow machine.
> > > >
> > > > Has anyone experienced similar problem? Does it mean that the createGlobal
> > > > method is not thread-safe? Any solution?
> > > >
> > > > Thanks very much for help.
> > > > Raymond
> > > >
> > > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> > > > For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> > > >
> > > >
> > >
> >
>

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: strange bug: global created twice

Posted by Hanson Char <ha...@gmail.com>.
Also, to be completely thread-safe, the AbstractEngine.getGlobal
method also needs synchronization (to avoid the caller to ever get
access to a partially initialized global object.)

    public Object getGlobal()
    {
        synchronized(LOCK_GLOBAL) {
            return _global;
        }
    }

H

On Sat, 12 Mar 2005 21:43:07 +1100, Hanson Char <ha...@gmail.com> wrote:
> The logic within the synchronzied block can be further simplified into:
> 
>         synchronized(LOCK_GLOBAL) {
>             if (_global == null)
>             {
>                 String name = GLOBAL_NAME + ":" + servletName;
>                 _global = createGlobal(context);
>                 servletContext.setAttribute(name, _global);
>             }
>         }
> 
> H
> 
> On Sat, 12 Mar 2005 21:33:24 +1100, Hanson Char <ha...@gmail.com> wrote:
> > From a cursory look at the AbstractEngine.java of Tapestry 3.0.2, it
> > does seem the initialization of _global is not thread-safe.  A quick
> > fix would be to add a lock and synchronize on it.
> >
> > Example:
> >
> >     // add a lock monitor for _global
> >     private final int[] LOCK_GLOBAL = {};
> >
> > ...
> >         synchronized(LOCK_GLOBAL) {
> >             if (_global == null)
> >             {
> >                 String name = GLOBAL_NAME + ":" + servletName;
> >
> >                 _global = servletContext.getAttribute(name);
> >
> >                 if (_global == null)
> >                 {
> >                     _global = createGlobal(context);
> >
> >                     servletContext.setAttribute(name, _global);
> >                 }
> >             }
> >         }
> >
> > H
> >
> >
> > On Sat, 12 Mar 2005 15:24:41 +0800, Raymond <pp...@hotmail.com> wrote:
> > > Hi Tapestry Users,
> > >
> > > There's a strange bug happening with our production Tapestry app (it never
> > > happened in the testing environment).
> > >
> > > The log file of the app shows that the Global object was created twice
> > > (actually the "protected engine.createGlobal(cycle)" method was called
> > > twice, sometimes even called many times) when the app was initializing. The
> > > extra Global object was found to die after 10 hours (by seeing the log
> > > statement in the Global object's finalize() method). And the webapp
> > > continues to run normally. But some internal states were messed up because
> > > we use the global object's private fields to store many application states
> > > and datetime value for various periodic jobs.
> > >
> > > Our production environment is quite busy and whenever the app is undeployed
> > > and redeployed for a few minutes we could see in the Tomcat log many failed
> > > requests. So I suspect perhaps the problem was the webapp received several
> > > concurrent requests before it fully initialized itself when the app was
> > > creating the Engine object. So createGlobal might be called twice and the 2
> > > global objects may be used by different threads. A global object died when
> > > no more thread was referencing it.
> > >
> > > We are using Tomcat 5.028 with jdk 1.4.2_06 on a qutie slow machine.
> > >
> > > Has anyone experienced similar problem? Does it mean that the createGlobal
> > > method is not thread-safe? Any solution?
> > >
> > > Thanks very much for help.
> > > Raymond
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> > > For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> > >
> > >
> >
>

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: strange bug: global created twice

Posted by Hanson Char <ha...@gmail.com>.
The logic within the synchronzied block can be further simplified into:

        synchronized(LOCK_GLOBAL) {
            if (_global == null)
            {
                String name = GLOBAL_NAME + ":" + servletName;
                _global = createGlobal(context);
                servletContext.setAttribute(name, _global);
            }
        }

H

On Sat, 12 Mar 2005 21:33:24 +1100, Hanson Char <ha...@gmail.com> wrote:
> From a cursory look at the AbstractEngine.java of Tapestry 3.0.2, it
> does seem the initialization of _global is not thread-safe.  A quick
> fix would be to add a lock and synchronize on it.
> 
> Example:
> 
>     // add a lock monitor for _global
>     private final int[] LOCK_GLOBAL = {};
> 
> ...
>         synchronized(LOCK_GLOBAL) {
>             if (_global == null)
>             {
>                 String name = GLOBAL_NAME + ":" + servletName;
> 
>                 _global = servletContext.getAttribute(name);
> 
>                 if (_global == null)
>                 {
>                     _global = createGlobal(context);
> 
>                     servletContext.setAttribute(name, _global);
>                 }
>             }
>         }
> 
> H
> 
> 
> On Sat, 12 Mar 2005 15:24:41 +0800, Raymond <pp...@hotmail.com> wrote:
> > Hi Tapestry Users,
> >
> > There's a strange bug happening with our production Tapestry app (it never
> > happened in the testing environment).
> >
> > The log file of the app shows that the Global object was created twice
> > (actually the "protected engine.createGlobal(cycle)" method was called
> > twice, sometimes even called many times) when the app was initializing. The
> > extra Global object was found to die after 10 hours (by seeing the log
> > statement in the Global object's finalize() method). And the webapp
> > continues to run normally. But some internal states were messed up because
> > we use the global object's private fields to store many application states
> > and datetime value for various periodic jobs.
> >
> > Our production environment is quite busy and whenever the app is undeployed
> > and redeployed for a few minutes we could see in the Tomcat log many failed
> > requests. So I suspect perhaps the problem was the webapp received several
> > concurrent requests before it fully initialized itself when the app was
> > creating the Engine object. So createGlobal might be called twice and the 2
> > global objects may be used by different threads. A global object died when
> > no more thread was referencing it.
> >
> > We are using Tomcat 5.028 with jdk 1.4.2_06 on a qutie slow machine.
> >
> > Has anyone experienced similar problem? Does it mean that the createGlobal
> > method is not thread-safe? Any solution?
> >
> > Thanks very much for help.
> > Raymond
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> >
> >
>

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org


Re: strange bug: global created twice

Posted by Hanson Char <ha...@gmail.com>.
>From a cursory look at the AbstractEngine.java of Tapestry 3.0.2, it
does seem the initialization of _global is not thread-safe.  A quick
fix would be to add a lock and synchronize on it.

Example:

    // add a lock monitor for _global
    private final int[] LOCK_GLOBAL = {};

...
        synchronized(LOCK_GLOBAL) {
            if (_global == null)
            {
                String name = GLOBAL_NAME + ":" + servletName;

                _global = servletContext.getAttribute(name);

                if (_global == null)
                {
                    _global = createGlobal(context);

                    servletContext.setAttribute(name, _global);
                }
            }
        }

H


On Sat, 12 Mar 2005 15:24:41 +0800, Raymond <pp...@hotmail.com> wrote:
> Hi Tapestry Users,
> 
> There's a strange bug happening with our production Tapestry app (it never
> happened in the testing environment).
> 
> The log file of the app shows that the Global object was created twice
> (actually the "protected engine.createGlobal(cycle)" method was called
> twice, sometimes even called many times) when the app was initializing. The
> extra Global object was found to die after 10 hours (by seeing the log
> statement in the Global object's finalize() method). And the webapp
> continues to run normally. But some internal states were messed up because
> we use the global object's private fields to store many application states
> and datetime value for various periodic jobs.
> 
> Our production environment is quite busy and whenever the app is undeployed
> and redeployed for a few minutes we could see in the Tomcat log many failed
> requests. So I suspect perhaps the problem was the webapp received several
> concurrent requests before it fully initialized itself when the app was
> creating the Engine object. So createGlobal might be called twice and the 2
> global objects may be used by different threads. A global object died when
> no more thread was referencing it.
> 
> We are using Tomcat 5.028 with jdk 1.4.2_06 on a qutie slow machine.
> 
> Has anyone experienced similar problem? Does it mean that the createGlobal
> method is not thread-safe? Any solution?
> 
> Thanks very much for help.
> Raymond
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> 
>

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-user-help@jakarta.apache.org