From cfc97fd02679dd0ddea6e2986aaf8b79a305d885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 11 Oct 2010 11:59:43 +0300 Subject: [PATCH] Bug #56947 InnoDB leaks memory when failing to create a table row_create_table_for_mysql(): When the table creation fails, free the dict_table_t object. --- mysql-test/suite/innodb/r/innodb_bug56947.result | 8 ++++++++ mysql-test/suite/innodb/t/innodb_bug56947.test | 16 ++++++++++++++++ storage/innobase/row/row0mysql.c | 14 ++++++++------ 3 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/innodb/r/innodb_bug56947.result create mode 100644 mysql-test/suite/innodb/t/innodb_bug56947.test diff --git a/mysql-test/suite/innodb/r/innodb_bug56947.result b/mysql-test/suite/innodb/r/innodb_bug56947.result new file mode 100644 index 00000000000..b279069d834 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug56947.result @@ -0,0 +1,8 @@ +SET @old_innodb_file_per_table=@@innodb_file_per_table; +SET GLOBAL innodb_file_per_table=0; +create table bug56947(a int not null) engine = innodb; +CREATE TABLE `bug56947#1`(a int) ENGINE=InnoDB; +alter table bug56947 add unique index (a); +ERROR HY000: Table 'test.bug56947#1' already exists +drop table `bug56947#1`; +drop table bug56947; diff --git a/mysql-test/suite/innodb/t/innodb_bug56947.test b/mysql-test/suite/innodb/t/innodb_bug56947.test new file mode 100644 index 00000000000..e11f39b97a8 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug56947.test @@ -0,0 +1,16 @@ +# +# Bug #56947 valgrind reports a memory leak in innodb-plugin.innodb-index +# +-- source include/have_innodb.inc + +SET @old_innodb_file_per_table=@@innodb_file_per_table; +# avoid a message about filed *.ibd file creation in the error log +SET GLOBAL innodb_file_per_table=0; +create table bug56947(a int not null) engine = innodb; +CREATE TABLE `bug56947#1`(a int) ENGINE=InnoDB; +--error 156 +alter table bug56947 add unique index (a); +drop table `bug56947#1`; +drop table bug56947; +--disable_query_log +SET GLOBAL innodb_file_per_table=@old_innodb_file_per_table; diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 3e155fd14e6..20885f4098c 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -1938,15 +1938,13 @@ err_exit: err = trx->error_state; - if (UNIV_UNLIKELY(err != DB_SUCCESS)) { + switch (err) { + case DB_SUCCESS: + break; + case DB_OUT_OF_FILE_SPACE: trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, NULL); - /* TO DO: free table? The code below will dereference - table->name, though. */ - } - switch (err) { - case DB_OUT_OF_FILE_SPACE: ut_print_timestamp(stderr); fputs(" InnoDB: Warning: cannot create table ", stderr); @@ -1961,9 +1959,13 @@ err_exit: break; case DB_DUPLICATE_KEY: + default: /* We may also get err == DB_ERROR if the .ibd file for the table already exists */ + trx->error_state = DB_SUCCESS; + trx_general_rollback_for_mysql(trx, NULL); + dict_mem_table_free(table); break; }