mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
MDEV-40004: Server crashes in sp_head::register_instr_mem_root_for_deallocation upon shutdown
n shutdown server could crash in case triggers executed during server run and some of triggers instructions were re-compiled. The crash is caused by attempt to allocate a memory for storing pointers on mem_roots used for memory allocation taken place on re-parsing failing trigger's statements. The reason of crash is dereferencing of nullptr returning by the function current_thd(). To fix the issue, use dummy THD on shutdown the table definition cache. tdc_start_shutdown() is solely invoked from the function clean_up() but the later is called from many places around the source code, not only from mysql_main(), particularly clean_up() is called from unireg_abort(). Therefore, the extra argument added into the signature of the function cleanup() to allow explicit request of use dummy THD on shutdown the table definition cache.
This commit is contained in:
@@ -2122,6 +2122,23 @@ i
|
||||
2
|
||||
1
|
||||
1
|
||||
DROP TEMPORARY TABLE t1;
|
||||
DROP PACKAGE BODY pkg1;
|
||||
DROP PACKAGE pkg1;
|
||||
SET sql_mode=@save_sql_mode;
|
||||
#
|
||||
# MDEV-40004: Server crashes in sp_head::register_instr_mem_root_for_deallocation upon shutdown
|
||||
#
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
CREATE TRIGGER tr BEFORE UPDATE ON t1 FOR EACH ROW DELETE FROM v1;
|
||||
CREATE VIEW v1 AS SELECT 0 AS a;
|
||||
UPDATE t1 SET a = 3;
|
||||
ERROR HY000: The target table v1 of the DELETE is not updatable
|
||||
CREATE OR REPLACE VIEW v1 AS SELECT 0 AS a;
|
||||
UPDATE t1 SET a = 4;
|
||||
ERROR HY000: The target table v1 of the DELETE is not updatable
|
||||
# restart
|
||||
# Clean up
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
|
||||
@@ -2923,9 +2923,33 @@ $
|
||||
--delimiter ;
|
||||
CALL pkg1.p2();
|
||||
|
||||
DROP TEMPORARY TABLE t1;
|
||||
DROP PACKAGE BODY pkg1;
|
||||
DROP PACKAGE pkg1;
|
||||
|
||||
SET sql_mode=@save_sql_mode;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-40004: Server crashes in sp_head::register_instr_mem_root_for_deallocation upon shutdown
|
||||
--echo #
|
||||
CREATE TABLE t1 (a INT);
|
||||
|
||||
INSERT INTO t1 VALUES (1),(2);
|
||||
CREATE TRIGGER tr BEFORE UPDATE ON t1 FOR EACH ROW DELETE FROM v1;
|
||||
CREATE VIEW v1 AS SELECT 0 AS a;
|
||||
|
||||
--error ER_NON_UPDATABLE_TABLE
|
||||
UPDATE t1 SET a = 3;
|
||||
|
||||
CREATE OR REPLACE VIEW v1 AS SELECT 0 AS a;
|
||||
|
||||
--error ER_NON_UPDATABLE_TABLE
|
||||
UPDATE t1 SET a = 4;
|
||||
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
--echo # Clean up
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--enable_ps2_protocol
|
||||
|
||||
@@ -1565,7 +1565,7 @@ void handle_connections_sockets();
|
||||
|
||||
static bool read_init_file(char *file_name);
|
||||
pthread_handler_t handle_slave(void *arg);
|
||||
static void clean_up(bool print_message);
|
||||
static void clean_up(bool print_message, bool use_dummy_thd= false);
|
||||
static int test_if_case_insensitive(const char *dir_name);
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
@@ -1974,7 +1974,7 @@ static void mysqld_exit(int exit_code)
|
||||
|
||||
#endif /* !EMBEDDED_LIBRARY */
|
||||
|
||||
static void clean_up(bool print_message)
|
||||
static void clean_up(bool print_message, bool use_dummy_thd)
|
||||
{
|
||||
DBUG_PRINT("exit",("clean_up"));
|
||||
if (cleanup_done++)
|
||||
@@ -2009,7 +2009,7 @@ static void clean_up(bool print_message)
|
||||
lex_free(); /* Free some memory */
|
||||
item_create_cleanup();
|
||||
cleanup_json_schema_keyword_hash();
|
||||
tdc_start_shutdown();
|
||||
tdc_start_shutdown(use_dummy_thd);
|
||||
#ifdef HAVE_REPLICATION
|
||||
semi_sync_master_deinit();
|
||||
#endif
|
||||
@@ -6164,7 +6164,7 @@ int mysqld_main(int argc, char **argv)
|
||||
|
||||
close_connections();
|
||||
ha_pre_shutdown();
|
||||
clean_up(1);
|
||||
clean_up(1, true);
|
||||
sd_notify(0, "STATUS=MariaDB server is down");
|
||||
|
||||
/* (void) pthread_attr_destroy(&connection_attrib); */
|
||||
|
||||
@@ -632,7 +632,7 @@ bool tdc_init(void)
|
||||
minimal in order to reduce number of references to pluggable engines.
|
||||
*/
|
||||
|
||||
void tdc_start_shutdown(void)
|
||||
void tdc_start_shutdown(bool use_dummy_thd)
|
||||
{
|
||||
DBUG_ENTER("tdc_start_shutdown");
|
||||
if (tdc_inited)
|
||||
@@ -645,8 +645,50 @@ void tdc_start_shutdown(void)
|
||||
*/
|
||||
tdc_size= 0;
|
||||
tc_size= 0;
|
||||
|
||||
THD *thd= nullptr;
|
||||
bool reset_back_current_thd= false;
|
||||
|
||||
if (use_dummy_thd && _current_thd() == nullptr)
|
||||
{
|
||||
/*
|
||||
There is no active THD, use the surrogate one to handle memory
|
||||
allocations in Sql_alloc::operator new() that uses current_thd()
|
||||
for getting THD to get access to memory allocation API
|
||||
*/
|
||||
thd= new THD(0);
|
||||
DBUG_ASSERT(thd != nullptr);
|
||||
|
||||
thd->store_globals();
|
||||
thd->init();
|
||||
thd->set_query_inner((char*) STRING_WITH_LEN("intern:tdc_start_shutdown"),
|
||||
default_charset_info);
|
||||
|
||||
reset_back_current_thd= true;
|
||||
}
|
||||
/* Free all cached but unused TABLEs and TABLE_SHAREs. */
|
||||
/*
|
||||
purge_tables() iterates along opened tables close every one of them.
|
||||
In case tables use triggers it results in destroying sp_head objects
|
||||
for every associated trigger. Destroying an object of the sp_head class
|
||||
leads to deleting sp_instr objects. In case some of SP instruction
|
||||
were previously re-parsed by the reason of changes in tables metadata,
|
||||
the method
|
||||
sp_head::register_instr_mem_root_for_deallocation()
|
||||
is called to add a memory root used for re-parsing to the list of
|
||||
mem_roots to be freed on sp_head destruction. Mem_roots for later
|
||||
destruction are placed on the List that use current_thd() for memory
|
||||
allocation. That is the reason why the dummy THD is created before
|
||||
in case there is no active THD at the moment the function
|
||||
tdc_start_shutdown is invoked.
|
||||
*/
|
||||
purge_tables();
|
||||
|
||||
if (reset_back_current_thd)
|
||||
{
|
||||
thd->reset_globals();
|
||||
delete thd;
|
||||
}
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ extern ulong tc_size;
|
||||
extern uint32 tc_instances;
|
||||
|
||||
extern bool tdc_init(void);
|
||||
extern void tdc_start_shutdown(void);
|
||||
extern void tdc_start_shutdown(bool use_dummy_thd);
|
||||
extern void tdc_deinit(void);
|
||||
extern ulong tdc_records(void);
|
||||
extern void tdc_purge(bool all);
|
||||
|
||||
Reference in New Issue
Block a user