Bug #7619 | Memory leak when mysql_init() and mysql_real_connect() [MYSQL C API's] used | ||
---|---|---|---|
Submitted: | 2 Jan 2005 16:37 | Modified: | 16 May 2006 7:26 |
Reporter: | TestUser U | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | MySQL Server: C API (client library) | Severity: | S3 (Non-critical) |
Version: | 3.23.58, 4.1.8, 5.0.2-alpha | OS: | Linux (Linux 9.0) |
Assigned to: | Alexander Barkov | CPU Architecture: | Any |
[2 Jan 2005 16:37]
TestUser U
[8 Jan 2005 21:36]
Ivgeni Segal
Found the same problem by using valgrind. In our case we ran libmysql through php. The cs_info_table is never freed under charset.c
[21 Jun 2005 9:43]
Barry Zubel
Verified on Debian, with 4.0.24 client libs and server.
[24 Jul 2005 12:21]
Sela Lerer
Got the same problem on WIN XP without using the mysql_init() allocation. The code: #include <stdio.h> #include <windows.h> #include <mysql.h> #define CONNECTION_COUNT 4 void printMemStat(void) { MEMORYSTATUS memStat; GlobalMemoryStatus(&memStat); printf("FREE MEMORY %uK/%uK (%3.2lf%%)\n",memStat.dwAvailVirtual/1024,memStat.dwTotalVirtual/1024 ,((double)memStat.dwAvailVirtual/(double)memStat.dwTotalVirtual)*100); printf("USED MEMORY %uK\n",(memStat.dwTotalVirtual-memStat.dwAvailVirtual)/1024); } int main(int argc, char *argv[]) { if(mysql_thread_safe()) { static MYSQL conn[CONNECTION_COUNT]; int connected[CONNECTION_COUNT]={0}; int i=0; my_init(); printf("START: "); printMemStat(); for(i=0;i<CONNECTION_COUNT;i++) { printf("Before connection %d...\n",i); printMemStat(); getchar(); if(NULL!=mysql_real_connect(&conn[i],"localhost","root","sela90","kevin",3306 ,NULL,CLIENT_MULTI_STATEMENTS)) { connected[i]=1; printf("Connected %d successfully.\n",i); printMemStat(); } else { fprintf(stderr,"mysql_real_connect() %d error: %s\n",i,mysql_error(&conn[i])); } } for(i=0;i<CONNECTION_COUNT;i++) { if(connected[i]) { printf("Before closing connection %d...\n",i); printMemStat(); getchar(); mysql_close(&conn[i]); printf("Closed connection %d.\n",i); printMemStat(); } } printf("Before mysql_thread_end()....\n"); getchar(); mysql_thread_end(); printf("EXIT: "); printMemStat(); getchar(); } else { fprintf(stderr,"MySQL client library is not thread safe. Exiting.\n"); getchar(); } return 0; }
[23 Sep 2005 7:27]
[ name withheld ]
I have similar memory leaks on Debian (Sarge) with 4.1.11 mysql server and client. The problem even appears when no connection is established. This is the minimal C source: #include <mysql/mysql.h> int main() { MYSQL* mysql = mysql_init(0); mysql_close(mysql); return 0; } and valgrind --leak-check=full --show-reachable=yes ==21928== Memcheck, a memory error detector for x86-linux. ==21928== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al. ==21928== Using valgrind-2.4.0, a program supervision framework for x86-linux. ==21928== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al. ==21928== For more details, rerun with: -v ==21928== ==21928== ==21928== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 29 from 1) ==21928== malloc/free: in use at exit: 30 bytes in 2 blocks. ==21928== malloc/free: 61 allocs, 59 frees, 6952 bytes allocated. ==21928== For counts of detected errors, rerun with: -v ==21928== searching for pointers to 2 not-freed blocks. ==21928== checked 1093632 bytes. ==21928== ==21928== 4 bytes in 1 blocks are definitely lost in loss record 1 of 2 ==21928== at 0x1B90459D: malloc (vg_replace_malloc.c:130) ==21928== by 0x1B8E9346: (within /lib/ld-2.3.2.so) ==21928== by 0x1B8EA5A5: _dl_map_object (in /lib/ld-2.3.2.so) ==21928== by 0x1B8EEB08: (within /lib/ld-2.3.2.so) ==21928== by 0x1B8F0015: _dl_catch_error (in /lib/ld-2.3.2.so) ==21928== by 0x1B8EF580: _dl_map_object_deps (in /lib/ld-2.3.2.so) ==21928== by 0x1BB2C100: (within /lib/tls/libc-2.3.2.so) ==21928== by 0x1B8F0015: _dl_catch_error (in /lib/ld-2.3.2.so) ==21928== by 0x1BB2BED5: _dl_open (in /lib/tls/libc-2.3.2.so) ==21928== by 0x1BB2DD62: (within /lib/tls/libc-2.3.2.so) ==21928== by 0x1B8F0015: _dl_catch_error (in /lib/ld-2.3.2.so) ==21928== by 0x1BB2DBE7: __libc_dlopen_mode (in /lib/tls/libc-2.3.2.so) ==21928== ==21928== ==21928== 26 bytes in 1 blocks are definitely lost in loss record 2 of 2 ==21928== at 0x1B90459D: malloc (vg_replace_malloc.c:130) ==21928== by 0x1BD74F81: ??? ==21928== by 0x1BD74E4A: ??? ==21928== by 0x1BD46FC1: ??? ==21928== by 0x1BD3E128: ??? ==21928== by 0x1BCDF995: ??? ==21928== by 0x1BCDFB0A: ??? ==21928== by 0x1BCDF1BE: ??? ==21928== by 0x1BCDF46F: ??? ==21928== by 0x1BB11208: getservbyname_r (in /lib/tls/libc-2.3.2.so) ==21928== by 0x1BB11077: getservbyname (in /lib/tls/libc-2.3.2.so) ==21928== by 0x1B92782F: mysql_server_init (in /usr/lib/libmysqlclient.so.14.0.0) ==21928== ==21928== LEAK SUMMARY: ==21928== definitely lost: 30 bytes in 2 blocks. ==21928== possibly lost: 0 bytes in 0 blocks. ==21928== still reachable: 0 bytes in 0 blocks. ==21928== suppressed: 0 bytes in 0 blocks. I haven't digged deeper so far. Tomasz Buchert thinred@o2.pl
[25 Jan 2006 1:52]
Marcus Grando
I have same problem in FreeBSD / MySQL 4.1 Client... Any news about that? Without that i can't running daemon with threads... ==72446== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) ==72446== malloc/free: in use at exit: 56569 bytes in 517 blocks. ==72446== malloc/free: 1484 allocs, 967 frees, 767143 bytes allocated. ==72446== For counts of detected errors, rerun with: -v ==72446== searching for pointers to 517 not-freed blocks. ==72446== checked 4142980 bytes. ==72446== ==72446== 49 bytes in 5 blocks are definitely lost in loss record 2 of 17 ==72446== at 0x3C032183: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck.so) ==72446== by 0x3C37C823: strdup (in /lib/libc.so.6) ==72446== by 0x3C376B1E: _nsyylex (in /lib/libc.so.6) ==72446== by 0x3C375FA4: _nsyyparse (in /lib/libc.so.6) ==72446== by 0x3C379A65: _nsdispatch (in /lib/libc.so.6) ==72446== by 0x3C378E87: (within /lib/libc.so.6) ==72446== by 0x3C379223: gethostbyname (in /lib/libc.so.6) ==72446== by 0x3C08154B: my_gethostbyname_r (in /usr/local/lib/mysql/libmysqlclient_r.so.14) ==72446== by 0x3C08BE8B: mysql_real_connect (in /usr/local/lib/mysql/libmysqlclient_r.so.14) ==72446== by 0x804A3BF: my_dbconnect (mysql.c:14) ==72446== by 0x804AC88: main_thread (blogmail.c:58) ==72446== by 0x3C03A692: (within /usr/local/lib/valgrind/libpthread.so.2) ==72446== ==72446== ==72446== 104 bytes in 2 blocks are definitely lost in loss record 3 of 17 ==72446== at 0x3C03294B: calloc (in /usr/local/lib/valgrind/vgpreload_memcheck.so) ==72446== by 0x3C078E80: my_thread_init (in /usr/local/lib/mysql/libmysqlclient_r.so.14) ==72446== by 0x3C078FC8: my_thread_global_init (in /usr/local/lib/mysql/libmysqlclient_r.so.14) ==72446== by 0x3C074AF6: my_init (in /usr/local/lib/mysql/libmysqlclient_r.so.14) ==72446== by 0x3C06EE25: mysql_server_init (in /usr/local/lib/mysql/libmysqlclient_r.so.14) ==72446== by 0x3C08AD4F: mysql_init (in /usr/local/lib/mysql/libmysqlclient_r.so.14) ==72446== by 0x804A381: my_dbconnect (mysql.c:8) ==72446== by 0x804AC88: main_thread (blogmail.c:58) ==72446== by 0x3C03A692: (within /usr/local/lib/valgrind/libpthread.so.2) ==72446== by 0xB8010B4F: (within /usr/local/lib/valgrind/stage2)
[3 Mar 2006 16:39]
Nathanael Noblet
Just a confirmation that the bug exists in 5.0.18 for Fedora Core 5 (test3). I have a problem because we have virtual users that are using a pam module pam_mysql. With this memory leak after a few days 2GB of swap is consumed. Is this being worked on?
[12 May 2006 6:07]
Braden Temme
I am getting this same bug. I recommend upgrading this bug report to 'S2 (Serious)'.
[16 May 2006 7:26]
Alexander Barkov
This is not a bug. Hartmut is right that this is only one time "memory leak", it is not something which is accumulated through calling mysql_connect..mysql_close in a loop. Thus you can just ignore those 6K of memory not freed. It is not harmfull. This program proves that: #include <stdio.h> #include <mysql.h> static int one_time() { MYSQL *connection,mysql; mysql_init(&mysql); connection=mysql_real_connect(&mysql,"localhost","root",NULL,"test",0,0,0); if( connection == NULL ) { printf("%s", mysql_error(&mysql)); return 1; } mysql_close(connection); return 0; } int main(void) { int i; for (i= 0; i < 100; i++) { one_time(); } return; } No mater the counter is 1 or 100, vagrind reports the same amount of memory not freed. Note, the same happens with any program using functions like gethostbyname(). Functions of these family allocate some in-memory cache to make subsequent calls faster. So, vagrind reports some not-freed memory at the end of the program. But this is not really *memory leak*. libmysqlclient does the same: character set information in not freed by mysql_clone() *intentionally*, to make subsequent mysql_connect() or mysql_init() much faster. which is important for things like PHP, or for pam modules. I agree that it probably would be nice to have a special function to free all memory allocated by libmysqlclient at a desired moment of time. Something like mysql_free_library(). Feel free to post a feature request for that. As for PAM module eating 2GB memory, most likely it is the one who is leaking memory itself. I suggest either report its authors or try to trace it somehow.
[16 May 2006 8:00]
Sergei Golubchik
It is an expected and documented behaviour. See http://dev.mysql.com/doc/refman/5.0/en/c-api-function-overview.html " Application programs should use this general outline for interacting with MySQL: 1. Initialize the MySQL library by calling mysql_library_init(). The library can be either the mysqlclient C client library or the mysqld embedded server library, depending on whether the application was linked with the -libmysqlclient or -libmysqld flag. 2. Initialize a connection handler by calling mysql_init() and connect to the server by calling mysql_real_connect(). 3. Issue SQL statements and process their results. (The following discussion provides more information about how to do this.) 4. Close the connection to the MySQL server by calling mysql_close(). 5. End use of the MySQL library by calling mysql_library_end(). The purpose of calling mysql_library_init() and mysql_library_end() is to provide proper initialization and finalization of the MySQL library. For applications that are linked with the client library, they provide improved memory management. If you don't call mysql_library_end(), a block of memory remains allocated. (This does not increase the amount of memory used by the application, but some memory leak detectors will complain about it.) For applications that are linked with the embedded server, these calls start and stop the server."
[16 May 2006 9:20]
Alexander Barkov
Sergey, thanks for your comment! I didn't know about mysql_library_end(). This is exactly what I mean here: > I agree that it probably would be nice to have a special function to free all > memory allocated by libmysqlclient at a desired moment of time. > Something like mysql_free_library(). Feel free to post a feature request for > that. so there is no a need for a feature request. The function already exists.