[JAVA-595] With redeploy web app created a ThreadLocal but failed to remove it when the web application was stopped Created: 03/Jul/12  Updated: 22/Nov/13  Resolved: 10/Mar/13

Status: Closed
Project: Java Driver
Component/s: Connection Management
Affects Version/s: 2.8.0
Fix Version/s: 2.11.0

Type: Bug Priority: Major - P3
Reporter: Gert Vaartjes Assignee: Jeffrey Yemin
Resolution: Done Votes: 8
Labels: mongodb
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

windows/linux (Ubuntu 12.04),sun java 1.7, tomcat 7


Attachments: Zip Archive MongoReporter.v2.zip     Zip Archive MongoReporter.zip    
Issue Links:
Duplicate
is duplicated by JAVA-732 Thread Locals not being freed in thre... Closed
Related

 Description   

With a redeploy of the webapplication to tomcat: This error message appears:
SEVERE: The web application [/MongoReporter] created a ThreadLocal with key of type [com.mongodb.DBTCPConnector$1] (value [com.mongodb.DBTCPConnector$1@6c747b55]) and a value of type [com.mongodb.DBTCPConnector.MyPort] (value [com.mongodb.DBTCPConnector$MyPort@534d4113]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

uploaded simple webapp to demonstrate



 Comments   
Comment by Tourendal [X] [ 22/Nov/13 ]

I am not sure. Thanks for pointing this out. I will check the code again.

Comment by Jeffrey Yemin [ 22/Nov/13 ]

Are you absolutely sure you are closing any and all MongoClient instances? If you don't class MongoClient#close, the threads won't die.

Comment by Tourendal [X] [ 22/Nov/13 ]

I still see this error with mongo-java-driver 2.11.3 on Tomcat 6.0.37:

SEVERE: The web application [/xyz] appears to have started a thread named [MongoCleaner1574466115] but has failed to stop it. This is very likely to create a memory leak.

Am I missing something? It happens without a redeploy but during normal operations of Tomcat. Is this another bug?

Comment by auto [ 12/Mar/13 ]

Author:

{u'date': u'2013-03-12T14:54:49Z', u'name': u'Jeff Yemin', u'email': u'jeff.yemin@10gen.com'}

Message: JAVA-595: Cleaned up the code a bit with helper methods and variable renames.
Branch: master
https://github.com/mongodb/mongo-java-driver/commit/9c268970fe398f8bc13ba923a49b7b0ef0bbea4e

Comment by auto [ 10/Mar/13 ]

Author:

{u'date': u'2013-03-10T02:29:02Z', u'name': u'Jeff Yemin', u'email': u'jeff.yemin@10gen.com'}

Message: JAVA-595: Removed annoying ThreadLocal that keeps track of the pinned request port. Now there is only a thread local set during a requestStart/requestDone block, but never outside it.
Branch: master
https://github.com/mongodb/mongo-java-driver/commit/0e1dacae87867c36b96ab5e7703f12ffc4954a16

Comment by Jeffrey Yemin [ 10/Mar/13 ]

Fixing this by only keeping a thread local set while a request is active. So if an application either doesn't use DB.requestStart/DB.requestDone, or else always ensures a matching call to DB.requestDone for every call to DB.requestStart (like in a finally block), there should no longer be any dangling thread locals.

// no thread local set
db.requestStart();  // thread local set
try {
   // do stuff
} finally {
  db.requestDone(); // thread local removed
}
// no thread local set

Comment by Olivier Allouch [ 19/Feb/13 ]

Setting the ThreadLocal reference to null is often enough.

Comment by Ignacio [ 23/Nov/12 ]

I think that the problem with the current implementation is the following:

by calling Mongo.close() -> then -> DBTCPConnector.close()
this line is executed:

// below this will remove the myport for this thread only
// client using thread pool in web framework may need to call close() from all threads
_myPort.remove();

It's clear that only the current thread value is removed, but all threads used are not affected.

ThreadLocal Javadoc:

public void remove()
Removes the current thread's value for this thread-local variable. If this thread-local variable is subsequently read by the current thread, its value will be reinitialized by invoking its initialValue() method, unless its value is set by the current thread in the interim. This may result in multiple invocations of the initialValue method in the current thread.

so, calling .close is not enough.

Comment by Jeffrey Yemin [ 03/Jul/12 ]

One other thing I should point out. Though this is a memory leak, it's a very small one. So long as you are calling com.mongodb.Mongo#close when the context is destroyed (which I see you are in your test program, at least), all the underlying Socket instances will be closed.

Comment by Gert Vaartjes [ 03/Jul/12 ]

Ok sounds interesting

Comment by Jeffrey Yemin [ 03/Jul/12 ]

Actually, with a bit of internal refactoring we can fix this without an API change.

Comment by Gert Vaartjes [ 03/Jul/12 ]

New configuration for deploying to tomcat with maven

Steps to reproduce issue are:

1) have tomcat-manager app installed for deploying apps to Tomcat

  • edit %TOMCAT_INSTALL%/conf/tomcat-users.xml.
  • Add inside the tomcat-users tags

    <role rolename="manager-gui"/>
    <role rolename="tomcat"/>
    <user username="tomcat" password="tompoes" roles="manager-gui,tomcat"/>

    2) edit Mavens settings.xml in .m2 folder. add inside the <servers> tag

    <server>
    		<id>highsoft-test</id>
    		<username>tomcat</username>			
    		<password>tompoes</password>
    	</server>	

    3) deploy app: with mvn tomcat:deploy
    4) request site : http://localhist:8080/MongoReporter/report
    5) redeploy app with mvn tomcat:redeploy
    ! Error message appears !

Comment by Scott Hernandez (Inactive) [ 03/Jul/12 ]

Given this zip what are the steps to reproduce? How did you deploy the webapp? How did you redeploy? Are you using maven for this or the web console?

Comment by Jeffrey Yemin [ 03/Jul/12 ]

We could fix this with an API change, something like this in com.mongodb.Mongo:

public void clearThreadLocals()

Applications that cared could call this method at the end of every request. It's not an elegant solution, but I'm not sure we can do much better without a bigger API change. The methods com.mongodb.DB#requestStart and com.mongodb.DB#requestDone rely on this ThreadLocal, and there is no other way besides a ThreadLocal to implement the semantics of those operations.

Generated at Thu Feb 08 08:52:39 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.