1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-34517: Memory leak on re-compilation of a failing statement inside a stored routine

SP instructions, consisting a body of a stored routine, had the same memory
root as an instance of the class sp_head, representing abstraction for stored
routine itself. It resulted in memory leaks on re-parsing a failed statement
of a stored routine in case the statement re-compilation has to be performed
by the reason of changes in metadata of tables, triggers, etc. the stored
routine depends on.

To fix this kind of memory leaks, every SP instruction requiring access to
a LEX object must do re-parsing of a failed statement on its own memory root.
These memory roots are allocated on sp_head's memory root and every instance of
the sp_lex_instr class has a pointer to allocated memory root in case re-parsing
of the correspondiong SP instruction was requested. On every subsequent
re-parsing of the failed statement, a memory allocated on SP instruction's
memory root is released and the memory root re-initialized. Following memory
allocations taken place on re-parsing the SP instruction's statement
is performed on the dedicated memory root. So, no memory leaks will happen on
SP statement re-parsing.
This commit is contained in:
Dmitry Shulga
2024-07-24 16:01:38 +07:00
parent 03807c8449
commit ba5a0ff4f8
4 changed files with 183 additions and 1 deletions

View File

@@ -278,6 +278,7 @@ public:
{
if (m_lex_resp)
{
m_lex_resp= false;
/* Prevent endless recursion. */
m_lex->sphead= nullptr;
lex_end(m_lex);
@@ -397,9 +398,30 @@ class sp_lex_instr : public sp_instr
public:
sp_lex_instr(uint ip, sp_pcontext *ctx, LEX *lex, bool is_lex_owner)
: sp_instr(ip, ctx),
m_lex_keeper(lex, is_lex_owner)
m_lex_keeper(lex, is_lex_owner),
m_mem_root_for_reparsing(nullptr)
{}
~sp_lex_instr() override
{
if (m_mem_root_for_reparsing)
{
/*
Free items owned by an instance of sp_lex_instr and call m_lex_keeper's
destructor explicitly to avoid referencing a deallocated memory
owned by the memory root m_mem_root_for_reparsing that else would take
place in case their implicit invocations (in that case, m_lex_keeper's
destructor and the method free_items() called by ~sp_instr are invoked
after the memory owned by the memory root m_mem_root_for_reparsing
be freed, that would result in abnormal server termination)
*/
free_items();
m_lex_keeper.~sp_lex_keeper();
free_root(m_mem_root_for_reparsing, MYF(0));
m_mem_root_for_reparsing= nullptr;
}
}
virtual bool is_invalid() const = 0;
virtual void invalidate() = 0;
@@ -469,6 +491,12 @@ private:
*/
SQL_I_List<Item_trigger_field> m_cur_trigger_stmt_items;
/**
MEM_ROOT used for allocation of memory on re-parsing of a statement
caused failure of SP-instruction execution
*/
MEM_ROOT *m_mem_root_for_reparsing;
/**
Clean up items previously created on behalf of the current instruction.
*/
@@ -492,6 +520,8 @@ private:
bool setup_table_fields_for_trigger(
THD *thd, sp_head *sp,
SQL_I_List<Item_trigger_field> *next_trig_items_list);
bool setup_memroot_for_reparsing(sp_head *sphead);
};