Skip to content

Commit 0e92a68

Browse files
committed
(Corrected) Fix for CONC-118: memory leak when reconnecting
1 parent 5c471dc commit 0e92a68

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

libmariadb/libmariadb.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,11 +2022,12 @@ static my_bool mysql_reconnect(MYSQL *mysql)
20222022
}
20232023

20242024
tmp_mysql.reconnect= mysql->reconnect;
2025-
bzero((char*) &mysql->options,sizeof(mysql->options));
20262025
if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
20272026
mysql->db, mysql->port, mysql->unix_socket,
20282027
mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
20292028
{
2029+
/* don't free options (CONC-118) */
2030+
memset(&tmp_mysql.options, 0, sizeof(struct st_mysql_options));
20302031
my_set_error(mysql, tmp_mysql.net.last_errno,
20312032
tmp_mysql.net.sqlstate,
20322033
tmp_mysql.net.last_error);
@@ -2046,14 +2047,16 @@ static my_bool mysql_reconnect(MYSQL *mysql)
20462047
stmt->state= MYSQL_STMT_INITTED;
20472048
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
20482049
}
2049-
else
2050-
tmp_mysql.stmts= list_add(tmp_mysql.stmts, &stmt->list);
20512050
}
20522051

2052+
tmp_mysql.free_me= mysql->free_me;
2053+
tmp_mysql.stmts= mysql->stmts;
2054+
2055+
/* Don't free options, we moved them to tmp_mysql */
2056+
memset(&mysql->options, 0, sizeof(mysql->options));
20532057
mysql->free_me=0;
20542058
mysql->stmts= NULL;
20552059
mysql_close(mysql);
2056-
memset(&mysql->options, 0, sizeof(mysql->options));
20572060
*mysql=tmp_mysql;
20582061
mysql->reconnect= 1;
20592062
net_clear(&mysql->net);

unittest/libmariadb/connection.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,39 @@ int test_connection_timeout(MYSQL *my)
638638
return OK;
639639
}
640640

641+
/* test should run with valgrind */
642+
static int test_conc118(MYSQL *mysql)
643+
{
644+
int rc;
645+
646+
mysql->reconnect= 1;
647+
mysql->options.unused_1= 1;
648+
649+
rc= mysql_kill(mysql, mysql_thread_id(mysql));
650+
sleep(2);
651+
652+
rc= mysql_query(mysql, "SET @a:=1");
653+
check_mysql_rc(rc, mysql);
654+
655+
FAIL_IF(mysql->options.unused_1 != 1, "options got lost");
656+
657+
rc= mysql_kill(mysql, mysql_thread_id(mysql));
658+
sleep(2);
659+
660+
mysql->host= "foo";
661+
662+
rc= mysql_query(mysql, "SET @a:=1");
663+
FAIL_IF(!rc, "error expected");
664+
665+
mysql->host= hostname;
666+
rc= mysql_query(mysql, "SET @a:=1");
667+
check_mysql_rc(rc, mysql);
668+
669+
return OK;
670+
}
671+
641672
struct my_tests_st my_tests[] = {
673+
{"test_conc118", test_conc118, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
642674
{"test_conc66", test_conc66, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
643675
{"test_bug20023", test_bug20023, TEST_CONNECTION_NEW, 0, NULL, NULL},
644676
{"test_bug31669", test_bug31669, TEST_CONNECTION_NEW, 0, NULL, NULL},

0 commit comments

Comments
 (0)