Bug #2061 key created by pthread_key_create is never deleted
Submitted: 9 Dec 2003 11:06 Modified: 10 Dec 2003 15:16
Reporter: [ name withheld ] Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S2 (Serious)
Version:4.0.16 OS:Mac OS X (Mac OS X)
Assigned to: Michael Widenius

[9 Dec 2003 11:06] [ name withheld ]
Description:
In my_thread_global_init() in my_thr_init.c, pthread_key_create is used to create a key.
This key is never deleted.
This becomes a problem if libmysql is built into a .so which is loaded and unloaded multiple times. The static variable which tracks whether mysql has been initialized is not maintained between loads of the .so, so each time it is loaded, my_thread_global_init gets called.
After 128 times, the limit for pthread keys in a single application is hit, and the application gets quit by the call to exit(1).

How to repeat:
* build libmysql into a .so which simply calls mysql_init then mysql_close. Then load and unload the library over and over again until the application quits.
* OR just call mysql_init, mysql_close, then try to open 128 different pthread keys (which should be possible). The last one will fail since libmysql opened one and never closed it.

Suggested fix:
1. At the beginning of my_thread_global_end, replace the first three lines (#if defined(USE_TLS) block) with:
pthread_key_delete(THR_KEY_mysys);

2. Add definitions for pthread_key_delete to my_pthread.h

3. Create a new function, called say "mysql_end()" which calls my_end(0). (Applications could call into my_end directly when they are done with mysql, but it should have a mysql_ wrapper).
[9 Dec 2003 11:54] [ name withheld ]
This COULD be related to bugs 1772 and 1069.
This is just a guess, based on the fact that my_thread_global_init makes mutices, and if my_thread_global_end is never called, they could leak memory...
[10 Dec 2003 15:16] Michael Widenius
Thank you for your bug report. This issue has been committed to our
source repository of that product and will be incorporated into the
next release.

If necessary, you can access the source repository and build the latest
available version, including the bugfix, yourself. More information 
about accessing the source trees is available at
    http://www.mysql.com/doc/en/Installing_source_tree.html

Additional info:

I changed the code to use pthread_key_delete() as this makes the code a bit more clear;  This should not have any notable effects on other platforms as the key should normally be cleared by the thread library (becasue of the free argument to pthread_key_create())

There is no need for a mysql_end() function.  The function mysql_server_end() already calls my_end().
[11 Dec 2003 13:19] [ name withheld ]
What if the program is a client, rather than a server?
Then it has not called mysql_server_init(), and probably should not call mysql_server_end().
Hence the suggestion for a mysql_end() function.