diff options
author | unknown <sergefp@mysql.com> | 2008-02-07 05:10:04 +0300 |
---|---|---|
committer | unknown <sergefp@mysql.com> | 2008-02-07 05:10:04 +0300 |
commit | a1e839783e3a6f415df1b404a86d86fd1553fb94 (patch) | |
tree | 4a5992b20fe286320ed3b62258b35e650611c9de /sql/handler.cc | |
parent | 65dfdcdfeb267062ef7ab5cc93c5044ef88aba20 (diff) | |
download | mariadb-git-a1e839783e3a6f415df1b404a86d86fd1553fb94.tar.gz |
BUG#27732 "Possible memory leak with index_merge"
The bug was that handler::clone/handler::ha_open() call caused allocation of
cloned_copy->ref on the handler->table->mem_root. The allocated memory could not
be reclaimed until the table is flushed, so it was possible to exhaust memory by
repeatedly running index_merge queries without doing table flushes.
The fix:
- make handler::clone() allocate new_handler->ref on the passed mem_root
- make handler::ha_open() not allocate this->ref if it has already been allocated
There is no testcase as it is not possible to check small leaks from testsuite.
sql/handler.cc:
BUG#27732 "Possible memory leak with index_merge"
- make handler::clone() allocate new_handler->ref on the passed mem_root
- make handler::ha_open() not allocate this->ref if it has already been allocated
Diffstat (limited to 'sql/handler.cc')
-rw-r--r-- | sql/handler.cc | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/sql/handler.cc b/sql/handler.cc index 27204ae725b..bfad10f986f 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1381,6 +1381,13 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path, handler *handler::clone(MEM_ROOT *mem_root) { handler *new_handler= get_new_handler(table, mem_root, table->s->db_type); + /* + Allocate handler->ref here because otherwise ha_open will allocate it + on this->table->mem_root and we will not be able to reclaim that memory + when the clone handler object is destroyed. + */ + if (!(new_handler->ref= (byte*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2))) + return NULL; if (new_handler && !new_handler->ha_open(table->s->path, table->db_stat, HA_OPEN_IGNORE_IF_LOCKED)) return new_handler; @@ -1420,8 +1427,9 @@ int handler::ha_open(const char *name, int mode, int test_if_locked) (void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL DBUG_ASSERT(alloc_root_inited(&table->mem_root)); - - if (!(ref= (byte*) alloc_root(&table->mem_root, ALIGN_SIZE(ref_length)*2))) + /* ref is already allocated for us if we're called from handler::clone() */ + if (!ref && !(ref= (byte*) alloc_root(&table->mem_root, + ALIGN_SIZE(ref_length)*2))) { close(); error=HA_ERR_OUT_OF_MEM; |