Commit c673fcb8 authored by pem@mysql.com's avatar pem@mysql.com

Getting rid of lots of memory leaks (but not quite all of them yet,

some will go away when temporary code is replaced).
parent 5eaa5954
...@@ -20,6 +20,7 @@ delete from t1; ...@@ -20,6 +20,7 @@ delete from t1;
drop procedure foo42; drop procedure foo42;
create procedure u() create procedure u()
use sptmp; use sptmp;
drop database if exists sptmp;
create database sptmp; create database sptmp;
use test; use test;
call u(); call u();
......
...@@ -35,6 +35,9 @@ drop procedure foo42; ...@@ -35,6 +35,9 @@ drop procedure foo42;
create procedure u() create procedure u()
use sptmp; use sptmp;
--disable_warnings
drop database if exists sptmp;
--enable_warnings
create database sptmp; create database sptmp;
use test; use test;
call u(); call u();
......
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
#include "sp.h" #include "sp.h"
#include "sp_head.h" #include "sp_head.h"
static sp_head * static sp_head *
sp_find_cached_function(THD *thd, char *name, uint namelen); sp_find_cached_function(THD *thd, char *name, uint namelen);
/* /*
* *
...@@ -373,6 +373,13 @@ sp_cache_functions(THD *thd, LEX *lex) ...@@ -373,6 +373,13 @@ sp_cache_functions(THD *thd, LEX *lex)
void void
sp_clear_function_cache(THD *thd) sp_clear_function_cache(THD *thd)
{ {
//QQ This doesn't work for some completely mysterious reason, but since this
//QQ is tempoarary code anyway, we just ignore it for now.
//QQ List_iterator_fast<sp_head> li(thd->spfuns);
//QQ sp_head *sp;
//QQ while ((sp= li++))
//QQ sp->destroy();
thd->spfuns.empty(); thd->spfuns.empty();
} }
......
...@@ -92,7 +92,7 @@ eval_func_item(THD *thd, Item *it, enum enum_field_types type) ...@@ -92,7 +92,7 @@ eval_func_item(THD *thd, Item *it, enum enum_field_types type)
} }
sp_head::sp_head(LEX_STRING *name, LEX *lex) sp_head::sp_head(LEX_STRING *name, LEX *lex)
: m_simple_case(FALSE) : Sql_alloc(), m_simple_case(FALSE)
{ {
const char *dstr = (const char*)lex->buf; const char *dstr = (const char*)lex->buf;
...@@ -126,19 +126,34 @@ sp_head::create(THD *thd) ...@@ -126,19 +126,34 @@ sp_head::create(THD *thd)
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
void
sp_head::destroy()
{
delete_dynamic(&m_instr);
m_pcont->destroy();
}
int int
sp_head::execute(THD *thd) sp_head::execute(THD *thd)
{ {
DBUG_ENTER("sp_head::execute"); DBUG_ENTER("sp_head::execute");
char *olddbname; char olddbname[128];
char *olddbptr= thd->db; char *olddbptr= thd->db;
int ret= 0; int ret= 0;
uint ip= 0; uint ip= 0;
LINT_INIT(olddbname);
if (olddbptr) if (olddbptr)
olddbname= my_strdup(olddbptr, MYF(MY_WME)); {
uint i= 0;
char *p= olddbptr;
/* Fast inline strncpy without padding... */
while (*p && i < sizeof(olddbname))
olddbname[i++]= *p++;
if (i == sizeof(olddbname))
i-= 1; // QQ Error or warning for truncate?
olddbname[i]= '\0';
}
do do
{ {
...@@ -156,13 +171,12 @@ sp_head::execute(THD *thd) ...@@ -156,13 +171,12 @@ sp_head::execute(THD *thd)
ret= -1; ret= -1;
/* If the DB has changed, the pointer has changed too, but the /* If the DB has changed, the pointer has changed too, but the
original thd->db will then have been freed */ original thd->db will then have been freed */
if (olddbptr && olddbptr != thd->db && olddbname) if (olddbptr && olddbptr != thd->db)
{ {
/* QQ Maybe we should issue some special error message or warning here, /* QQ Maybe we should issue some special error message or warning here,
if this fails?? */ if this fails?? */
if (! thd->killed) if (! thd->killed)
ret= mysql_change_db(thd, olddbname); ret= mysql_change_db(thd, olddbname);
my_free(olddbname, MYF(0));
} }
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
...@@ -399,7 +413,7 @@ sp_head::restore_lex(THD *thd) ...@@ -399,7 +413,7 @@ sp_head::restore_lex(THD *thd)
void void
sp_head::push_backpatch(sp_instr *i, sp_label_t *lab) sp_head::push_backpatch(sp_instr *i, sp_label_t *lab)
{ {
bp_t *bp= (bp_t *)my_malloc(sizeof(bp_t), MYF(MY_WME)); bp_t *bp= (bp_t *)sql_alloc(sizeof(bp_t));
if (bp) if (bp)
{ {
......
...@@ -52,21 +52,15 @@ class sp_head : public Sql_alloc ...@@ -52,21 +52,15 @@ class sp_head : public Sql_alloc
List<char *> m_tables; // Used tables. List<char *> m_tables; // Used tables.
#endif #endif
static void *operator new(size_t size)
{
return (void*) sql_alloc((uint) size);
}
static void operator delete(void *ptr, size_t size)
{
/* Empty */
}
sp_head(LEX_STRING *name, LEX *lex); sp_head(LEX_STRING *name, LEX *lex);
int int
create(THD *thd); create(THD *thd);
// Free memory
void
destroy();
int int
execute_function(THD *thd, Item **args, uint argcount, Item **resp); execute_function(THD *thd, Item **args, uint argcount, Item **resp);
...@@ -134,11 +128,13 @@ class sp_head : public Sql_alloc ...@@ -134,11 +128,13 @@ class sp_head : public Sql_alloc
inline sp_instr * inline sp_instr *
get_instr(uint i) get_instr(uint i)
{ {
sp_instr *in= NULL; sp_instr *ip;
if (i < m_instr.elements) if (i < m_instr.elements)
get_dynamic(&m_instr, (gptr)&in, i); get_dynamic(&m_instr, (gptr)&ip, i);
return in; else
ip= NULL;
return ip;
} }
int int
......
...@@ -27,30 +27,20 @@ ...@@ -27,30 +27,20 @@
#include "sp_head.h" #include "sp_head.h"
sp_pcontext::sp_pcontext() sp_pcontext::sp_pcontext()
: m_params(0), m_framesize(0), m_i(0), m_genlab(0) : Sql_alloc(), m_params(0), m_framesize(0), m_genlab(0)
{ {
m_pvar_size = 16; VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
m_pvar = (sp_pvar_t *)my_malloc(m_pvar_size * sizeof(sp_pvar_t), MYF(MY_WME));
if (m_pvar)
memset(m_pvar, 0, m_pvar_size * sizeof(sp_pvar_t));
m_label.empty(); m_label.empty();
} }
void void
sp_pcontext::grow() sp_pcontext::destroy()
{ {
uint sz = m_pvar_size + 8; delete_dynamic(&m_pvar);
sp_pvar_t *a = (sp_pvar_t *)my_realloc((char *)m_pvar, m_label.empty();
sz * sizeof(sp_pvar_t),
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
if (a)
{
m_pvar_size = sz;
m_pvar = a;
}
} }
/* This does a linear search (from newer to older variables, in case /* This does a linear search (from newer to older variables, in case
** we have shadowed names). ** we have shadowed names).
** It's possible to have a more efficient allocation and search method, ** It's possible to have a more efficient allocation and search method,
...@@ -61,19 +51,20 @@ sp_pcontext::grow() ...@@ -61,19 +51,20 @@ sp_pcontext::grow()
sp_pvar_t * sp_pvar_t *
sp_pcontext::find_pvar(LEX_STRING *name) sp_pcontext::find_pvar(LEX_STRING *name)
{ {
uint i = m_i; uint i = m_pvar.elements;
while (i-- > 0) while (i-- > 0)
{ {
uint len= (m_pvar[i].name.length > name->length ? sp_pvar_t *p= find_pvar(i);
m_pvar[i].name.length : name->length); uint len= (p->name.length > name->length ?
p->name.length : name->length);
if (my_strncasecmp(system_charset_info, if (my_strncasecmp(system_charset_info,
name->str, name->str,
m_pvar[i].name.str, p->name.str,
len) == 0) len) == 0)
{ {
return m_pvar + i; return p;
} }
} }
return NULL; return NULL;
...@@ -83,26 +74,26 @@ void ...@@ -83,26 +74,26 @@ void
sp_pcontext::push(LEX_STRING *name, enum enum_field_types type, sp_pcontext::push(LEX_STRING *name, enum enum_field_types type,
sp_param_mode_t mode) sp_param_mode_t mode)
{ {
if (m_i >= m_pvar_size) sp_pvar_t *p= (sp_pvar_t *)sql_alloc(sizeof(sp_pvar_t));
grow();
if (m_i < m_pvar_size) if (p)
{ {
if (m_i == m_framesize) if (m_pvar.elements == m_framesize)
m_framesize += 1; m_framesize += 1;
m_pvar[m_i].name.str= name->str; p->name.str= name->str;
m_pvar[m_i].name.length= name->length, p->name.length= name->length;
m_pvar[m_i].type= type; p->type= type;
m_pvar[m_i].mode= mode; p->mode= mode;
m_pvar[m_i].offset= m_i; p->offset= m_pvar.elements;
m_pvar[m_i].isset= (mode == sp_param_out ? FALSE : TRUE); p->isset= (mode == sp_param_out ? FALSE : TRUE);
m_i += 1; insert_dynamic(&m_pvar, (gptr)&p);
} }
} }
sp_label_t * sp_label_t *
sp_pcontext::push_label(char *name, uint ip) sp_pcontext::push_label(char *name, uint ip)
{ {
sp_label_t *lab = (sp_label_t *)my_malloc(sizeof(sp_label_t), MYF(MY_WME)); sp_label_t *lab = (sp_label_t *)sql_alloc(sizeof(sp_label_t));
if (lab) if (lab)
{ {
......
...@@ -53,6 +53,10 @@ class sp_pcontext : public Sql_alloc ...@@ -53,6 +53,10 @@ class sp_pcontext : public Sql_alloc
sp_pcontext(); sp_pcontext();
// Free memory
void
destroy();
inline uint inline uint
max_framesize() max_framesize()
{ {
...@@ -62,7 +66,7 @@ class sp_pcontext : public Sql_alloc ...@@ -62,7 +66,7 @@ class sp_pcontext : public Sql_alloc
inline uint inline uint
current_framesize() current_framesize()
{ {
return m_i; return m_pvar.elements;
} }
inline uint inline uint
...@@ -75,21 +79,25 @@ class sp_pcontext : public Sql_alloc ...@@ -75,21 +79,25 @@ class sp_pcontext : public Sql_alloc
inline void inline void
set_params() set_params()
{ {
m_params= m_i; m_params= m_pvar.elements;
} }
inline void inline void
set_type(uint i, enum enum_field_types type) set_type(uint i, enum enum_field_types type)
{ {
if (i < m_i) sp_pvar_t *p= find_pvar(i);
m_pvar[i].type= type;
if (p)
p->type= type;
} }
inline void inline void
set_isset(uint i, my_bool val) set_isset(uint i, my_bool val)
{ {
if (i < m_i) sp_pvar_t *p= find_pvar(i);
m_pvar[i].isset= val;
if (p)
p->isset= val;
} }
void void
...@@ -99,8 +107,8 @@ class sp_pcontext : public Sql_alloc ...@@ -99,8 +107,8 @@ class sp_pcontext : public Sql_alloc
inline void inline void
pop(uint num = 1) pop(uint num = 1)
{ {
if (num < m_i) while (num--)
m_i -= num; pop_dynamic(&m_pvar);
} }
// Find by name // Find by name
...@@ -111,9 +119,13 @@ class sp_pcontext : public Sql_alloc ...@@ -111,9 +119,13 @@ class sp_pcontext : public Sql_alloc
sp_pvar_t * sp_pvar_t *
find_pvar(uint i) find_pvar(uint i)
{ {
if (i >= m_i) sp_pvar_t *p;
return NULL;
return m_pvar+i; if (i < m_pvar.elements)
get_dynamic(&m_pvar, (gptr)&p, i);
else
p= NULL;
return p;
} }
sp_label_t * sp_label_t *
...@@ -138,13 +150,8 @@ class sp_pcontext : public Sql_alloc ...@@ -138,13 +150,8 @@ class sp_pcontext : public Sql_alloc
uint m_params; // The number of parameters uint m_params; // The number of parameters
uint m_framesize; // The maximum framesize uint m_framesize; // The maximum framesize
uint m_i; // The current index (during parsing)
sp_pvar_t *m_pvar;
uint m_pvar_size; // Current size of m_pvar.
void DYNAMIC_ARRAY m_pvar;
grow();
List<sp_label_t> m_label; // The label list List<sp_label_t> m_label; // The label list
uint m_genlab; // Gen. label counter uint m_genlab; // Gen. label counter
......
...@@ -191,6 +191,9 @@ THD::THD():user_time(0), is_fatal_error(0), ...@@ -191,6 +191,9 @@ THD::THD():user_time(0), is_fatal_error(0),
pthread_mutex_unlock(&LOCK_thread_count); pthread_mutex_unlock(&LOCK_thread_count);
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id); randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id);
} }
/* QQ init the temporary function cache */
spfuns.empty();
} }
...@@ -282,6 +285,10 @@ void THD::cleanup(void) ...@@ -282,6 +285,10 @@ void THD::cleanup(void)
pthread_mutex_unlock(&LOCK_user_locks); pthread_mutex_unlock(&LOCK_user_locks);
ull= 0; ull= 0;
} }
// extern void sp_clear_function_cache(THD *);
// sp_clear_function_cache(this);
cleanup_done=1; cleanup_done=1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -2810,6 +2810,7 @@ mysql_execute_command(THD *thd) ...@@ -2810,6 +2810,7 @@ mysql_execute_command(THD *thd)
sp_head *sph= sp_find_function(thd, &lex->udf.name); sp_head *sph= sp_find_function(thd, &lex->udf.name);
if (sph) if (sph)
{ {
sph->destroy(); // QQ Free memory. Remove this when caching!!!
net_printf(thd, ER_UDF_EXISTS, lex->udf.name.str); net_printf(thd, ER_UDF_EXISTS, lex->udf.name.str);
goto error; goto error;
} }
...@@ -3050,6 +3051,8 @@ mysql_execute_command(THD *thd) ...@@ -3050,6 +3051,8 @@ mysql_execute_command(THD *thd)
thd->net.no_send_ok= nsok; thd->net.no_send_ok= nsok;
#endif #endif
sp->destroy(); // QQ Free memory. Remove this when caching!!!
if (res == 0) if (res == 0)
send_ok(thd); send_ok(thd);
else else
...@@ -3075,6 +3078,7 @@ mysql_execute_command(THD *thd) ...@@ -3075,6 +3078,7 @@ mysql_execute_command(THD *thd)
{ {
/* QQ This is an no-op right now, since we haven't /* QQ This is an no-op right now, since we haven't
put the characteristics in yet. */ put the characteristics in yet. */
sp->destroy(); // QQ Free memory. Remove this when caching!!!
send_ok(thd); send_ok(thd);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment