summaryrefslogtreecommitdiff
path: root/sql/sp_rcontext.cc
diff options
context:
space:
mode:
authorunknown <pem@mysql.comhem.se>2005-05-23 23:43:43 +0200
committerunknown <pem@mysql.comhem.se>2005-05-23 23:43:43 +0200
commit9c79a9d69165aaba06ac6c7300b2216a372be204 (patch)
tree616f85ace18874855d5ab3b1a193fe32e82e096a /sql/sp_rcontext.cc
parent982bd00d481333c44e6aee59fc667f8de155a612 (diff)
downloadmariadb-git-9c79a9d69165aaba06ac6c7300b2216a372be204.tar.gz
Fixed on BUG#6048: Stored procedure causes operating system reboot
Memory leak in locally evalutated expressions during SP execution fixed by reusing allocated item slots when possible. Note: No test case added, since the test is a stress test that tries to make the machine to run out of memory. Second attempt, now tested with debug build, valgrind build, max (optimized) build, with and without --debug, --vagrind and --ps-protocol. Errors in trigger and view test with --debug in debug build where present before this patch, and likewise for valgrind warnings for view test in valgrind build with --ps-protocol. sql/item.cc: Init rsize in Item (for SP item reusal). sql/item.h: Addes special new operator for reuse of Items, for SP internal use only. sql/sp_head.cc: Reuse items assigned internally in SPs when possible. sql/sp_rcontext.cc: Reuse items assigned internally in SPs when possible. Moved the local variable assignment here (from sp_head) to avoid duplicated code. sql/sp_rcontext.h: New arg to sp_rcontext::set_item_eval() (and some coding style). sql/sql_class.cc: Adjusted call to new set_item_eval().
Diffstat (limited to 'sql/sp_rcontext.cc')
-rw-r--r--sql/sp_rcontext.cc63
1 files changed, 52 insertions, 11 deletions
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 672491a97f2..49ead5d1585 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -40,19 +40,39 @@ sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax)
m_saved.empty();
}
+
int
-sp_rcontext::set_item_eval(uint idx, Item **item_addr, enum_field_types type)
+sp_rcontext::set_item_eval(THD *thd, uint idx, Item **item_addr,
+ enum_field_types type)
{
- extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type);
- Item *it= sp_eval_func_item(current_thd, item_addr, type);
+ extern Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type,
+ Item *reuse);
+ Item *it;
+ Item *reuse_it;
+ Item *old_item_next;
+ Item *old_free_list= thd->free_list;
+ int res;
+ LINT_INIT(old_item_next);
+ if ((reuse_it= get_item(idx)))
+ old_item_next= reuse_it->next;
+ it= sp_eval_func_item(thd, item_addr, type, reuse_it);
if (! it)
- return -1;
+ res= -1;
else
{
+ res= 0;
+ if (reuse_it && it == reuse_it)
+ {
+ // A reused item slot, where the constructor put it in the free_list,
+ // so we have to restore the list.
+ thd->free_list= old_free_list;
+ it->next= old_item_next;
+ }
set_item(idx, it);
- return 0;
}
+
+ return res;
}
bool
@@ -111,7 +131,10 @@ void
sp_rcontext::save_variables(uint fp)
{
while (fp < m_count)
- m_saved.push_front(m_frame[fp++]);
+ {
+ m_saved.push_front(m_frame[fp]);
+ m_frame[fp++]= NULL; // Prevent reuse
+ }
}
void
@@ -230,7 +253,12 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
for (fldcount= 0 ; (pv= li++) ; fldcount++)
{
Item *it;
+ Item *reuse;
+ uint rsize;
+ Item *old_item_next;
+ Item *old_free_list= thd->free_list;
const char *s;
+ LINT_INIT(old_item_next);
if (fldcount >= m_prot->get_field_count())
{
@@ -238,9 +266,13 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
return -1;
}
+
+ if ((reuse= thd->spcont->get_item(pv->offset)))
+ old_item_next= reuse->next;
+
s= row[fldcount];
if (!s)
- it= new Item_null();
+ it= new(reuse, &rsize) Item_null();
else
{
/*
@@ -255,23 +287,32 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
len= (*next -s)-1;
switch (sp_map_result_type(pv->type)) {
case INT_RESULT:
- it= new Item_int(s);
+ it= new(reuse, &rsize) Item_int(s);
break;
case REAL_RESULT:
- it= new Item_float(s, len);
+ it= new(reuse, &rsize) Item_float(s, len);
break;
case DECIMAL_RESULT:
- it= new Item_decimal(s, len, thd->db_charset);
+ it= new(reuse, &rsize) Item_decimal(s, len, thd->db_charset);
break;
case STRING_RESULT:
/* TODO: Document why we do an extra copy of the string 's' here */
- it= new Item_string(thd->strmake(s, len), len, thd->db_charset);
+ it= new(reuse, &rsize) Item_string(thd->strmake(s, len), len,
+ thd->db_charset);
break;
case ROW_RESULT:
default:
DBUG_ASSERT(0);
}
}
+ it->rsize= rsize;
+ if (reuse && it == reuse)
+ {
+ // A reused item slot, where the constructor put it in the free_list,
+ // so we have to restore the list.
+ thd->free_list= old_free_list;
+ it->next= old_item_next;
+ }
thd->spcont->set_item(pv->offset, it);
}
if (fldcount < m_prot->get_field_count())