Commit 9d431a0d authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-19439 - Allow THD member (or base) class constructor/destructor to allocate/free memory

Fixed by moving memory accounting to THD_count constructor/destructor, so
that memory accounting is configured before member/base constructors
have been called and deinitialised after member/base destructors have been
finished.
parent f81007f8
......@@ -137,7 +137,7 @@ class Session_sysvars_tracker: public State_tracker
bool track_all;
void init()
{
my_hash_init(&m_registered_sysvars, &my_charset_bin, 0, 0, 0,
my_hash_init(&m_registered_sysvars, &my_charset_bin, 4, 0, 0,
(my_hash_get_key) sysvars_get_key, my_free,
HASH_UNIQUE | (mysqld_server_initialized ?
HASH_THREAD_SPECIFIC : 0));
......@@ -164,8 +164,7 @@ class Session_sysvars_tracker: public State_tracker
}
public:
vars_list(): track_all(false) { init(); }
~vars_list() { if (my_hash_inited(&m_registered_sysvars)) free_hash(); }
void deinit() { free_hash(); }
~vars_list() { free_hash(); }
sysvar_node_st *insert_or_search(const sys_var *svar)
{
......@@ -208,7 +207,6 @@ class Session_sysvars_tracker: public State_tracker
bool update(THD *thd, set_var *var);
bool store(THD *thd, String *buf);
void mark_as_changed(THD *thd, LEX_CSTRING *tracked_item_name);
void deinit() { orig_list.deinit(); }
/* callback */
static uchar *sysvars_get_key(const char *entry, size_t *length,
my_bool not_used __attribute__((unused)));
......
......@@ -600,6 +600,43 @@ extern "C" void thd_kill_timeout(THD* thd)
thd->awake(KILL_TIMEOUT);
}
THD_count::THD_count()
{
THD *thd= static_cast<THD*>(this);
thread_count++;
/*
We set THR_THD to temporally point to this THD to register all the
variables that allocates memory for this THD
*/
orig_thd= current_thd;
set_current_thd(thd);
thd->status_var.local_memory_used= sizeof(THD);
thd->status_var.max_local_memory_used= thd->status_var.local_memory_used;
thd->status_var.global_memory_used= 0;
thd->variables.max_mem_used= global_system_variables.max_mem_used;
}
THD_count::~THD_count()
{
THD *thd= static_cast<THD*>(this);
/* Ensure everything is freed */
thd->status_var.local_memory_used-= sizeof(THD);
if (thd->status_var.local_memory_used != 0)
{
DBUG_PRINT("error", ("memory_used: %lld",
thd->status_var.local_memory_used));
SAFEMALLOC_REPORT_MEMORY(thd->thread_id);
DBUG_ASSERT(thd->status_var.local_memory_used == 0 ||
!debug_assert_on_not_freed_memory);
}
update_global_memory_status(thd->status_var.global_memory_used);
set_current_thd(orig_thd);
thread_count--;
}
THD::THD(my_thread_id id, bool is_wsrep_applier)
:Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,
/* statement id */ 0),
......@@ -690,15 +727,6 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
ulong tmp;
bzero(&variables, sizeof(variables));
/*
We set THR_THD to temporally point to this THD to register all the
variables that allocates memory for this THD
*/
THD *old_THR_THD= current_thd;
set_current_thd(this);
status_var.local_memory_used= sizeof(THD);
status_var.max_local_memory_used= status_var.local_memory_used;
status_var.global_memory_used= 0;
variables.pseudo_thread_id= thread_id;
variables.max_mem_used= global_system_variables.max_mem_used;
main_da.init();
......@@ -866,8 +894,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
force_read_stats= FALSE;
save_prep_leaf_list= FALSE;
org_charset= 0;
/* Restore THR_THD */
set_current_thd(old_THR_THD);
set_current_thd(orig_thd);
}
......@@ -1648,7 +1675,6 @@ void THD::reset_for_reuse()
THD::~THD()
{
THD *orig_thd= current_thd;
THD_CHECK_SENTRY(this);
DBUG_ENTER("~THD()");
/* Make sure threads are not available via server_threads. */
......@@ -1658,7 +1684,11 @@ THD::~THD()
In error cases, thd may not be current thd. We have to fix this so
that memory allocation counting is done correctly
*/
set_current_thd(this);
orig_thd= current_thd;
if (orig_thd == this)
orig_thd= 0;
else
set_current_thd(this);
if (!status_in_global)
add_status_to_global();
......@@ -1716,23 +1746,6 @@ THD::~THD()
lf_hash_put_pins(tdc_hash_pins);
if (xid_hash_pins)
lf_hash_put_pins(xid_hash_pins);
/* Ensure everything is freed */
status_var.local_memory_used-= sizeof(THD);
/* trick to make happy memory accounting system */
#ifndef EMBEDDED_LIBRARY
session_tracker.sysvars.deinit();
#endif //EMBEDDED_LIBRARY
if (status_var.local_memory_used != 0)
{
DBUG_PRINT("error", ("memory_used: %lld", status_var.local_memory_used));
SAFEMALLOC_REPORT_MEMORY(thread_id);
DBUG_ASSERT(status_var.local_memory_used == 0 ||
!debug_assert_on_not_freed_memory);
}
update_global_memory_status(status_var.global_memory_used);
set_current_thd(orig_thd == this ? 0 : orig_thd);
DBUG_VOID_RETURN;
}
......
......@@ -2132,10 +2132,12 @@ extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
Destructor unblocks close_conneciton() if there are no more THD's left.
*/
struct THD_count
class THD_count
{
THD_count() { thread_count++; }
~THD_count() { thread_count--; }
THD *orig_thd;
THD_count();
~THD_count();
friend class 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