Bug #92112 Memory leak when client APIs called after mysql_close
Submitted: 21 Aug 2018 20:14 Modified: 5 Feb 2019 14:55
Reporter: Manuel Ung Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: C API (client library) Severity:S3 (Non-critical)
Version:8.0.11, 8.0.12, 5.7.23 OS:Any
Assigned to: CPU Architecture:Any

[21 Aug 2018 20:14] Manuel Ung
Description:
The client api leaks memory when the application calls mysql_next_result after mysql_close is called on the MYSQL handle. This is because MYSQL_TRACE_STAGE will allocate memory for the 'extensions' field:

#define TRACE_DATA(M) (MYSQL_EXTENSION_PTR(M)->trace_data)
#define MYSQL_EXTENSION_PTR(H)              \
  ((MYSQL_EXTENSION *)((H)->extension       \
                           ? (H)->extension \
                           : ((H)->extension = mysql_extension_init(H))))

However, the application will likely receive an out of sync error, and will not call mysql_close again. The memory allocated for extension is then leaked.

This is in theory bad behaviour from the application, since they shouldn't be doing this on a closed handle. However, the client library behaviour can probably be improved as well.

How to repeat:
Apply this diff on testclients/mysql_client_test.cc and run main.mysql_client_test with valgrind.

diff --git a/testclients/mysql_client_test.cc b/testclients/mysql_client_test.cc
index 10950e03273..2b6d5e35e0a 100644
--- a/testclients/mysql_client_test.cc
+++ b/testclients/mysql_client_test.cc
@@ -20152,7 +20152,21 @@ static void test_bug25701141() {
   myquery(mysql_query(mysql, "DROP TABLE t1"));
 }

+static void test_leak() {
+  MYSQL *mysql_local;
+  myheader("test_leak");
+
+  if (!(mysql_local = mysql_client_init(NULL))) {
+    fprintf(stderr, "\n mysql_client_init() failed");
+    exit(1);
+  }
+
+  mysql_close(mysql_local);
+  mysql_next_result(mysql_local);
+}
+
 static struct my_tests_st my_tests[] = {
+    {"test_leak", test_leak},
     {"disable_query_logs", disable_query_logs},
     {"test_view_sp_list_fields", test_view_sp_list_fields},
     {"client_query", client_query},

Check _build/mysql-test/var/log/mysql_client_test.out.log for valgrind output that shows leak (I don't think mtr

Suggested fix:
Best solution is probably to track whether a handle is closed or not, and avoid check that flag before allocating memory for extensions.
[22 Aug 2018 4:50] MySQL Verification Team
Hello Manuel,

Thank you for the report!

regards,
Umesh
[22 Aug 2018 4:54] MySQL Verification Team
test results

Attachment: 92112_8.0.12.results (application/octet-stream, text), 273.53 KiB.

[23 Aug 2018 12:14] MySQL Verification Team
5.7.23 - test results

Attachment: 92112_5.7.23.results (application/octet-stream, text), 7.78 KiB.

[28 Jan 2019 10:35] Shishir Jaiswal
IMHO it's not a bug.

https://dev.mysql.com/doc/refman/5.7/en/c-api-threaded-clients.html
says, "When you call mysql_init(), MySQL creates a
thread-specific variable for the thread that is used by the
debug library (among other things). If you call a MySQL
function before the thread has called mysql_init(), the
thread does not have the necessary thread-specific
variables in place and you are likely to end up with a core
dump sooner or later."
[5 Feb 2019 14:55] Paul DuBois
Posted by developer:
 
After you call mysql_close() to close a connection handler, you're supposed to stop using it. Further use is bound to cause trouble.

I'll add a note to that effect to the mysql_close() section.