Fix for yet another memleak caused by SP-locking patch.

Improved handling of situations when we encounter error during
CREATE PROCEDURE (FUNCTION/TRIGGER/...) and bail out of yyparse()
without restoring proper THD::lex.
parent c2482083
...@@ -307,8 +307,6 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp) ...@@ -307,8 +307,6 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
goto done; goto done;
if (sp) if (sp)
{ {
if (oldlex != newlex)
sp->restore_lex(thd);
delete sp; delete sp;
newlex->sphead= NULL; newlex->sphead= NULL;
} }
......
...@@ -459,11 +459,22 @@ sp_head::destroy() ...@@ -459,11 +459,22 @@ sp_head::destroy()
delete_dynamic(&m_instr); delete_dynamic(&m_instr);
m_pcont->destroy(); m_pcont->destroy();
free_items(free_list); free_items(free_list);
/*
If we have non-empty LEX stack then we just came out of parser with
error. Now we should delete all auxilary LEXes and restore original
THD::lex (In this case sp_head::restore_thd_mem_root() was not called
too, so m_thd points to the current thread context).
It is safe to not update LEX::ptr because further query string parsing
and execution will be stopped anyway.
*/
DBUG_ASSERT(m_lex.is_empty() || m_thd);
while ((lex= (LEX *)m_lex.pop())) while ((lex= (LEX *)m_lex.pop()))
{ {
if (lex != &m_thd->main_lex) // We got interrupted and have lex'es left delete m_thd->lex;
delete lex; m_thd->lex= lex;
} }
hash_free(&m_sptabs); hash_free(&m_sptabs);
hash_free(&m_spfuns); hash_free(&m_spfuns);
hash_free(&m_spprocs); hash_free(&m_spprocs);
......
...@@ -5083,8 +5083,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length) ...@@ -5083,8 +5083,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
{ {
if (thd->lex->sphead) if (thd->lex->sphead)
{ {
if (lex != thd->lex)
thd->lex->sphead->restore_lex(thd);
delete thd->lex->sphead; delete thd->lex->sphead;
thd->lex->sphead= NULL; thd->lex->sphead= NULL;
} }
...@@ -5120,8 +5118,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length) ...@@ -5120,8 +5118,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
if (thd->lex->sphead) if (thd->lex->sphead)
{ {
/* Clean up after failed stored procedure/function */ /* Clean up after failed stored procedure/function */
if (lex != thd->lex)
thd->lex->sphead->restore_lex(thd);
delete thd->lex->sphead; delete thd->lex->sphead;
thd->lex->sphead= NULL; thd->lex->sphead= NULL;
} }
......
...@@ -1771,8 +1771,6 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, ...@@ -1771,8 +1771,6 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
my_pthread_setprio(pthread_self(),WAIT_PRIOR); my_pthread_setprio(pthread_self(),WAIT_PRIOR);
if (error && thd->lex->sphead) if (error && thd->lex->sphead)
{ {
if (lex != thd->lex)
thd->lex->sphead->restore_lex(thd);
delete thd->lex->sphead; delete thd->lex->sphead;
thd->lex->sphead= NULL; thd->lex->sphead= NULL;
} }
......
...@@ -415,9 +415,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, ...@@ -415,9 +415,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
*/ */
if (lex.sphead) if (lex.sphead)
{ {
if (&lex != thd->lex)
thd->lex->sphead->restore_lex(thd);
delete lex.sphead; delete lex.sphead;
lex.sphead= 0;
} }
goto err_with_lex_cleanup; goto err_with_lex_cleanup;
} }
......
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