From be694384d41d33934eb36cb0b722c3ac109d04d0 Mon Sep 17 00:00:00 2001 From: hsser Date: Sat, 16 Dec 2023 21:54:01 -0800 Subject: [PATCH 1/4] MDEV-31925 Fix for File Leak in mysql_upgrade with --check-if-upgrade-is-needed Option This commit addresses the file leakage problem encountered with the mysql_upgrade --check-if-upgrade-is-needed command. --- client/mysql_upgrade.c | 7 +++++- .../main/mysql_upgrade_file_leak.result | 4 ++++ mysql-test/main/mysql_upgrade_file_leak.test | 24 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 mysql-test/main/mysql_upgrade_file_leak.result create mode 100644 mysql-test/main/mysql_upgrade_file_leak.test diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index ea18c1c5ba7..70e2d341c5b 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -1374,7 +1374,12 @@ int main(int argc, char **argv) open_mysql_upgrade_file(); if (opt_check_upgrade) - exit(upgrade_already_done(0) == 0); + { + int upgrade_needed = upgrade_already_done(0); + free_used_memory(); + my_end(my_end_arg); + exit(upgrade_needed == 0); + } /* Find mysqlcheck */ find_tool(mysqlcheck_path, IF_WIN("mysqlcheck.exe", "mysqlcheck"), self_name); diff --git a/mysql-test/main/mysql_upgrade_file_leak.result b/mysql-test/main/mysql_upgrade_file_leak.result new file mode 100644 index 00000000000..648a0c97802 --- /dev/null +++ b/mysql-test/main/mysql_upgrade_file_leak.result @@ -0,0 +1,4 @@ +Running mysql_upgrade with --check-if-upgrade-is-needed +Checking for absence of temporary files by mysql_upgrade +No temporary files found +End of 10.4 tests diff --git a/mysql-test/main/mysql_upgrade_file_leak.test b/mysql-test/main/mysql_upgrade_file_leak.test new file mode 100644 index 00000000000..44f178322b4 --- /dev/null +++ b/mysql-test/main/mysql_upgrade_file_leak.test @@ -0,0 +1,24 @@ +-- source include/mysql_upgrade_preparation.inc + +# +# MDEV-31925 mysqld_upgrade --check-if-upgrade-is-needed leaks files +# + +# Run mysql_upgrade with --check-if-upgrade-is-needed +--echo Running mysql_upgrade with --check-if-upgrade-is-needed +--exec $MYSQL_UPGRADE --check-if-upgrade-is-needed 2>&1 + +# Check if temporary files related to mysql_upgrade are cleared +--echo Checking for absence of temporary files by mysql_upgrade +--perl + +# Use the temporary directory path from the MySQL configuration +my $tmpdir = "$ENV{MYSQL_TMP_DIR}"; + +die "Test failed: Found temporary file left by mysql_upgrade\n" if (glob("$tmpdir/mysql_upgrade-*")); +print "No temporary files found\n"; +EOF + +let $MYSQLD_DATADIR= `select @@datadir`; +--remove_file $MYSQLD_DATADIR/mysql_upgrade_info +--echo End of 10.4 tests From a204ce2788987a611bb3b6798afdc7f4f2553556 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sun, 17 Dec 2023 13:57:26 +0100 Subject: [PATCH 2/4] MDEV-33045: Server crashes in Item_func_binlog_gtid_pos::val_str / Binary_string::c_ptr_safe Item::val_str() sets the Item::null_value flag, so call it before checking the flag, not after. Signed-off-by: Kristian Nielsen --- mysql-test/suite/binlog_encryption/rpl_gtid_basic.result | 7 +++++++ mysql-test/suite/rpl/r/rpl_gtid_basic.result | 7 +++++++ mysql-test/suite/rpl/t/rpl_gtid_basic.test | 7 +++++++ sql/item_strfunc.cc | 6 +++--- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/binlog_encryption/rpl_gtid_basic.result b/mysql-test/suite/binlog_encryption/rpl_gtid_basic.result index 5771b0f405f..99721813159 100644 --- a/mysql-test/suite/binlog_encryption/rpl_gtid_basic.result +++ b/mysql-test/suite/binlog_encryption/rpl_gtid_basic.result @@ -182,6 +182,13 @@ BINLOG_GTID_POS('master-bin.000001',18446744073709551616) NULL Warnings: Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated +SET sql_log_bin= 0; +CREATE TABLE t1 AS SELECT MASTER_POS_WAIT(@binlog_file, 4, 0); +SELECT BINLOG_GTID_POS(@binlog_file, 4); +BINLOG_GTID_POS(@binlog_file, 4) +NULL +DROP TABLE t1; +SET sql_log_bin= 1; *** Some tests of @@GLOBAL.gtid_binlog_state *** connection server_2; include/sync_with_master_gtid.inc diff --git a/mysql-test/suite/rpl/r/rpl_gtid_basic.result b/mysql-test/suite/rpl/r/rpl_gtid_basic.result index aefb80a7c13..afc700a72c5 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_basic.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_basic.result @@ -182,6 +182,13 @@ BINLOG_GTID_POS('master-bin.000001',18446744073709551616) NULL Warnings: Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated +SET sql_log_bin= 0; +CREATE TABLE t1 AS SELECT MASTER_POS_WAIT(@binlog_file, 4, 0); +SELECT BINLOG_GTID_POS(@binlog_file, 4); +BINLOG_GTID_POS(@binlog_file, 4) +NULL +DROP TABLE t1; +SET sql_log_bin= 1; *** Some tests of @@GLOBAL.gtid_binlog_state *** connection server_2; include/sync_with_master_gtid.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_basic.test b/mysql-test/suite/rpl/t/rpl_gtid_basic.test index 70bd0087f7a..a7af234d47e 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_basic.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.test @@ -162,6 +162,13 @@ eval SELECT BINLOG_GTID_POS('$valid_binlog_name',0); eval SELECT BINLOG_GTID_POS('$valid_binlog_name',18446744073709551615); eval SELECT BINLOG_GTID_POS('$valid_binlog_name',18446744073709551616); +# MDEV-33045: Server crashes in Item_func_binlog_gtid_pos::val_str / Binary_string::c_ptr_safe +SET sql_log_bin= 0; +CREATE TABLE t1 AS SELECT MASTER_POS_WAIT(@binlog_file, 4, 0); +SELECT BINLOG_GTID_POS(@binlog_file, 4); +DROP TABLE t1; +SET sql_log_bin= 1; + --echo *** Some tests of @@GLOBAL.gtid_binlog_state *** --connection server_2 diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 92d5e196da4..0373d2a94a6 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -3232,12 +3232,12 @@ String *Item_func_binlog_gtid_pos::val_str(String *str) String name_str, *name; longlong pos; - if (args[0]->null_value || args[1]->null_value) - goto err; - name= args[0]->val_str(&name_str); pos= args[1]->val_int(); + if (args[0]->null_value || args[1]->null_value) + goto err; + if (pos < 0 || pos > UINT_MAX32) goto err; From 1cbba45e6ed1dd4f08614198f9596ef828a8ada4 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sun, 17 Dec 2023 18:30:38 +0100 Subject: [PATCH 3/4] Attempt to fix rare race in test for MDEV-8031 The error-injection inject_mdev8031 simulates a deadlock kill in a specific place, by setting killed_for_retry to RETRY_KILL_KILLED directly. If a real deadlock kill triggers at the same time, it is possible for the thread to complete its transaction retry and set rgi_slave to NULL before the real readlock kill can complete in the background. This will cause a segfault due to null-pointer access. Fix by changing the error injection to do a real background deadlock kill, which ensures that the thread will wait for any pending background kills to complete. Signed-off-by: Kristian Nielsen --- sql/rpl_parallel.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index 397b45c4eef..d9ff07fa740 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -856,8 +856,7 @@ do_retry: thd->wait_for_commit_ptr->unregister_wait_for_prior_commit(); DBUG_EXECUTE_IF("inject_mdev8031", { /* Simulate that we get deadlock killed at this exact point. */ - rgi->killed_for_retry= rpl_group_info::RETRY_KILL_KILLED; - thd->set_killed(KILL_CONNECTION); + slave_background_kill_request(thd); }); #ifdef ENABLED_DEBUG_SYNC DBUG_EXECUTE_IF("rpl_parallel_simulate_wait_at_retry", { From eaa4968fc564444ce9c8803da87f685fb182b447 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sun, 17 Dec 2023 18:35:14 +0100 Subject: [PATCH 4/4] MDEV-10653: Fix segfault in SHOW MASTER STATUS with NULL inuse_relaylog The previous patch for MDEV-10653 changes the rpl_parallel::workers_idle() function to use Relay_log_info::last_inuse_relaylog to check for idle workers. But the code was missing a NULL check. Also, there was one place during SQL slave thread start which was missing mutex synchronisation when updating inuse_relaylog. Signed-off-by: Kristian Nielsen --- sql/rpl_parallel.cc | 6 ++++-- sql/slave.cc | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/sql/rpl_parallel.cc b/sql/rpl_parallel.cc index d9ff07fa740..ac96d92eb5d 100644 --- a/sql/rpl_parallel.cc +++ b/sql/rpl_parallel.cc @@ -2538,8 +2538,10 @@ rpl_parallel::stop_during_until() bool rpl_parallel::workers_idle(Relay_log_info *rli) { - return rli->last_inuse_relaylog->queued_count == - rli->last_inuse_relaylog->dequeued_count; + mysql_mutex_assert_owner(&rli->data_lock); + return !rli->last_inuse_relaylog || + rli->last_inuse_relaylog->queued_count == + rli->last_inuse_relaylog->dequeued_count; } diff --git a/sql/slave.cc b/sql/slave.cc index 2cc11b9ed42..f4d76e447cd 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -5369,19 +5369,25 @@ pthread_handler_t handle_slave_sql(void *arg) } else rli->gtid_skip_flag = GTID_SKIP_NOT; + mysql_mutex_lock(&rli->data_lock); if (init_relay_log_pos(rli, rli->group_relay_log_name, rli->group_relay_log_pos, - 1 /*need data lock*/, &errmsg, + 0 /*need data lock*/, &errmsg, 1 /*look for a description_event*/)) { rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, NULL, "Error initializing relay log position: %s", errmsg); + mysql_mutex_unlock(&rli->data_lock); goto err_before_start; } rli->reset_inuse_relaylog(); if (rli->alloc_inuse_relaylog(rli->group_relay_log_name)) + { + mysql_mutex_unlock(&rli->data_lock); goto err_before_start; + } + mysql_mutex_unlock(&rli->data_lock); strcpy(rli->future_event_master_log_name, rli->group_master_log_name); THD_CHECK_SENTRY(thd);