diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 43f26751f27..158dfc48935 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -99,7 +99,7 @@ static void calculate_block_sizes(MEM_ROOT *mem_root, size_t block_size, { size_t pre_alloc= *pre_alloc_size; - if (mem_root->flags&= ROOT_FLAG_MPROTECT) + if (mem_root->flags & ROOT_FLAG_MPROTECT) { mem_root->block_size= MY_ALIGN(block_size, my_system_page_size); if (pre_alloc) @@ -159,6 +159,8 @@ void init_alloc_root(PSI_memory_key key, MEM_ROOT *mem_root, size_t block_size, mem_root->min_malloc= 32 + REDZONE_SIZE; mem_root->block_size= MY_MAX(block_size, ROOT_MIN_BLOCK_SIZE); mem_root->flags= 0; + DBUG_ASSERT(!test_all_bits(mem_root->flags, + (MY_THREAD_SPECIFIC | MY_ROOT_USE_MPROTECT))); if (my_flags & MY_THREAD_SPECIFIC) mem_root->flags|= ROOT_FLAG_THREAD_SPECIFIC; if (my_flags & MY_ROOT_USE_MPROTECT) diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c index b8f64de589e..a1a7a1303df 100644 --- a/mysys/my_malloc.c +++ b/mysys/my_malloc.c @@ -44,15 +44,12 @@ typedef struct my_memory_header my_memory_header; @return 0 - ok 1 - failure, abort the allocation */ -static void dummy(long long size __attribute__((unused)), - my_bool is_thread_specific __attribute__((unused))) -{} -static MALLOC_SIZE_CB update_malloc_size= dummy; +static MALLOC_SIZE_CB update_malloc_size= 0; void set_malloc_size_cb(MALLOC_SIZE_CB func) { - update_malloc_size= func ? func : dummy; + update_malloc_size= func; } @@ -106,7 +103,11 @@ void *my_malloc(PSI_memory_key key, size_t size, myf my_flags) int flag= MY_TEST(my_flags & MY_THREAD_SPECIFIC); mh->m_size= size | flag; mh->m_key= PSI_CALL_memory_alloc(key, size, & mh->m_owner); - update_malloc_size(size + HEADER_SIZE, flag); + if (update_malloc_size) + { + mh->m_size|=2; + update_malloc_size(size + HEADER_SIZE, flag); + } point= HEADER_TO_USER(mh); if (my_flags & MY_ZEROFILL) bzero(point, size); @@ -143,11 +144,11 @@ void *my_realloc(PSI_memory_key key, void *old_point, size_t size, myf my_flags) DBUG_RETURN(my_malloc(key, size, my_flags)); old_mh= USER_TO_HEADER(old_point); - old_size= old_mh->m_size & ~1; - old_flags= old_mh->m_size & 1; + old_size= old_mh->m_size & ~3; + old_flags= old_mh->m_size & 3; DBUG_ASSERT(old_mh->m_key == key || old_mh->m_key == PSI_NOT_INSTRUMENTED); - DBUG_ASSERT(old_flags == MY_TEST(my_flags & MY_THREAD_SPECIFIC)); + DBUG_ASSERT((old_flags & 1) == MY_TEST(my_flags & MY_THREAD_SPECIFIC)); size= ALIGN_SIZE(size); mh= sf_realloc(old_mh, size + HEADER_SIZE, my_flags); @@ -171,7 +172,8 @@ void *my_realloc(PSI_memory_key key, void *old_point, size_t size, myf my_flags) { mh->m_size= size | old_flags; mh->m_key= PSI_CALL_memory_realloc(key, old_size, size, & mh->m_owner); - update_malloc_size((longlong)size - (longlong)old_size, old_flags); + if (update_malloc_size && (old_flags & 2)) + update_malloc_size((longlong)size - (longlong)old_size, old_flags & 1); point= HEADER_TO_USER(mh); } @@ -197,11 +199,12 @@ void my_free(void *ptr) DBUG_VOID_RETURN; mh= USER_TO_HEADER(ptr); - old_size= mh->m_size & ~1; - old_flags= mh->m_size & 1; + old_size= mh->m_size & ~3; + old_flags= mh->m_size & 3; PSI_CALL_memory_free(mh->m_key, old_size, mh->m_owner); - update_malloc_size(- (longlong) old_size - HEADER_SIZE, old_flags); + if (update_malloc_size && (old_flags & 2)) + update_malloc_size(- (longlong) old_size - HEADER_SIZE, old_flags & 1); #ifndef SAFEMALLOC /* diff --git a/sql/mysqld.cc b/sql/mysqld.cc index d8f16405351..88e1fdab57b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -280,6 +280,12 @@ extern "C" sig_handler handle_fatal_signal(int sig); int init_io_cache_encryption(); +extern "C" +{ + static void my_malloc_size_cb_func(long long size, + my_bool is_thread_specific); +} + /* Constants */ #include // ORACLE_WELCOME_COPYRIGHT_NOTICE diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 6baa82ca963..03bc1bb6eeb 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2988,7 +2988,7 @@ void Show_explain_request::call_in_target_thread() target_thd->set_n_backup_active_arena((Query_arena*)request_thd, &backup_arena); - query_str.copy(target_thd->query(), + query_str.copy(target_thd->query(), target_thd->query_length(), target_thd->query_charset()); @@ -3139,6 +3139,8 @@ int fill_show_explain_or_analyze(THD *thd, TABLE_LIST *table, COND *cond, if ((tmp= find_thread_by_id(thread_id))) { Security_context *tmp_sctx= tmp->security_ctx; + MEM_ROOT explain_mem_root, *save_mem_root; + /* If calling_user==NULL, calling thread has SUPER or PROCESS privilege, and so can do SHOW EXPLAIN/SHOW ANALYZE on any user. @@ -3164,7 +3166,8 @@ int fill_show_explain_or_analyze(THD *thd, TABLE_LIST *table, COND *cond, bool bres; /* Ok we've found the thread of interest and it won't go away because - we're holding its LOCK_thd_kill. Post it a SHOW EXPLAIN/SHOW ANALYZE request. + we're holding its LOCK_thd_kill. Post it a SHOW EXPLAIN/SHOW ANALYZE + request. */ bool timed_out; int timeout_sec= 30; @@ -3172,7 +3175,9 @@ int fill_show_explain_or_analyze(THD *thd, TABLE_LIST *table, COND *cond, explain_req.is_json_format= json_format; select_result_explain_buffer *explain_buf; - explain_buf= new select_result_explain_buffer(thd, table->table); + if (!(explain_buf= new (thd->mem_root) + select_result_explain_buffer(thd, table->table))) + DBUG_RETURN(1); explain_req.is_analyze= is_analyze; explain_req.explain_buf= explain_buf; @@ -3180,8 +3185,19 @@ int fill_show_explain_or_analyze(THD *thd, TABLE_LIST *table, COND *cond, explain_req.request_thd= thd; explain_req.failed_to_produce= FALSE; + /* + Do not use default memroot as this is only to be used by the + target thread (It's marked as thread MY_THREAD_SPECIFIC). + */ + init_sql_alloc(key_memory_thd_main_mem_root, + &explain_mem_root, 0, 8000, MYF(0)); + save_mem_root= thd->mem_root; + thd->mem_root= &explain_mem_root; + /* Ok, we have a lock on target->LOCK_thd_kill, can call: */ - bres= tmp->apc_target.make_apc_call(thd, &explain_req, timeout_sec, &timed_out); + bres= tmp->apc_target.make_apc_call(thd, &explain_req, timeout_sec, + &timed_out); + thd->mem_root= save_mem_root; if (bres || explain_req.failed_to_produce) { @@ -3226,6 +3242,7 @@ int fill_show_explain_or_analyze(THD *thd, TABLE_LIST *table, COND *cond, push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_YES, warning_text); } + free_root(&explain_mem_root, MYF(0)); DBUG_RETURN(bres); } my_error(ER_NO_SUCH_THREAD, MYF(0), (ulong) thread_id); diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index a0ef89ff0f5..beeee9da72f 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -482,6 +482,14 @@ bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) if (lock_table(thd, table_ref, &hton_can_recreate)) DBUG_RETURN(TRUE); + /* + This is mainly here for truncate_notembedded.test, but it is still + useful to check killed after we got the lock + */ + + if (thd->killed) + DBUG_RETURN(TRUE); + if (hton_can_recreate) { /*