You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Patric Rufflar <Pa...@rufflar.com> on 2012/01/26 15:33:00 UTC

ThreadLocals, context listeners and classloader leaks

Hi,

I've got some questions regards the use of ThreadLocals in context 
listeners:
(This is a general question, but I tested this with tomcat 6.0.32 only)

1. It's unspecified in the servlet spec 2.5 if a servlet context 
listener is allowed to take the use of ThreadLocals during 
contextInitialized().
    Is this (also) allowed in tomcat?


    If the answer of this question is "yes":

2. Tomcat invokes the contextInitialized() method with the main thread.
    At some later time, the main thread (most probably) spawns some more 
threads (e.g. the http connector/acceptor threads).
    Because ThreadLocals are inherited from its parent threads, the 
thread local value references of each ThreadLocal object
    are copied to the child threads.

    With the result that even if the reference to the original 
ThreadLocal instance is removed (for example during contextDestroyed(),
    the inherited ThreadLocals are still there and reference to the 
original values - and will most probably remain in the spawned threads 
forever.
    (I am aware that tomcat's leak-prevention system / 
WebClassLoader.clearThreadLocalMap() may remove them,
    but I can neither rely on that at customer installations nor 
consider this as a good style)

    a) Is the main thread usage for context initializers intended? Is 
this configurable?
    b) What's the best way to deal with this situation (especially if 
the avoidance of ThreadLocals in context initializers is not an option)?
    c) Wouldn't it be better to create an individual thread for (each) 
context initializer to avoid these kind of problems?


Thanks you very much in advance.

- Patric
















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


Re: ThreadLocals, context listeners and classloader leaks

Posted by Pid <pi...@pidster.com>.
On 26/01/2012 17:48, Caldarale, Charles R wrote:
>> From: Pid [mailto:pid@pidster.com] 
>> Subject: Re: ThreadLocals, context listeners and classloader leaks
> 
>> Imagine the fiendishly clever and machiavellian applications 
>> we'd have to debug if you did that...
> 
> Job security.

ROFL.


p



-- 

[key:62590808]


RE: ThreadLocals, context listeners and classloader leaks

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Pid [mailto:pid@pidster.com] 
> Subject: Re: ThreadLocals, context listeners and classloader leaks

> Imagine the fiendishly clever and machiavellian applications 
> we'd have to debug if you did that...

Job security.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


Re: ThreadLocals, context listeners and classloader leaks

Posted by Pid <pi...@pidster.com>.
On 26/01/2012 17:30, Caldarale, Charles R wrote:
>> From: Jess Holle [mailto:jessh@ptc.com] 
>> Subject: Re: ThreadLocals, context listeners and classloader leaks
> 
>> That said, there could and arguably should be another choice:
> 
> I'll suggest something more radical: define a class such as ScopeLocal where values are added to and removed from threads as they enter and leave a scope boundary.  For servlet engine purposes, typical scopes would be webapp, session, request, servlet, etc.  Doing it properly (and efficiently) might well require JVM intervention, but it would certainly help in providing a useful mechanism for app writers.  Obviously, there's lots of definition work needed here...

Imagine the fiendishly clever and machiavellian applications we'd have
to debug if you did that...


p


> THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.
> 


-- 

[key:62590808]


RE: ThreadLocals, context listeners and classloader leaks

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Jess Holle [mailto:jessh@ptc.com] 
> Subject: Re: ThreadLocals, context listeners and classloader leaks

> That said, there could and arguably should be another choice:

I'll suggest something more radical: define a class such as ScopeLocal where values are added to and removed from threads as they enter and leave a scope boundary.  For servlet engine purposes, typical scopes would be webapp, session, request, servlet, etc.  Doing it properly (and efficiently) might well require JVM intervention, but it would certainly help in providing a useful mechanism for app writers.  Obviously, there's lots of definition work needed here...

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


Re: ThreadLocals, context listeners and classloader leaks

Posted by Rainer Jung <ra...@kippdata.de>.
On 26.01.2012 18:00, Jess Holle wrote:
> On 1/26/2012 10:38 AM, Mark Thomas wrote:
>> OK. ThreadLocals have no place in a web application. Period. If a
>> programmer insists on using them, then it is their responsibility to
>> clean up the mess they leave behind.
>>
>> Tomcat's memory leak detection and prevention code goes some way to
>> clearing up things like this but it is never going to cover every case.
>>
>> Mark
> Or put another way, you have a choice:
>
> 1. Use ThreadLocals the way you'd have assumed you could, but don't
> expect to ever restart your web app without leaking tons of memory.
> 2. Use ThreadLocals, but be sure you religiously clean up after
> yourself by the time your web app is fully shut down.
> 3. Don't use ThreadLocals.
>
> If you use someone else's library that uses ThreadLocals then you'll
> probably end up in forced into A.
>
> That said, there could and arguably should be another choice:
>
> 4. Select a special mode in a servlet engine that shuts down all
> threads that have ever serviced requests for a given web app when it
> is shutdown (and code your web app to shutdown any threads it
> creates, obviously!), e.g. after they complete servicing any request
> in progress. [It could just replace all request threads with new
> ones after the requests currently in progress complete.]
>
> That's assuming the servlet engine is nice enough to provide such a
> mode. If it did, however, I believe that would resolve any ThreadLocal
> issues without one having to avoid using a perfect natural and useful
> Java language feature. I'd argue all servlet engines should really
> provide this feature for just this reason. That said, I can live with A.

Renewing threads is what was implemented some time ago in Tomcat's 
ThreadLocal leak prevention:

http://tomcat.apache.org/tomcat-7.0-doc/config/listeners.html#ThreadLocal_Leak_Prevention_Listener_-_org.apache.catalina.core.ThreadLocalLeakPreventionListener

Regards,

Rainer

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


Re: ThreadLocals, context listeners and classloader leaks

Posted by Jess Holle <je...@ptc.com>.
On 1/26/2012 10:38 AM, Mark Thomas wrote:
> OK. ThreadLocals have no place in a web application. Period. If a
> programmer insists on using them, then it is their responsibility to
> clean up the mess they leave behind.
>
> Tomcat's memory leak detection and prevention code goes some way to
> clearing up things like this but it is never going to cover every case.
>
> Mark
Or put another way, you have a choice:

 1. Use ThreadLocals the way you'd have assumed you could, but don't
    expect to ever restart your web app without leaking tons of memory.
 2. Use ThreadLocals, but be sure you religiously clean up after
    yourself by the time your web app is fully shut down.
 3. Don't use ThreadLocals.

If you use someone else's library that uses ThreadLocals then you'll 
probably end up in forced into A.

That said, there could and arguably should be another choice:

 4. Select a special mode in a servlet engine that shuts down all
    threads that have ever serviced requests for a given web app when it
    is shutdown (and code your web app to shutdown any threads it
    creates, obviously!), e.g. after they complete servicing any request
    in progress.  [It could just replace all request threads with new
    ones after the requests currently in progress complete.]

That's assuming the servlet engine is nice enough to provide such a 
mode.  If it did, however, I believe that would resolve any ThreadLocal 
issues without one having to avoid using a perfect natural and useful 
Java language feature.  I'd argue all servlet engines should really 
provide this feature for just this reason.  That said, I can live with A.

--
Jess Holle


Re: ThreadLocals, context listeners and classloader leaks

Posted by Mark Thomas <ma...@apache.org>.
On 26/01/2012 15:16, Patric Rufflar wrote:
>> I have no idea what the phrase "take the use of" means; what are you
>> trying to say?
> 
> I'd like to know if there's some statement from the tomcat team if the
> usage of ThreadLocals within contextInitialized() is discouraged or even
> not supported.

OK. ThreadLocals have no place in a web application. Period. If a
programmer insists on using them, then it is their responsibility to
clean up the mess they leave behind.

Tomcat's memory leak detection and prevention code goes some way to
clearing up things like this but it is never going to cover every case.

Mark

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


RE: ThreadLocals, context listeners and classloader leaks

Posted by Patric Rufflar <Pa...@rufflar.com>.
Am 26.01.2012 16:59, schrieb Caldarale, Charles R:
> No; again, a ThreadLocal is _not_ inherited, but an
> InheritableThreadLocal is.  These are different animals.

1. A InheritableThreadLocal is (extends) a ThreadLocal.
2. Surprise: A InheritableThreadLocal is _not_ used for the 
Thread.inheritableThreadLocals field/mechanism when creating a new 
thread
(at least not in oracle jdk 6, see Thread.class source for details) - 
for this, a ThreadLocal.class instance is used, too.

So the statement "we have more than one ThreadLocal which references to 
value A" seems correct to me.

> Why can't they be removed?  (The code to do so is ugly, but readily
> findable with Google.)

I think you mean by traversing all threads and do some reflection 
actions on them?
Please note that I already included feasible workarounds into my 
projects - so for me, this issue is not a show stopper anymore.

But:
The intention of my original mail was to highlight the problem with 
ThreadLocals/Context initializers and to suggest an improvement to 
tomcat to prevent
others from falling into this pit.
Secondly, from an economic perspective such an improvement in tomcat 
would be much cheaper than to include such hacks inside all the projects
all over the world.

> Again, that would fix _one_ stupid programmer trick, out of the
> uncountable number of potential errors.

I am interested in these disadvantages.
What kind of potential errors do you see if an individual thread would 
be used for each context initialization?

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


RE: ThreadLocals, context listeners and classloader leaks

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Patric Rufflar [mailto:Patric@rufflar.com] 
> Subject: RE: ThreadLocals, context listeners and classloader leaks

> 1. contextInitializer() sets value A to the ThreadLocal X 
> in thread main
> 2. childs threads get spawned from main thread, now we have 
> more than one ThreadLocal which references to value A

No; again, a ThreadLocal is _not_ inherited, but an InheritableThreadLocal is.  These are different animals.

> 3. Reference to ThreadLocal X gets dropped, but references 
> to value A still exist - without being able to remove them.

Why can't they be removed?  (The code to do so is ugly, but readily findable with Google.)

> But wouldn't it be much easier for everyone if tomcat would 
> always use a separate thread for each context initializer 

Again, that would fix _one_ stupid programmer trick, out of the uncountable number of potential errors.

Note that Tomcat 7 includes a ThreadLocalLeakPreventionListener, but it is only invoked during undeployment of a <Context> to clean up <Executor> thread pools.  It would certainly be possible to use this logic upon return from an initializer; filing a bugzilla enhancement request would at least allow some discussion by the committers.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


RE: ThreadLocals, context listeners and classloader leaks

Posted by Patric Rufflar <Pa...@rufflar.com>.
> I have no idea what the phrase "take the use of" means; what are you
> trying to say?

I'd like to know if there's some statement from the tomcat team if the 
usage of ThreadLocals within contextInitialized() is discouraged or even 
not supported.

> ??? A ThreadLocal is _not_ inherited from the parent thread, although
> the _value_ of each InheritableThreadLocal is copied to a spawned
> thread.

I meant exactly that.
Consider the situation:
1. contextInitializer() sets value A to the ThreadLocal X in thread 
main
2. childs threads get spawned from main thread, now we have more than 
one ThreadLocal which references to value A
3. Reference to ThreadLocal X gets dropped, but references to value A 
still exist - without being able to remove them.


> Why is it not an option?  Even if your code calls some 3rd-party
> package to do its work, you can clean up the mess created before
> returning from the initializer.
This means that everyone which uses tomcat has to deeply analyze which 
ThreadLocals are created under which circumstances,
and everytime a 3rd party library is added/upgraded/replaced he has to 
do this again.
Beside the risk, that something will be missed...

> Tomcat can't work around every possible programming silliness.

Agreed.
But wouldn't it be much easier for everyone if tomcat would always use 
a separate thread for each context initializer (even if parallel 
initialization is disabled)
than to rely on that "every possible programming silliness" in 
3rd-party code will be fixed?

(BTW, Log4j is one of those buggy libraries - see 
https://issues.apache.org/bugzilla/show_bug.cgi?id=50486 for details)

- Patric



Am 26.01.2012 15:50, schrieb Caldarale, Charles R:
>> From: Patric Rufflar [mailto:Patric@rufflar.com]
>> Subject: ThreadLocals, context listeners and classloader leaks
>
>> It's unspecified in the servlet spec 2.5 if a servlet context
>> listener is allowed to take the use of ThreadLocals during
>> contextInitialized().
>
> I have no idea what the phrase "take the use of" means; what are you
> trying to say?  Any thread can make use of ThreadLocal, but in a
> thread pool environment, it's usually silly to do so, unless you're
> very, very careful.
>
>> Is this (also) allowed in tomcat?
>
> Tomcat makes little effort to prevent stupid programmer tricks.
>
>> Because ThreadLocals are inherited from its parent threads
>
> ??? A ThreadLocal is _not_ inherited from the parent thread, although
> the _value_ of each InheritableThreadLocal is copied to a spawned
> thread.
>
>> the inherited ThreadLocals are still there and reference to the
>> original values - and will most probably remain in the spawned
>> threads forever
>
> Which is an example of why you must be very, very careful in your use
> of ThreadLocal in a pooled environment.
>
>> Is the main thread usage for context initializers intended?
>
> Yes.  In Tomcat 7, you can have parallel initialization, but not in
> Tomcat 6.  Read the docs for <Engine> and <Host>.
>
>> What's the best way to deal with this situation (especially
>> if the avoidance of ThreadLocals in context initializers is
>> not an option)?
>
> Why is it not an option?  Even if your code calls some 3rd-party
> package to do its work, you can clean up the mess created before
> returning from the initializer.
>
>> Wouldn't it be better to create an individual thread for (each)
>> context initializer to avoid these kind of problems?
>
> Tomcat can't work around every possible programming silliness.
>
>  - Chuck
>
>
> THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE
> PROPRIETARY MATERIAL and is thus for use only by the intended
> recipient. If you received this in error, please contact the sender
> and delete the e-mail and its attachments from all computers.


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


RE: ThreadLocals, context listeners and classloader leaks

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Patric Rufflar [mailto:Patric@rufflar.com] 
> Subject: ThreadLocals, context listeners and classloader leaks

> It's unspecified in the servlet spec 2.5 if a servlet context 
> listener is allowed to take the use of ThreadLocals during 
> contextInitialized().

I have no idea what the phrase "take the use of" means; what are you trying to say?  Any thread can make use of ThreadLocal, but in a thread pool environment, it's usually silly to do so, unless you're very, very careful.

> Is this (also) allowed in tomcat?

Tomcat makes little effort to prevent stupid programmer tricks.

> Because ThreadLocals are inherited from its parent threads

??? A ThreadLocal is _not_ inherited from the parent thread, although the _value_ of each InheritableThreadLocal is copied to a spawned thread.

> the inherited ThreadLocals are still there and reference to the 
> original values - and will most probably remain in the spawned 
> threads forever

Which is an example of why you must be very, very careful in your use of ThreadLocal in a pooled environment.

> Is the main thread usage for context initializers intended?

Yes.  In Tomcat 7, you can have parallel initialization, but not in Tomcat 6.  Read the docs for <Engine> and <Host>.

> What's the best way to deal with this situation (especially
> if the avoidance of ThreadLocals in context initializers is
> not an option)?

Why is it not an option?  Even if your code calls some 3rd-party package to do its work, you can clean up the mess created before returning from the initializer.

> Wouldn't it be better to create an individual thread for (each) 
> context initializer to avoid these kind of problems?

Tomcat can't work around every possible programming silliness.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.