MDEV-30936 clang 15.0.7 -fsanitize=memory fails massively
handle_slave_io(), handle_slave_sql(), os_thread_exit(): Remove a redundant pthread_exit(nullptr) call, because it would cause SIGSEGV. mysql_print_status(): Add MEM_MAKE_DEFINED() to work around some missing instrumentation around mallinfo2(). que_graph_free_stat_list(): Invoke que_node_get_next(node) before que_graph_free_recursive(node). That is the logical and MSAN_OPTIONS=poison_in_dtor=1 compatible way of freeing memory. ins_node_t::~ins_node_t(): Invoke mem_heap_free(entry_sys_heap). que_graph_free_recursive(): Rely on ins_node_t::~ins_node_t(). fts_t::~fts_t(): Invoke mem_heap_free(fts_heap). fts_free(): Replace with direct calls to fts_t::~fts_t(). The failures in free_root() due to MSAN_OPTIONS=poison_in_dtor=1 will be covered in MDEV-30942.
This commit is contained in:
parent
a8b616d1e9
commit
dfa90257f6
@ -5060,8 +5060,7 @@ err_during_init:
|
|||||||
DBUG_LEAVE; // Must match DBUG_ENTER()
|
DBUG_LEAVE; // Must match DBUG_ENTER()
|
||||||
my_thread_end();
|
my_thread_end();
|
||||||
ERR_remove_state(0);
|
ERR_remove_state(0);
|
||||||
pthread_exit(0);
|
return nullptr;
|
||||||
return 0; // Avoid compiler warnings
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5766,8 +5765,7 @@ err_during_init:
|
|||||||
DBUG_LEAVE; // Must match DBUG_ENTER()
|
DBUG_LEAVE; // Must match DBUG_ENTER()
|
||||||
my_thread_end();
|
my_thread_end();
|
||||||
ERR_remove_state(0);
|
ERR_remove_state(0);
|
||||||
pthread_exit(0);
|
return nullptr;
|
||||||
return 0; // Avoid compiler warnings
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -623,6 +623,10 @@ Next alarm time: %lu\n",
|
|||||||
#elif defined(HAVE_MALLINFO)
|
#elif defined(HAVE_MALLINFO)
|
||||||
struct mallinfo info= mallinfo();
|
struct mallinfo info= mallinfo();
|
||||||
#endif
|
#endif
|
||||||
|
#if __has_feature(memory_sanitizer)
|
||||||
|
/* Work around missing MSAN instrumentation */
|
||||||
|
MEM_MAKE_DEFINED(&info, sizeof info);
|
||||||
|
#endif
|
||||||
#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
|
#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
|
||||||
char llbuff[10][22];
|
char llbuff[10][22];
|
||||||
printf("\nMemory status:\n\
|
printf("\nMemory status:\n\
|
||||||
|
@ -2465,9 +2465,7 @@ next:
|
|||||||
my_thread_end();
|
my_thread_end();
|
||||||
/* We count the number of threads in os_thread_exit(). A created
|
/* We count the number of threads in os_thread_exit(). A created
|
||||||
thread should always use that to exit and not use return() to exit. */
|
thread should always use that to exit and not use return() to exit. */
|
||||||
os_thread_exit();
|
return os_thread_exit();
|
||||||
|
|
||||||
OS_THREAD_DUMMY_RETURN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initialize page_cleaner. */
|
/** Initialize page_cleaner. */
|
||||||
|
@ -1962,8 +1962,8 @@ void dict_sys_t::remove(dict_table_t* table, bool lru, bool keep)
|
|||||||
#ifdef BTR_CUR_HASH_ADAPT
|
#ifdef BTR_CUR_HASH_ADAPT
|
||||||
if (table->fts) {
|
if (table->fts) {
|
||||||
fts_optimize_remove_table(table);
|
fts_optimize_remove_table(table);
|
||||||
fts_free(table);
|
table->fts->~fts_t();
|
||||||
table->fts = NULL;
|
table->fts = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
table->autoinc_mutex.lock();
|
table->autoinc_mutex.lock();
|
||||||
|
@ -3092,7 +3092,8 @@ func_exit:
|
|||||||
/* the table->fts could be created in dict_load_column
|
/* the table->fts could be created in dict_load_column
|
||||||
when a user defined FTS_DOC_ID is present, but no
|
when a user defined FTS_DOC_ID is present, but no
|
||||||
FTS */
|
FTS */
|
||||||
fts_free(table);
|
table->fts->~fts_t();
|
||||||
|
table->fts = nullptr;
|
||||||
} else if (fts_optimize_wq) {
|
} else if (fts_optimize_wq) {
|
||||||
fts_optimize_add_table(table);
|
fts_optimize_add_table(table);
|
||||||
} else if (table->can_be_evicted) {
|
} else if (table->can_be_evicted) {
|
||||||
|
@ -224,7 +224,7 @@ dict_mem_table_free(
|
|||||||
|| DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
|
|| DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
|
||||||
|| DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_ADD_DOC_ID)) {
|
|| DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_ADD_DOC_ID)) {
|
||||||
if (table->fts) {
|
if (table->fts) {
|
||||||
fts_free(table);
|
table->fts->~fts_t();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2240,9 +2240,7 @@ DECLARE_THREAD(fil_crypt_thread)(void*)
|
|||||||
/* We count the number of threads in os_thread_exit(). A created
|
/* We count the number of threads in os_thread_exit(). A created
|
||||||
thread should always use that to exit and not use return() to exit. */
|
thread should always use that to exit and not use return() to exit. */
|
||||||
|
|
||||||
os_thread_exit();
|
return os_thread_exit();
|
||||||
|
|
||||||
OS_THREAD_DUMMY_RETURN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
|
@ -833,7 +833,8 @@ void fts_clear_all(dict_table_t *table, trx_t *trx)
|
|||||||
fts_optimize_remove_table(table);
|
fts_optimize_remove_table(table);
|
||||||
|
|
||||||
fts_drop_tables(trx, table);
|
fts_drop_tables(trx, table);
|
||||||
fts_free(table);
|
table->fts->~fts_t();
|
||||||
|
table->fts= nullptr;
|
||||||
DICT_TF2_FLAG_UNSET(table, DICT_TF2_FTS);
|
DICT_TF2_FLAG_UNSET(table, DICT_TF2_FTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5350,14 +5351,14 @@ fts_t::~fts_t()
|
|||||||
{
|
{
|
||||||
ut_ad(add_wq == NULL);
|
ut_ad(add_wq == NULL);
|
||||||
|
|
||||||
if (cache != NULL) {
|
if (cache) {
|
||||||
fts_cache_clear(cache);
|
fts_cache_clear(cache);
|
||||||
fts_cache_destroy(cache);
|
fts_cache_destroy(cache);
|
||||||
cache = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* There is no need to call ib_vector_free() on this->indexes
|
/* There is no need to call ib_vector_free() on this->indexes
|
||||||
because it is stored in this->fts_heap. */
|
because it is stored in this->fts_heap. */
|
||||||
|
mem_heap_free(fts_heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
@ -5380,22 +5381,6 @@ fts_create(
|
|||||||
return(fts);
|
return(fts);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
|
||||||
Free the FTS resources. */
|
|
||||||
void
|
|
||||||
fts_free(
|
|
||||||
/*=====*/
|
|
||||||
dict_table_t* table) /*!< in/out: table with FTS indexes */
|
|
||||||
{
|
|
||||||
fts_t* fts = table->fts;
|
|
||||||
|
|
||||||
fts->~fts_t();
|
|
||||||
|
|
||||||
mem_heap_free(fts->fts_heap);
|
|
||||||
|
|
||||||
table->fts = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
Take a FTS savepoint. */
|
Take a FTS savepoint. */
|
||||||
UNIV_INLINE
|
UNIV_INLINE
|
||||||
|
@ -12622,7 +12622,8 @@ int create_table_info_t::create_table(bool create_fk)
|
|||||||
m_table->name.m_name);
|
m_table->name.m_name);
|
||||||
|
|
||||||
if (m_table->fts) {
|
if (m_table->fts) {
|
||||||
fts_free(m_table);
|
m_table->fts->~fts_t();
|
||||||
|
m_table->fts = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
|
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
|
||||||
|
@ -1028,7 +1028,8 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
|
|||||||
old_v_cols[i].~dict_v_col_t();
|
old_v_cols[i].~dict_v_col_t();
|
||||||
}
|
}
|
||||||
if (instant_table->fts) {
|
if (instant_table->fts) {
|
||||||
fts_free(instant_table);
|
instant_table->fts->~fts_t();
|
||||||
|
instant_table->fts = nullptr;
|
||||||
}
|
}
|
||||||
dict_mem_table_free(instant_table);
|
dict_mem_table_free(instant_table);
|
||||||
}
|
}
|
||||||
@ -8753,7 +8754,8 @@ innobase_rollback_sec_index(
|
|||||||
&& !DICT_TF2_FLAG_IS_SET(user_table,
|
&& !DICT_TF2_FLAG_IS_SET(user_table,
|
||||||
DICT_TF2_FTS_HAS_DOC_ID)
|
DICT_TF2_FTS_HAS_DOC_ID)
|
||||||
&& !innobase_fulltext_exist(table)) {
|
&& !innobase_fulltext_exist(table)) {
|
||||||
fts_free(user_table);
|
user_table->fts->~fts_t();
|
||||||
|
user_table->fts = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,14 +607,6 @@ fts_create(
|
|||||||
dict_table_t* table); /*!< out: table with FTS
|
dict_table_t* table); /*!< out: table with FTS
|
||||||
indexes */
|
indexes */
|
||||||
|
|
||||||
/**********************************************************************//**
|
|
||||||
Free the FTS resources. */
|
|
||||||
void
|
|
||||||
fts_free(
|
|
||||||
/*=====*/
|
|
||||||
dict_table_t* table); /*!< in/out: table with
|
|
||||||
FTS indexes */
|
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
Run OPTIMIZE on the given table.
|
Run OPTIMIZE on the given table.
|
||||||
@return DB_SUCCESS if all OK */
|
@return DB_SUCCESS if all OK */
|
||||||
|
@ -86,7 +86,7 @@ We do not return an error code because if there is one, we crash here. */
|
|||||||
os_thread_t os_thread_create(os_thread_func_t func, void *arg= nullptr);
|
os_thread_t os_thread_create(os_thread_func_t func, void *arg= nullptr);
|
||||||
|
|
||||||
/** Detach and terminate the current thread. */
|
/** Detach and terminate the current thread. */
|
||||||
ATTRIBUTE_NORETURN void os_thread_exit();
|
os_thread_ret_t os_thread_exit();
|
||||||
|
|
||||||
/*****************************************************************//**
|
/*****************************************************************//**
|
||||||
The thread sleeps at least the time given in microseconds. */
|
The thread sleeps at least the time given in microseconds. */
|
||||||
|
@ -177,6 +177,7 @@ struct ins_node_t
|
|||||||
trx_id(0), entry_sys_heap(mem_heap_create(128))
|
trx_id(0), entry_sys_heap(mem_heap_create(128))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
~ins_node_t() { mem_heap_free(entry_sys_heap); }
|
||||||
que_common_t common; /*!< node type: QUE_NODE_INSERT */
|
que_common_t common; /*!< node type: QUE_NODE_INSERT */
|
||||||
ulint ins_type;/* INS_VALUES, INS_SEARCHED, or INS_DIRECT */
|
ulint ins_type;/* INS_VALUES, INS_SEARCHED, or INS_DIRECT */
|
||||||
dtuple_t* row; /*!< row to insert */
|
dtuple_t* row; /*!< row to insert */
|
||||||
|
@ -86,7 +86,7 @@ os_thread_t os_thread_create(os_thread_func_t func, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Detach and terminate the current thread. */
|
/** Detach and terminate the current thread. */
|
||||||
ATTRIBUTE_NORETURN void os_thread_exit()
|
os_thread_ret_t os_thread_exit()
|
||||||
{
|
{
|
||||||
#ifdef UNIV_DEBUG_THREAD_CREATION
|
#ifdef UNIV_DEBUG_THREAD_CREATION
|
||||||
ib::info() << "Thread exits, id " << os_thread_get_curr_id();
|
ib::info() << "Thread exits, id " << os_thread_get_curr_id();
|
||||||
@ -100,8 +100,8 @@ ATTRIBUTE_NORETURN void os_thread_exit()
|
|||||||
ExitThread(0);
|
ExitThread(0);
|
||||||
#else
|
#else
|
||||||
pthread_detach(pthread_self());
|
pthread_detach(pthread_self());
|
||||||
pthread_exit(NULL);
|
|
||||||
#endif
|
#endif
|
||||||
|
OS_THREAD_DUMMY_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************//**
|
/*****************************************************************//**
|
||||||
|
@ -360,9 +360,9 @@ que_graph_free_stat_list(
|
|||||||
que_node_t* node) /*!< in: first query graph node in the list */
|
que_node_t* node) /*!< in: first query graph node in the list */
|
||||||
{
|
{
|
||||||
while (node) {
|
while (node) {
|
||||||
|
que_node_t* next = que_node_get_next(node);
|
||||||
que_graph_free_recursive(node);
|
que_graph_free_recursive(node);
|
||||||
|
node = next;
|
||||||
node = que_node_get_next(node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,19 +421,10 @@ que_graph_free_recursive(
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case QUE_NODE_INSERT:
|
case QUE_NODE_INSERT:
|
||||||
|
|
||||||
ins = static_cast<ins_node_t*>(node);
|
ins = static_cast<ins_node_t*>(node);
|
||||||
|
|
||||||
que_graph_free_recursive(ins->select);
|
que_graph_free_recursive(ins->select);
|
||||||
ins->select = NULL;
|
|
||||||
|
|
||||||
ins->~ins_node_t();
|
ins->~ins_node_t();
|
||||||
|
|
||||||
if (ins->entry_sys_heap != NULL) {
|
|
||||||
mem_heap_free(ins->entry_sys_heap);
|
|
||||||
ins->entry_sys_heap = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case QUE_NODE_PURGE:
|
case QUE_NODE_PURGE:
|
||||||
purge = static_cast<purge_node_t*>(node);
|
purge = static_cast<purge_node_t*>(node);
|
||||||
|
@ -3225,8 +3225,8 @@ row_drop_ancillary_fts_tables(
|
|||||||
/* fts_que_graph_free_check_lock would try to acquire
|
/* fts_que_graph_free_check_lock would try to acquire
|
||||||
dict mutex lock */
|
dict mutex lock */
|
||||||
table->fts->dict_locked = true;
|
table->fts->dict_locked = true;
|
||||||
|
table->fts->~fts_t();
|
||||||
fts_free(table);
|
table->fts = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(DB_SUCCESS);
|
return(DB_SUCCESS);
|
||||||
|
@ -845,9 +845,7 @@ DECLARE_THREAD(trx_rollback_all_recovered)(void*)
|
|||||||
/* We count the number of threads in os_thread_exit(). A created
|
/* We count the number of threads in os_thread_exit(). A created
|
||||||
thread should always use that to exit and not use return() to exit. */
|
thread should always use that to exit and not use return() to exit. */
|
||||||
|
|
||||||
os_thread_exit();
|
return os_thread_exit();
|
||||||
|
|
||||||
OS_THREAD_DUMMY_RETURN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************//**
|
/****************************************************************//**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user