From 82964737c007bafad28cd45829874eb98593127a Mon Sep 17 00:00:00 2001 From: forkfun Date: Mon, 5 Oct 2026 17:07:05 +0200 Subject: [PATCH] MDEV-31527 Flush buffered early messages on early exit Buffered_logs::flush() prints and frees the buffered early-option messages. Call it on every early exit, so warnings and errors are not lost and the buffer is not leaked. Make the early-option error exit in mysqld_main() unconditional. Without the performance schema, a failed early option parse left "----file-marker----" in argv, and it was reported as an unknown option. Index.xml parse errors go through error_handler_hook, not vprint_msg_to_log(), so --validate-config reported "Configuration is valid." Install a hook that sets validate_config_has_warnings. Test cleanup. --- mysql-test/main/validate_config.inc | 63 ++++ mysql-test/main/validate_config.result | 227 +++++++----- mysql-test/main/validate_config.test | 484 +++++++++++++------------ sql/log.cc | 4 + sql/mysqld.cc | 58 ++- 5 files changed, 513 insertions(+), 323 deletions(-) create mode 100644 mysql-test/main/validate_config.inc diff --git a/mysql-test/main/validate_config.inc b/mysql-test/main/validate_config.inc new file mode 100644 index 00000000000..309bfed6cdf --- /dev/null +++ b/mysql-test/main/validate_config.inc @@ -0,0 +1,63 @@ +# ==== Purpose ==== +# +# Run a server command, check its exit code and show or check its output +# (stdout and stderr merged). +# +# ==== Usage ==== +# +# --let $vc_args= --no-defaults --validate-config +# [--let $vc_cmd= $MYSQLD_BOOTSTRAP_CMD] +# [--let $vc_rc= 2] +# [--let $vc_brief= 1] +# [--let $vc_expect= Starts the MariaDB database server] +# --source validate_config.inc +# +# Parameters: +# $vc_args +# Command line arguments. +# +# $vc_cmd +# The command to run, default $MYSQLD. +# +# $vc_rc +# The expected exit code, default 0. +# +# $vc_brief +# 0 (default): print the whole output. +# 1: for long output (--help, --version) only check that $vc_expect +# is found and $vc_absent is not. +# +# $vc_expect, $vc_absent +# Patterns for $vc_brief=1. +# +# $vc_rc, $vc_cmd and $vc_brief are set back to the defaults afterwards. + +--let $_vc_log= $MYSQLTEST_VARDIR/tmp/validate_config.log + +--error $vc_rc +--exec $vc_cmd $vc_args >$_vc_log 2>&1 + +if ($vc_brief) +{ + --let SEARCH_FILE= $_vc_log + --let SEARCH_PATTERN= $vc_expect + --source include/search_pattern_in_file.inc + + --let SEARCH_PATTERN= $vc_absent + --let SEARCH_ABORT= FOUND + --source include/search_pattern_in_file.inc + --let SEARCH_ABORT= +} +if (!$vc_brief) +{ + # Remove what differs between runs and platforms: the vardir, timestamps + # and thread id, the server name and the Index.xml path + --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR + --replace_regex /[0-9]+-[0-9]+-[0-9]+ +[0-9:]+ 0 // /(\S*[\\\/])?(mysqld|mariadbd)(\.exe)?: /mysqld: / /'[^']*Index\.xml'/'Index.xml'/ + --cat_file $_vc_log +} +--remove_file $_vc_log + +--let $vc_rc= 0 +--let $vc_cmd= $MYSQLD +--let $vc_brief= 0 diff --git a/mysql-test/main/validate_config.result b/mysql-test/main/validate_config.result index 251d54fd031..a34acb05d6f 100644 --- a/mysql-test/main/validate_config.result +++ b/mysql-test/main/validate_config.result @@ -1,100 +1,153 @@ # -# Test 1: --validate-config with valid configuration should succeed (exit 0) +# MDEV-31527: Add --validate-config option to check configuration +# without starting the server # -FOUND 1 /Configuration is valid\./ in mdev-31527-test1.log # -# Test 2: --validate-config with unknown option should fail (exit 2) +# 1. Valid configuration: only "Configuration is valid." is printed # -FOUND 1 /unknown option '--nonexistentoption'/ in mdev-31527-test2.log +Configuration is valid. +# MTR bootstrap command: only "Configuration is valid." +Configuration is valid. +# --verbose, --silent-startup: only "Configuration is valid." +Configuration is valid. +Configuration is valid. +# "Configuration is valid." goes to stdout, stderr is empty +# stdout: +Configuration is valid. +# stderr: +# valid value in a config file: only "Configuration is valid." +Configuration is valid. # -# Test 3: --validate-config should not start the server (no pid file created) +# 2. Valid configuration with warnings: the warnings, then +# "Configuration is valid, but warnings were reported; see above." # -FOUND 1 /Configuration is valid\./ in mdev-31527-test3.log +# values adjusted in a config file, [mysqld] and [server] groups: +# two warnings, then "warnings were reported" +[Warning] option 'sort_buffer_size': unsigned value 1 adjusted to 1024 +[Warning] Buffered warning: option 'max_connections': unsigned value 0 adjusted to 10 +Configuration is valid, but warnings were reported; see above. +# value adjusted on the command line before --validate-config: +# warning, then "warnings were reported" +[Warning] option 'sort_buffer_size': unsigned value 1 adjusted to 1024 +Configuration is valid, but warnings were reported; see above. +# plugin option value adjusted: warning, then "warnings were reported" +[Warning] option 'aria-sort-buffer-size': unsigned value 1 adjusted to 16352 +Configuration is valid, but warnings were reported; see above. +# unknown --loose- option: warning, then "warnings were reported" +[Warning] mysqld: unknown variable 'loose-zzz-bogus=1' +Configuration is valid, but warnings were reported; see above. +# checks made after option parsing: +# warning, then "warnings were reported" +[Warning] TLSv1.0 and TLSv1.1 are insecure and should not be used for tls_version +Configuration is valid, but warnings were reported; see above. +[Warning] Although a general log file was specified, log tables are used. To enable logging to files use the --log-output option. +Configuration is valid, but warnings were reported; see above. +# malformed Index.xml, error printed outside the error log: +# the error, then "warnings were reported" +mysqld: Error while parsing 'Index.xml': at line 2 pos 1: END-OF-INPUT unexpected (ident or '/' wanted) +Configuration is valid, but warnings were reported; see above. # -# Test 4: --validate-config should not produce help output +# 3. Invalid configuration: the error and the exit code, +# no "Configuration is valid." # -NOT FOUND /Starts the MariaDB database server/ in mdev-31527-test4.log +# unknown option, exit code 2: error, no "Configuration is valid" +[ERROR] mysqld: unknown option '--nonexistentoption' +[ERROR] Aborting +# unknown plugin variable, exit code 7: +# error, no "Configuration is valid" +[ERROR] mysqld: unknown variable 'aria-bogus=1' +[ERROR] Aborting +# unknown variable in a config file, exit code 7: +# error, no "Configuration is valid" +[ERROR] mysqld: unknown variable 'zzz_bogus_option=123' +[ERROR] Aborting +# unknown variable in a file pulled in by !include, exit code 7: +# error, no "Configuration is valid" +[ERROR] mysqld: unknown variable 'zzz_bogus_option=123' +[ERROR] Aborting +# max_connections=abc, exit code 9: error, no "Configuration is valid" +[ERROR] Buffered error: Unknown suffix 'a' used for variable 'max_connections' (value 'abc'). Legal suffix characters are: K, M, G, T, P, E +[ERROR] Buffered error: mysqld: Error while setting value 'abc' to 'max_connections' +# max_connections=abc in a config file, exit code 9: +# error, no "Configuration is valid" +[ERROR] Buffered error: Unknown suffix 'a' used for variable 'max_connections' (value 'abc'). Legal suffix characters are: K, M, G, T, P, E +[ERROR] Buffered error: mysqld: Error while setting value 'abc' to 'max_connections' +# --thread-handling=bogus, exit code 13: +# error, then max_connections warning, no "Configuration is valid" +[ERROR] mysqld: Error while setting value 'bogus' to 'thread_handling' +[Warning] Buffered warning: option 'max_connections': unsigned value 0 adjusted to 10 +# unknown character set, exit code 1: +# error, then max_connections warning +mysqld: Character set 'bogus' is not a compiled character set and is not specified in the 'Index.xml' file +[Warning] Buffered warning: option 'max_connections': unsigned value 0 adjusted to 10 +[ERROR] Aborting +# unknown collation, exit code 1: max_connections warning, then error +[Warning] Buffered warning: option 'max_connections': unsigned value 0 adjusted to 10 +[ERROR] Unknown collation: 'bogus' +[ERROR] Aborting +# collation does not match the character set, exit code 1: +# max_connections warning, then error +[Warning] Buffered warning: option 'max_connections': unsigned value 0 adjusted to 10 +[ERROR] COLLATION 'utf8mb4_bin' is not valid for CHARACTER SET 'latin1' +[ERROR] Aborting +# invalid --ft-boolean-syntax, exit code 1: +# error, then max_connections warning +[ERROR] Invalid ft-boolean-syntax string: x +[Warning] Buffered warning: option 'max_connections': unsigned value 0 adjusted to 10 +# extra argument, exit code 1: max_connections warning, then error +[Warning] Buffered warning: option 'max_connections': unsigned value 0 adjusted to 10 +mysqld: Too many arguments (first extra is 'extra_argument'). +[ERROR] Aborting +# --defaults-file does not exist, exit code 1: error +Could not open required defaults file: MYSQLTEST_VARDIR/tmp/validate_config/missing.cnf +Fatal error in defaults handling. Program aborted +# --defaults-extra-file (without --defaults-file) names a missing file, exit code 1: error +Could not open required defaults file: MYSQLTEST_VARDIR/tmp/validate_config/missing.cnf +Fatal error in defaults handling. Program aborted # -# Test 5: --validate-config with bad option in config file should fail +# 4. --help and --version win over --validate-config: +# "Configuration is valid." and option errors are not printed # -FOUND 1 /unknown variable 'zzz_bogus_option=123'/ in mdev-31527-test5.log +# --help: help text, no "Configuration is valid" +FOUND 1 /Starts the MariaDB database server/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log +# --help --verbose: help text, no "Configuration is valid" +FOUND 1 /Starts the MariaDB database server/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log +# --help with an unknown option: help text, no error +FOUND 1 /Starts the MariaDB database server/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log +# --help with an unknown variable in a config file: help text, no error +FOUND 1 /Starts the MariaDB database server/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log +# --version: version, no "Configuration is valid" +FOUND 1 /Ver [0-9]/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log +# --version --verbose: version, no "Configuration is valid" +FOUND 1 /Ver [0-9]/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log +# --version with an unknown option: version, no error +FOUND 1 /Ver [0-9]/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log +# --version with an unknown variable in a config file: version, no error +FOUND 1 /Ver [0-9]/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log +# --help --verbose lists --validate-config +FOUND 1 /Validate the server configuration/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log +# --max-connections=0 with --help, --help --verbose, --version: +# the warning is printed +FOUND 1 /option 'max_connections': unsigned value 0 adjusted to 10/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log +FOUND 1 /option 'max_connections': unsigned value 0 adjusted to 10/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log +FOUND 1 /option 'max_connections': unsigned value 0 adjusted to 10/ in validate_config.log +NOT FOUND /Configuration is valid|\[ERROR\]/ in validate_config.log # -# Test 6: --validate-config with valid config file should succeed +# 5. --validate-config creates no files and does not start the server # -FOUND 1 /Configuration is valid\./ in mdev-31527-test6.log -# -# Test 7: --validate-config with --help (help takes precedence, -# 'Configuration is valid' should NOT be printed) -# -FOUND 1 /Starts the MariaDB database server/ in mdev-31527-test7.log -NOT FOUND /Configuration is valid/ in mdev-31527-test7.log -# -# Test 8: --validate-config with --verbose should still succeed (exit 0) -# -FOUND 1 /Configuration is valid\./ in mdev-31527-test8.log -# -# Test 9: --validate-config with --version (version takes precedence, -# 'Configuration is valid' should NOT be printed) -# -FOUND 1 /Ver [0-9]/ in mdev-31527-test9.log -NOT FOUND /Configuration is valid/ in mdev-31527-test9.log -# -# Test 10: --help --validate-config --invalid-config should print help -# and exit cleanly (help takes precedence) -# -FOUND 1 /Starts the MariaDB database server/ in mdev-31527-test10.log -NOT FOUND /unknown option/ in mdev-31527-test10.log -# -# Test 11: --version --validate-config --invalid-config should print version -# and exit cleanly (version takes precedence) -# -FOUND 1 /Ver [0-9]/ in mdev-31527-test11.log -NOT FOUND /unknown option/ in mdev-31527-test11.log -# -# Test 12: --validate-config --log-bin should not create binlog index file -# -FOUND 1 /Configuration is valid\./ in mdev-31527-test12.log -# -# Test 13: --validate-config with adjusted option value should warn and succeed -# -FOUND 1 /option 'table_open_cache': unsigned value 0 adjusted/ in mdev-31527-test13.log -FOUND 1 /Configuration is valid, but warnings were reported/ in mdev-31527-test13.log -# -# Test 14: --validate-config with a warning that is not related to -# option parsing (e.g. tls_version) should still report -# "warnings were reported" -# -FOUND 1 /TLSv1.0 and TLSv1.1 are insecure/ in mdev-31527-test14.log -FOUND 1 /Configuration is valid, but warnings were reported/ in mdev-31527-test14.log -# -# Test 15: --validate-config --help --verbose should not print -# 'Configuration is valid' (help takes precedence) -# -FOUND 1 /Starts the MariaDB database server/ in mdev-31527-test15.log -NOT FOUND /Configuration is valid/ in mdev-31527-test15.log -# -# Test 16: --validate-config --version --verbose should not print -# 'Configuration is valid' (version takes precedence) -# -FOUND 1 /Ver [0-9]/ in mdev-31527-test16.log -NOT FOUND /Configuration is valid/ in mdev-31527-test16.log -# -# Test 17: --validate-config --silent-startup must still print the verdict -# -FOUND 1 /Configuration is valid\./ in mdev-31527-test17.log -# -# Test 18: a warning printed via sql_print_warning() is counted -# -FOUND 1 /Although a general log file was specified, log tables are used/ in mdev-31527-test18.log -FOUND 1 /Configuration is valid, but warnings were reported/ in mdev-31527-test18.log -# -# Test 19: a warning for an early-parsed option is counted -# -FOUND 1 /option 'max_connections': unsigned value 99999999999 adjusted/ in mdev-31527-test19.log -FOUND 1 /Configuration is valid, but warnings were reported/ in mdev-31527-test19.log -# -# Test 20: --validate-config prints no [Note] lines -# (e.g. "Plugin 'FEEDBACK' is disabled.") -# -NOT FOUND /\[Note\]/ in mdev-31527-test20.log +Configuration is valid. +# files in the test directory: only the datadir +data +# files in the datadir: none # End of 13.2 tests diff --git a/mysql-test/main/validate_config.test b/mysql-test/main/validate_config.test index f1be75495a1..1c91c16ce0b 100644 --- a/mysql-test/main/validate_config.test +++ b/mysql-test/main/validate_config.test @@ -1,259 +1,289 @@ -# -# MDEV-31527: Add --validate-config option to check configuration -# without starting the server -# +--echo # +--echo # MDEV-31527: Add --validate-config option to check configuration +--echo # without starting the server +--echo # --source include/not_embedded.inc - -# mysqld refuses to run as root normally. +# mysqld refuses to start as root --source include/not_as_root.inc -# Keep runs that expect the clean verdict free of environment-dependent -# warnings (open files ulimit, case-insensitive file system). ---let $quiet= --max-connections=10 --table-open-cache=10 --table-open-cache-instances=1 --open-files-limit=512 --lower-case-table-names=1 +--let $vc_dir= $MYSQLTEST_VARDIR/tmp/validate_config +--mkdir $vc_dir +--mkdir $vc_dir/data + +# Private datadir, no network. The fixed limits and lower-case-table-names +# keep clean runs free of environment-dependent warnings. +--let $vc_opts= --datadir=$vc_dir/data --skip-networking --max-connections=10 --table-open-cache=10 --table-open-cache-instances=1 --open-files-limit=512 --lower-case-table-names=1 +# Must not be found in the brief output +--let $vc_absent= Configuration is valid|\[ERROR\] +--let $vc_help= Starts the MariaDB database server +--let $vc_ver= Ver [0-9] +--let $vc_warn= option 'max_connections': unsigned value 0 adjusted to 10 + +--let $vc_base= --no-defaults $vc_opts --validate-config + +--let $vc_rc= 0 +--let $vc_cmd= $MYSQLD +--let $vc_brief= 0 --echo # ---echo # Test 1: --validate-config with valid configuration should succeed (exit 0) +--echo # 1. Valid configuration: only "Configuration is valid." is printed --echo # ---exec $MYSQLD_BOOTSTRAP_CMD $quiet --validate-config >$MYSQLTEST_VARDIR/tmp/mdev-31527-test1.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test1.log ---let SEARCH_PATTERN=Configuration is valid\. ---source include/search_pattern_in_file.inc ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test1.log +--let $vc_args= $vc_base +--source validate_config.inc + +--echo # MTR bootstrap command: only "Configuration is valid." +--let $vc_cmd= $MYSQLD_BOOTSTRAP_CMD +--let $vc_args= $vc_opts --validate-config +--source validate_config.inc + +--echo # --verbose, --silent-startup: only "Configuration is valid." +--let $vc_args= $vc_base --verbose +--source validate_config.inc +--let $vc_args= $vc_base --silent-startup +--source validate_config.inc + +--echo # "Configuration is valid." goes to stdout, stderr is empty +--echo # stdout: +--exec $MYSQLD $vc_base 2>$vc_dir/err +--echo # stderr: +--cat_file $vc_dir/err +--remove_file $vc_dir/err + +--echo # valid value in a config file: only "Configuration is valid." +--write_file $vc_dir/good.cnf +[mysqld] +key_buffer_size=16M +EOF +--let $vc_args= --defaults-file=$vc_dir/good.cnf $vc_opts --validate-config +--source validate_config.inc --echo # ---echo # Test 2: --validate-config with unknown option should fail (exit 2) +--echo # 2. Valid configuration with warnings: the warnings, then +--echo # "Configuration is valid, but warnings were reported; see above." --echo # ---error 2 ---exec $MYSQLD_BOOTSTRAP_CMD --validate-config --nonexistentoption >$MYSQLTEST_VARDIR/tmp/mdev-31527-test2.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test2.log ---let SEARCH_PATTERN=unknown option '--nonexistentoption' ---source include/search_pattern_in_file.inc ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test2.log +--echo # values adjusted in a config file, [mysqld] and [server] groups: +--echo # two warnings, then "warnings were reported" +--write_file $vc_dir/adjusted.cnf +[mysqld] +max_connections=0 +[server] +sort_buffer_size=1 +EOF +--let $vc_args= --defaults-file=$vc_dir/adjusted.cnf $vc_opts --validate-config +--source validate_config.inc + +--echo # value adjusted on the command line before --validate-config: +--echo # warning, then "warnings were reported" +--let $vc_args= --no-defaults $vc_opts --sort-buffer-size=1 --validate-config +--source validate_config.inc + +--echo # plugin option value adjusted: warning, then "warnings were reported" +--let $vc_args= $vc_base --aria-sort-buffer-size=1 +--source validate_config.inc + +--echo # unknown --loose- option: warning, then "warnings were reported" +--let $vc_args= $vc_base --loose-zzz-bogus=1 +--source validate_config.inc + +--echo # checks made after option parsing: +--echo # warning, then "warnings were reported" +--let $vc_args= $vc_base --tls-version=TLSv1.0 +--source validate_config.inc +--let $vc_args= $vc_base --general-log --general-log-file=$vc_dir/general.log --log-output=table +--source validate_config.inc + +--echo # malformed Index.xml, error printed outside the error log: +--echo # the error, then "warnings were reported" +--mkdir $vc_dir/charsets +--write_file $vc_dir/charsets/Index.xml +< +EOF +--let $vc_args= $vc_base --character-sets-dir=$vc_dir/charsets +--source validate_config.inc +--remove_file $vc_dir/charsets/Index.xml +--rmdir $vc_dir/charsets --echo # ---echo # Test 3: --validate-config should not start the server (no pid file created) +--echo # 3. Invalid configuration: the error and the exit code, +--echo # no "Configuration is valid." --echo # ---exec $MYSQLD --no-defaults $quiet --validate-config --pid-file=$MYSQLTEST_VARDIR/tmp/mdev-31527-validate.pid >$MYSQLTEST_VARDIR/tmp/mdev-31527-test3.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test3.log ---let SEARCH_PATTERN=Configuration is valid\. ---source include/search_pattern_in_file.inc ---error 1 ---file_exists $MYSQLTEST_VARDIR/tmp/mdev-31527-validate.pid ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test3.log +--echo # unknown option, exit code 2: error, no "Configuration is valid" +--let $vc_rc= 2 +--let $vc_args= $vc_base --nonexistentoption +--source validate_config.inc ---echo # ---echo # Test 4: --validate-config should not produce help output ---echo # ---exec $MYSQLD_BOOTSTRAP_CMD --validate-config >$MYSQLTEST_VARDIR/tmp/mdev-31527-test4.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test4.log ---let SEARCH_PATTERN=Starts the MariaDB database server ---source include/search_pattern_in_file.inc ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test4.log +--echo # unknown plugin variable, exit code 7: +--echo # error, no "Configuration is valid" +--let $vc_rc= 7 +--let $vc_args= $vc_base --aria-bogus=1 +--source validate_config.inc ---echo # ---echo # Test 5: --validate-config with bad option in config file should fail ---echo # ---write_file $MYSQLTEST_VARDIR/tmp/mdev-31527-bad.cnf +--echo # unknown variable in a config file, exit code 7: +--echo # error, no "Configuration is valid" +--write_file $vc_dir/bad_var.cnf [mariadb] zzz_bogus_option=123 EOF ---error 7 ---exec $MYSQLD --defaults-file=$MYSQLTEST_VARDIR/tmp/mdev-31527-bad.cnf --validate-config >$MYSQLTEST_VARDIR/tmp/mdev-31527-test5.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test5.log ---let SEARCH_PATTERN=unknown variable 'zzz_bogus_option=123' ---source include/search_pattern_in_file.inc ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test5.log ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-bad.cnf +--let $vc_rc= 7 +--let $vc_args= --defaults-file=$vc_dir/bad_var.cnf $vc_opts --validate-config +--source validate_config.inc ---echo # ---echo # Test 6: --validate-config with valid config file should succeed ---echo # ---write_file $MYSQLTEST_VARDIR/tmp/mdev-31527-good.cnf -[mariadb] -key_buffer_size=16M +--echo # unknown variable in a file pulled in by !include, exit code 7: +--echo # error, no "Configuration is valid" +--perl + my $d= "$ENV{MYSQLTEST_VARDIR}/tmp/validate_config"; + open(F, ">$d/main.cnf") or die "$d/main.cnf: $!"; + print F "!include $d/bad_var.cnf\n"; + close(F); EOF ---exec $MYSQLD --defaults-file=$MYSQLTEST_VARDIR/tmp/mdev-31527-good.cnf $quiet --validate-config >$MYSQLTEST_VARDIR/tmp/mdev-31527-test6.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test6.log ---let SEARCH_PATTERN=Configuration is valid\. ---source include/search_pattern_in_file.inc ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test6.log ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-good.cnf +--let $vc_rc= 7 +--let $vc_args= --defaults-file=$vc_dir/main.cnf $vc_opts --validate-config +--source validate_config.inc ---echo # ---echo # Test 7: --validate-config with --help (help takes precedence, ---echo # 'Configuration is valid' should NOT be printed) ---echo # ---exec $MYSQLD_BOOTSTRAP_CMD --validate-config --help >$MYSQLTEST_VARDIR/tmp/mdev-31527-test7.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test7.log ---let SEARCH_PATTERN=Starts the MariaDB database server ---source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=Configuration is valid ---let SEARCH_ABORT=FOUND ---source include/search_pattern_in_file.inc ---let SEARCH_ABORT= ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test7.log +--echo # max_connections=abc, exit code 9: error, no "Configuration is valid" +--let $vc_rc= 9 +--let $vc_args= $vc_base --max-connections=abc +--source validate_config.inc ---echo # ---echo # Test 8: --validate-config with --verbose should still succeed (exit 0) ---echo # ---exec $MYSQLD_BOOTSTRAP_CMD $quiet --validate-config --verbose >$MYSQLTEST_VARDIR/tmp/mdev-31527-test8.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test8.log ---let SEARCH_PATTERN=Configuration is valid\. ---source include/search_pattern_in_file.inc ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test8.log - ---echo # ---echo # Test 9: --validate-config with --version (version takes precedence, ---echo # 'Configuration is valid' should NOT be printed) ---echo # ---exec $MYSQLD_BOOTSTRAP_CMD --validate-config --version >$MYSQLTEST_VARDIR/tmp/mdev-31527-test9.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test9.log ---let SEARCH_PATTERN=Ver [0-9] ---source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=Configuration is valid ---let SEARCH_ABORT=FOUND ---source include/search_pattern_in_file.inc ---let SEARCH_ABORT= ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test9.log - ---echo # ---echo # Test 10: --help --validate-config --invalid-config should print help ---echo # and exit cleanly (help takes precedence) ---echo # ---exec $MYSQLD_BOOTSTRAP_CMD --help --validate-config --invalid-config >$MYSQLTEST_VARDIR/tmp/mdev-31527-test10.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test10.log ---let SEARCH_PATTERN=Starts the MariaDB database server ---source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=unknown option ---let SEARCH_ABORT=FOUND ---source include/search_pattern_in_file.inc ---let SEARCH_ABORT= ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test10.log - ---echo # ---echo # Test 11: --version --validate-config --invalid-config should print version ---echo # and exit cleanly (version takes precedence) ---echo # ---exec $MYSQLD_BOOTSTRAP_CMD --version --validate-config --invalid-config >$MYSQLTEST_VARDIR/tmp/mdev-31527-test11.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test11.log ---let SEARCH_PATTERN=Ver [0-9] ---source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=unknown option ---let SEARCH_ABORT=FOUND ---source include/search_pattern_in_file.inc ---let SEARCH_ABORT= ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test11.log - ---echo # ---echo # Test 12: --validate-config --log-bin should not create binlog index file ---echo # ---exec $MYSQLD_BOOTSTRAP_CMD $quiet --validate-config --log-bin=$MYSQLTEST_VARDIR/tmp/mdev-31527-binlog >$MYSQLTEST_VARDIR/tmp/mdev-31527-test12.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test12.log ---let SEARCH_PATTERN=Configuration is valid\. ---source include/search_pattern_in_file.inc ---error 1 ---file_exists $MYSQLTEST_VARDIR/tmp/mdev-31527-binlog.index ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test12.log - ---echo # ---echo # Test 13: --validate-config with adjusted option value should warn and succeed ---echo # ---write_file $MYSQLTEST_VARDIR/tmp/mdev-31527-adjusted.cnf -[mariadb] -table_open_cache=0 +--echo # max_connections=abc in a config file, exit code 9: +--echo # error, no "Configuration is valid" +--write_file $vc_dir/bad_num.cnf +[mysqld] +max_connections=abc EOF ---exec $MYSQLD --defaults-file=$MYSQLTEST_VARDIR/tmp/mdev-31527-adjusted.cnf --validate-config >$MYSQLTEST_VARDIR/tmp/mdev-31527-test13.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test13.log ---let SEARCH_PATTERN=option 'table_open_cache': unsigned value 0 adjusted ---source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=Configuration is valid, but warnings were reported ---source include/search_pattern_in_file.inc ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test13.log ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-adjusted.cnf +--let $vc_rc= 9 +--let $vc_args= --defaults-file=$vc_dir/bad_num.cnf $vc_opts --validate-config +--source validate_config.inc + +--echo # --thread-handling=bogus, exit code 13: +--echo # error, then max_connections warning, no "Configuration is valid" +--let $vc_rc= 13 +--let $vc_args= $vc_base --max-connections=0 --thread-handling=bogus +--source validate_config.inc + +--echo # unknown character set, exit code 1: +--echo # error, then max_connections warning +--let $vc_rc= 1 +--let $vc_args= $vc_base --max-connections=0 --character-set-server=bogus +--source validate_config.inc + +--echo # unknown collation, exit code 1: max_connections warning, then error +--let $vc_rc= 1 +--let $vc_args= $vc_base --max-connections=0 --collation-server=bogus +--source validate_config.inc + +--echo # collation does not match the character set, exit code 1: +--echo # max_connections warning, then error +--let $vc_rc= 1 +--let $vc_args= $vc_base --max-connections=0 --character-set-server=latin1 --collation-server=utf8mb4_bin +--source validate_config.inc + +--echo # invalid --ft-boolean-syntax, exit code 1: +--echo # error, then max_connections warning +--let $vc_rc= 1 +--let $vc_args= $vc_base --max-connections=0 --ft-boolean-syntax=x +--source validate_config.inc + +--echo # extra argument, exit code 1: max_connections warning, then error +--let $vc_rc= 1 +--let $vc_args= $vc_base --max-connections=0 extra_argument +--source validate_config.inc + +--echo # --defaults-file does not exist, exit code 1: error +--let $vc_rc= 1 +--let $vc_args= --defaults-file=$vc_dir/missing.cnf $vc_opts --validate-config +--source validate_config.inc +--echo # --defaults-extra-file (without --defaults-file) names a missing file, exit code 1: error +--let $vc_rc= 1 +--let $vc_args= --defaults-extra-file=$vc_dir/missing.cnf $vc_opts --validate-config +--source validate_config.inc --echo # ---echo # Test 14: --validate-config with a warning that is not related to ---echo # option parsing (e.g. tls_version) should still report ---echo # "warnings were reported" +--echo # 4. --help and --version win over --validate-config: +--echo # "Configuration is valid." and option errors are not printed --echo # ---exec $MYSQLD --no-defaults --validate-config --tls-version=TLSv1.0 >$MYSQLTEST_VARDIR/tmp/mdev-31527-test14.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test14.log ---let SEARCH_PATTERN=TLSv1.0 and TLSv1.1 are insecure ---source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=Configuration is valid, but warnings were reported ---source include/search_pattern_in_file.inc ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test14.log +--echo # --help: help text, no "Configuration is valid" +--let $vc_brief= 1 +--let $vc_expect= $vc_help +--let $vc_args= $vc_base --help +--source validate_config.inc + +--echo # --help --verbose: help text, no "Configuration is valid" +--let $vc_brief= 1 +--let $vc_expect= $vc_help +--let $vc_args= $vc_base --help --verbose +--source validate_config.inc + +--echo # --help with an unknown option: help text, no error +--let $vc_brief= 1 +--let $vc_expect= $vc_help +--let $vc_args= --no-defaults $vc_opts --help --validate-config --invalid-config +--source validate_config.inc + +--echo # --help with an unknown variable in a config file: help text, no error +--let $vc_brief= 1 +--let $vc_expect= $vc_help +--let $vc_args= --defaults-file=$vc_dir/bad_var.cnf $vc_opts --help --validate-config +--source validate_config.inc + +--echo # --version: version, no "Configuration is valid" +--let $vc_brief= 1 +--let $vc_expect= $vc_ver +--let $vc_args= $vc_base --version +--source validate_config.inc + +--echo # --version --verbose: version, no "Configuration is valid" +--let $vc_brief= 1 +--let $vc_expect= $vc_ver +--let $vc_args= $vc_base --version --verbose +--source validate_config.inc + +--echo # --version with an unknown option: version, no error +--let $vc_brief= 1 +--let $vc_expect= $vc_ver +--let $vc_args= --no-defaults $vc_opts --version --validate-config --invalid-config +--source validate_config.inc + +--echo # --version with an unknown variable in a config file: version, no error +--let $vc_brief= 1 +--let $vc_expect= $vc_ver +--let $vc_args= --defaults-file=$vc_dir/bad_var.cnf $vc_opts --version --validate-config +--source validate_config.inc + +--echo # --help --verbose lists --validate-config +--let $vc_brief= 1 +--let $vc_expect= Validate the server configuration +--let $vc_args= --no-defaults $vc_opts --help --verbose +--source validate_config.inc + +--echo # --max-connections=0 with --help, --help --verbose, --version: +--echo # the warning is printed +--let $vc_brief= 1 +--let $vc_expect= $vc_warn +--let $vc_args= --no-defaults $vc_opts --max-connections=0 --help +--source validate_config.inc +--let $vc_brief= 1 +--let $vc_expect= $vc_warn +--let $vc_args= --no-defaults $vc_opts --max-connections=0 --help --verbose +--source validate_config.inc +--let $vc_brief= 1 +--let $vc_expect= $vc_warn +--let $vc_args= --no-defaults $vc_opts --max-connections=0 --version +--source validate_config.inc --echo # ---echo # Test 15: --validate-config --help --verbose should not print ---echo # 'Configuration is valid' (help takes precedence) +--echo # 5. --validate-config creates no files and does not start the server --echo # ---exec $MYSQLD_BOOTSTRAP_CMD --validate-config --help --verbose >$MYSQLTEST_VARDIR/tmp/mdev-31527-test15.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test15.log ---let SEARCH_PATTERN=Starts the MariaDB database server ---source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=Configuration is valid ---let SEARCH_ABORT=FOUND ---source include/search_pattern_in_file.inc ---let SEARCH_ABORT= ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test15.log +--remove_files_wildcard $vc_dir *.cnf +--let $vc_args= $vc_base --pid-file=$vc_dir/mysqld.pid --log-error=$vc_dir/error.log --log-bin=$vc_dir/binlog --general-log --general-log-file=$vc_dir/general.log --slow-query-log --slow-query-log-file=$vc_dir/slow.log --socket=$vc_dir/mysqld.sock +--source validate_config.inc +--echo # files in the test directory: only the datadir +--list_files $vc_dir +--echo # files in the datadir: none +--list_files $vc_dir/data ---echo # ---echo # Test 16: --validate-config --version --verbose should not print ---echo # 'Configuration is valid' (version takes precedence) ---echo # ---exec $MYSQLD_BOOTSTRAP_CMD --validate-config --version --verbose >$MYSQLTEST_VARDIR/tmp/mdev-31527-test16.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test16.log ---let SEARCH_PATTERN=Ver [0-9] ---source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=Configuration is valid ---let SEARCH_ABORT=FOUND ---source include/search_pattern_in_file.inc ---let SEARCH_ABORT= ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test16.log - ---echo # ---echo # Test 17: --validate-config --silent-startup must still print the verdict ---echo # ---exec $MYSQLD --no-defaults $quiet --validate-config --silent-startup >$MYSQLTEST_VARDIR/tmp/mdev-31527-test17.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test17.log ---let SEARCH_PATTERN=Configuration is valid\. ---source include/search_pattern_in_file.inc ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test17.log - ---echo # ---echo # Test 18: a warning printed via sql_print_warning() is counted ---echo # ---exec $MYSQLD --no-defaults --validate-config --general-log --general-log-file=$MYSQLTEST_VARDIR/tmp/mdev-31527-general.log --log-output=table >$MYSQLTEST_VARDIR/tmp/mdev-31527-test18.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test18.log ---let SEARCH_PATTERN=Although a general log file was specified, log tables are used ---source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=Configuration is valid, but warnings were reported ---source include/search_pattern_in_file.inc ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test18.log - ---echo # ---echo # Test 19: a warning for an early-parsed option is counted ---echo # ---exec $MYSQLD --no-defaults --validate-config --max-connections=99999999999 >$MYSQLTEST_VARDIR/tmp/mdev-31527-test19.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test19.log ---let SEARCH_PATTERN=option 'max_connections': unsigned value 99999999999 adjusted ---source include/search_pattern_in_file.inc ---let SEARCH_PATTERN=Configuration is valid, but warnings were reported ---source include/search_pattern_in_file.inc ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test19.log - ---echo # ---echo # Test 20: --validate-config prints no [Note] lines ---echo # (e.g. "Plugin 'FEEDBACK' is disabled.") ---echo # ---exec $MYSQLD_BOOTSTRAP_CMD --validate-config >$MYSQLTEST_VARDIR/tmp/mdev-31527-test20.log 2>&1 ---let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/mdev-31527-test20.log ---let SEARCH_PATTERN=\[Note\] ---let SEARCH_ABORT=FOUND ---source include/search_pattern_in_file.inc ---let SEARCH_ABORT= ---remove_file $MYSQLTEST_VARDIR/tmp/mdev-31527-test20.log +--rmdir $vc_dir/data +--rmdir $vc_dir --echo # End of 13.2 tests diff --git a/sql/log.cc b/sql/log.cc index 6bf1251f220..b512b9d9d71 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -12024,6 +12024,10 @@ int vprint_msg_to_log(enum loglevel level, const char *format, va_list args) size_t length; DBUG_ENTER("vprint_msg_to_log"); + /* + Not conditional on opt_validate_config: --validate-config may be + parsed after options whose warnings are already printed. + */ if (level == WARNING_LEVEL) validate_config_has_warnings= 1; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7482628eb95..e413181e1f2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1479,6 +1479,8 @@ public: void buffer(enum loglevel m_level, const char *msg); void print(); + /** Print and release the buffered messages. Safe to call repeatedly. */ + void flush(); private: /** Memory root to use to store buffered logs. @@ -1489,17 +1491,23 @@ private: MEM_ROOT m_root; /** List of buffered log messages. */ List m_list; + /** True between init() and cleanup(), while m_root is usable. */ + bool m_active= false; }; void Buffered_logs::init() { init_alloc_root(PSI_NOT_INSTRUMENTED, &m_root, 1024, 0, MYF(0)); + m_active= true; } void Buffered_logs::cleanup() { + if (!m_active) + return; m_list.delete_elements(); free_root(&m_root, MYF(0)); + m_active= false; } /** @@ -1507,6 +1515,15 @@ void Buffered_logs::cleanup() */ void Buffered_logs::buffer(enum loglevel level, const char *msg) { + if (!m_active) + { + /* Not active (before init() or after flush()): log directly. */ + if (level == ERROR_LEVEL) + sql_print_error("%s", msg); + else if (level == WARNING_LEVEL) + sql_print_warning("%s", msg); + return; + } /* Do not let Sql_alloc::operator new(size_t) allocate memory, there is no memory root associated with the main() thread. @@ -1529,11 +1546,31 @@ void Buffered_logs::print() log->print(); } +void Buffered_logs::flush() +{ + if (!m_active) + return; + print(); + cleanup(); +} + /** Logs reported before a logger is available. */ static Buffered_logs buffered_logs; struct my_rnd_struct sql_rand; ///< used by sql_class.cc:THD::THD() +/** + Early mysys error hook: print to stderr, and count the message as a + warning for the --validate-config verdict (e.g. Index.xml parse errors). +*/ +static void early_error_handler(uint error, const char *str, myf flags) +{ + if (!(flags & (ME_NOTE | ME_ERROR_LOG_ONLY))) + validate_config_has_warnings= 1; + my_message_stderr(error, str, flags); +} + + #ifndef EMBEDDED_LIBRARY Dynamic_array listen_sockets(PSI_INSTRUMENT_MEM, 0); @@ -2008,6 +2045,9 @@ extern "C" void unireg_abort(int exit_code) { DBUG_ENTER("unireg_abort"); + /* Do not lose (or leak) messages buffered while parsing early options. */ + buffered_logs.flush(); + if (opt_help) usage(); else if (exit_code) @@ -4280,7 +4320,10 @@ static int init_common_variables() int opt_err; if ((opt_err= get_options(&remaining_argc, &remaining_argv))) + { + buffered_logs.flush(); exit(opt_err); + } if (IS_SYSVAR_AUTOSIZE(&server_version_ptr)) set_server_version(server_version, sizeof(server_version)); @@ -4425,6 +4468,7 @@ static int init_common_variables() } unireg_init(opt_specialflag); /* Set up extern variables */ + error_handler_hook= early_error_handler; if (!(my_default_lc_messages= my_locale_by_name(Lex_cstring_strlen(lc_messages)))) { @@ -4499,13 +4543,13 @@ static int init_common_variables() default_collation= get_charset_by_name(default_collation_name, MYF(utf8_flag)); if (!default_collation) { - buffered_logs.print(); - buffered_logs.cleanup(); + buffered_logs.flush(); sql_print_error(ER_DEFAULT(ER_UNKNOWN_COLLATION), default_collation_name); return 1; } if (!my_charset_same(default_charset_info, default_collation)) { + buffered_logs.flush(); sql_print_error(ER_DEFAULT(ER_COLLATION_CHARSET_MISMATCH), default_collation_name, default_charset_info->cs_name.str); @@ -5266,8 +5310,7 @@ static int init_server_components() to the proper file when the --log--error option is used, print the buffered messages to the log. */ - buffered_logs.print(); - buffered_logs.cleanup(); + buffered_logs.flush(); #ifndef EMBEDDED_LIBRARY /* @@ -6180,7 +6223,7 @@ int mysqld_main(int argc, char **argv) #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ my_timer_init(&sys_timer_info); - int ho_error __attribute__((unused))= handle_early_options(); + int ho_error= handle_early_options(); /* fix tdc_size */ if (IS_SYSVAR_AUTOSIZE(&tdc_size)) @@ -6263,7 +6306,6 @@ int mysqld_main(int argc, char **argv) */ logger.init_base(); -#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE if (ho_error) { /* @@ -6275,15 +6317,13 @@ int mysqld_main(int argc, char **argv) - messages will be printed to stderr, which is not redirected yet, - messages will be printed in the NT event log, for windows. */ - buffered_logs.print(); - buffered_logs.cleanup(); + buffered_logs.flush(); /* Not enough initializations for unireg_abort() Using exit() for windows. */ exit (ho_error); } -#endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */ #ifdef _CUSTOMSTARTUPCONFIG_ if (_cust_check_startup())