[MDEV-10455] libmariadbclient18 + MySQL-python leaks memory on failed connections Created: 2016-07-27 Updated: 2016-08-12 Resolved: 2016-08-12 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Scripts & Clients |
| Affects Version/s: | 10.0, 10.1 |
| Fix Version/s: | 10.1.17, 10.0.27 |
| Type: | Bug | Priority: | Major |
| Reporter: | Andrew Garner | Assignee: | Oleksandr Byelkin |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | None | ||
| Environment: |
Debian 8 |
||
| Issue Links: |
|
||||||||||||
| Description |
|
When MySQLdb (python-mysqldb) uses the MariaDB libmysqlclient.so.18 libraries, it seems to leak memory with each failed connection. A simple contrived loop (w/ mariadb stopped, generating client 2003 errors) leads to a few GB RSS for the associated python process in a few seconds when using the MariaDB 10.1 client packages:
The output of running this is as follows:
Removing libmariadbclient18 and reverting to the libmysqlclient18 provided by either MySQL 5.5 (5.5.50-0+deb8u1) (debian/jessie main) or MySQL 5.6 (5.6.30-1~bpo8+1 from jessie-backports), the memory leak goes away and memory use stays constant over time. I see MySQL-python does not call mysql_close() on a failed connection which seems to resolve this behavior with MariaDB - so perhaps this is an incorrect API usage bug. However the MariaDB behavior does seem to differ from the MySQL (5.5.50, 5.6.30) behavior, so I am opening this issue. |
| Comments |
| Comment by Elena Stepanova [ 2016-07-29 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thanks for the report. It started happening with the following revision in 10.0.5:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2016-08-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
pure C test do not leak memory, so probably python uses some preparation and then do not clean... | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2016-08-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
and BTW I did not call mysql_close()... but also did not init a new connection... actually without mysql_close() it can just leak allocated MYSQL object (who knows what that python id doing and how call mysql_init())... | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2016-08-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I do not see obvious flows in client connection attributes initialization. So it is probably how python uses the clientlibrary. Which is a bit difficult for me to test because I can't repeat it with build libraries (it looks like python uses something different then LD_LIBRARY_PATH and LD_PRELOAD to get the library). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2016-08-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
BTW that libmariadbclient18 is libmysqld supplied with server or connectors-C? Is it debian? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Andrew Garner [ 2016-08-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
This libmariadbclient18 is libmysqld supplied I believe - not the connector/C variant. I see Debian ships what I think is an older version of the MariaDB Connector/C (libmariadb2 -> v2.0.0) and this does not exhibit the same "leaking" behavior (using the naive python script above):
Simply removing LD_PRELOAD shows different behavior:
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Andrew Garner [ 2016-08-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
FWIW, the following "pure C" program exhibits the same behavior. This should be similar to what MySQL-python does from reading the code. As I understand it from my reading of the source, MySQL-python allocates a struct with a "MYSQL connection" member, calls mysql_init a series of mysql_option calls and mysql_real_connect. If mysql_real_connect fails, mysql_errno / mysql_error are called, but mysql_close is not.
Here's some output from my environment - still using Debian8 w/ libmariadbclient18 + libmariadbclient-dev from 10.1.16~maria-1~jessie packages.
I also ran valgrind output here, if it's helpful at all and this does seem to indicate a leak:
And again with libmysqlclient18_5.5.50-0+deb8u1_amd64.deb
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Andrew Garner [ 2016-08-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Also, as I follow my curiosity, this issue also seems to affect other libmysqlclient based connectors which seem to assume they either need not or should not call mysql_close after mysql_real_connect fails. For another example, see this trivial perl program using DBD-mysql.
valgrind shows a similar leak report here - which goes away with either MariaDB Connector/C or the MySQL 5.5 / 5.6 libmysqlclient libraries. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2016-08-10 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thank you, now it is repeatable. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2016-08-11 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
It was not implemented CLIENT_REMEMBER_OPTIONS. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2016-08-11 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
support added, problem fixed, now trying to put the test into regression test test suite (if possible)... | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2016-08-11 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
revision-id: 66ac894c40ad089175aaf6d4922f7250c23b9b3d (mariadb-10.0.26-17-g66ac894)
Support of CLIENT_REMEMBER_OPTIONS and freeing options added. — | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Oleksandr Byelkin [ 2016-08-12 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Got OK from Georg. |