Skip to content

Commit 08e6431

Browse files
committed
Fixed memory leak introduces by a fix for MDEV-29932
The leaks are all 40 bytes and happens in this call stack when running mtr vcol.vcol_syntax: alloc_root() ... Virtual_column_info::fix_and_check_exp() ... Delayed_insert::get_local_table() The problem was that one copied a MEM_ROOT from THD to a TABLE without taking into account that new blocks would be allocated through the TABLE memroot (and would thus be leaked). In general, one should NEVER copy MEM_ROOT from one object to another without clearing the copied memroot! Fixed by, at end of get_local_table(), copy all new allocated objects to client_thd->mem_root. Other things: - Removed references to MEM_ROOT::total_alloc that was wrongly left after a previous commit
1 parent 8e96119 commit 08e6431

File tree

3 files changed

+29
-2
lines changed

3 files changed

+29
-2
lines changed

include/my_sys.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,7 @@ extern void init_alloc_root(MEM_ROOT *mem_root, const char *name,
892892
extern void *alloc_root(MEM_ROOT *mem_root, size_t Size);
893893
extern void *multi_alloc_root(MEM_ROOT *mem_root, ...);
894894
extern void free_root(MEM_ROOT *root, myf MyFLAGS);
895+
extern void move_root(MEM_ROOT *to, MEM_ROOT *from);
895896
extern void set_prealloc_root(MEM_ROOT *root, char *ptr);
896897
extern void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,
897898
size_t prealloc_size);

mysys/my_alloc.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,6 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length)
199199
next->left= 0;
200200
next->size= length;
201201
mem_root->used= next;
202-
mem_root->total_alloc+= length;
203202
DBUG_PRINT("exit",("ptr: %p", (((char*) next)+
204203
ALIGN_SIZE(sizeof(USED_MEM)))));
205204
DBUG_RETURN((uchar*) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM))));
@@ -460,6 +459,28 @@ void set_prealloc_root(MEM_ROOT *root, char *ptr)
460459
}
461460
}
462461

462+
/*
463+
Move allocated objects from one root to another.
464+
465+
Notes:
466+
We do not increase 'to->block_num' here as the variable isused to
467+
increase block sizes in case of many allocations. This is special
468+
case where this is not needed to take into account
469+
*/
470+
471+
void move_root(MEM_ROOT *to, MEM_ROOT *from)
472+
{
473+
USED_MEM *block, *next;
474+
for (block= from->used; block ; block= next)
475+
{
476+
next= block->next;
477+
block->next= to->used;
478+
to->used= block;
479+
}
480+
from->used= 0;
481+
}
482+
483+
463484

464485
char *strdup_root(MEM_ROOT *root, const char *str)
465486
{

sql/sql_insert.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2635,7 +2635,9 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
26352635
copy= new (copy_tmp) TABLE;
26362636
*copy= *table;
26372637
copy->vcol_refix_list.empty();
2638-
copy->mem_root= *client_thd->mem_root;
2638+
init_alloc_root(&copy->mem_root, client_thd->mem_root->name,
2639+
client_thd->mem_root->block_size,
2640+
0, MY_THREAD_SPECIFIC);
26392641

26402642
/* We don't need to change the file handler here */
26412643
/* Assign the pointers for the field pointers array and the record. */
@@ -2729,11 +2731,14 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
27292731
bzero((char*) bitmap, share->column_bitmap_size * bitmaps_used);
27302732
copy->read_set= &copy->def_read_set;
27312733
copy->write_set= &copy->def_write_set;
2734+
move_root(client_thd->mem_root, &copy->mem_root);
2735+
free_root(&copy->mem_root, 0);
27322736

27332737
DBUG_RETURN(copy);
27342738

27352739
/* Got fatal error */
27362740
error:
2741+
free_root(&copy->mem_root, 0);
27372742
tables_in_use--;
27382743
mysql_cond_signal(&cond); // Inform thread about abort
27392744
DBUG_RETURN(0);

0 commit comments

Comments
 (0)