ThreadLocals, context listeners and classloader leaks

2012-01-26 Thread Patric Rufflar

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-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: ThreadLocals, context listeners and classloader leaks

2012-01-26 Thread Patric Rufflar

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:pat...@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-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org



RE: ThreadLocals, context listeners and classloader leaks

2012-01-26 Thread Patric Rufflar

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-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org