BUG#24009272 SEGFAULT WITH CREATE+SELECT FROM IS+DROP FTS TABLE CONCURRENTLY

Analysis:
When we access fts_internal_tbl_name in i_s_fts_config_fill (),
it can be set to NULL by another session.

Solution:
Define fts_internal_tbl_name2 for global variable innodb_ft_aux_table,
if it's NULL, set fts_internal_tbl_name to "default".

Reviewed-by: Jimmy Yang <jimmy.yang@oracle.com>
RB: 13401
This commit is contained in:
Shaohua Wang 2016-07-27 03:43:52 +02:00 committed by Marko Mäkelä
parent 4b5a9d8e0f
commit 9ce1ea6f51
4 changed files with 42 additions and 3 deletions

View file

@ -93,6 +93,7 @@ static const ulint FTS_DEADLOCK_RETRY_WAIT = 100000;
/** variable to record innodb_fts_internal_tbl_name for information
schema table INNODB_FTS_INSERTED etc. */
char* fts_internal_tbl_name = NULL;
char* fts_internal_tbl_name2 = NULL;
/** InnoDB default stopword list:
There are different versions of stopwords, the stop words listed

View file

@ -18773,6 +18773,41 @@ innodb_internal_table_validate(
}
#ifdef BTR_CUR_HASH_ADAPT
/****************************************************************//**
Update global variable "fts_internal_tbl_name" with the "saved"
stopword table name value. This function is registered as a callback
with MySQL. */
static
void
innodb_internal_table_update(
/*=========================*/
THD* thd, /*!< in: thread handle */
struct st_mysql_sys_var* var, /*!< in: pointer to
system variable */
void* var_ptr,/*!< out: where the
formal string goes */
const void* save) /*!< in: immediate result
from check function */
{
const char* table_name;
char* old;
ut_a(save != NULL);
ut_a(var_ptr != NULL);
table_name = *static_cast<const char*const*>(save);
old = *(char**) var_ptr;
*(char**) var_ptr = table_name ? my_strdup(table_name, MYF(0)) : NULL;
my_free(old);
fts_internal_tbl_name2 = *(char**) var_ptr;
if (fts_internal_tbl_name2 == NULL) {
fts_internal_tbl_name = const_cast<char*>("default");
} else {
fts_internal_tbl_name = fts_internal_tbl_name2;
}
}
/****************************************************************//**
Update the system variable innodb_adaptive_hash_index using the "saved"
value. This function is registered as a callback with MySQL. */
@ -21226,11 +21261,11 @@ static MYSQL_SYSVAR_BOOL(disable_sort_file_cache, srv_disable_sort_file_cache,
"Whether to disable OS system file cache for sort I/O",
NULL, NULL, FALSE);
static MYSQL_SYSVAR_STR(ft_aux_table, fts_internal_tbl_name,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
static MYSQL_SYSVAR_STR(ft_aux_table, fts_internal_tbl_name2,
PLUGIN_VAR_RQCMDARG,
"FTS internal auxiliary table to be checked",
innodb_internal_table_validate,
NULL, NULL);
innodb_internal_table_update, NULL);
static MYSQL_SYSVAR_ULONG(ft_cache_size, fts_max_cache_size,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,

View file

@ -3955,6 +3955,8 @@ i_s_fts_config_fill(
DBUG_RETURN(0);
}
DEBUG_SYNC_C("i_s_fts_config_fille_check");
fields = table->field;
/* Prevent DDL to drop fts aux tables. */

View file

@ -409,6 +409,7 @@ extern bool fts_need_sync;
/** Variable specifying the table that has Fulltext index to display its
content through information schema table */
extern char* fts_internal_tbl_name;
extern char* fts_internal_tbl_name2;
#define fts_que_graph_free(graph) \
do { \