diff --git a/include/my_getopt.h b/include/my_getopt.h index 50ebe9190d8..7cbad607aac 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -72,7 +72,7 @@ extern void my_cleanup_options(const struct my_option *options); extern void my_print_help(const struct my_option *options); extern void my_print_variables(const struct my_option *options); extern void my_getopt_register_get_addr(uchar ** (*func_addr)(const char *, uint, - const struct my_option *)); + const struct my_option *, int *)); ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, my_bool *fix); diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 23572ad4929..d644c45a66a 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -43,6 +43,15 @@ extern char mysql_server_last_error[MYSQL_ERRMSG_SIZE]; static my_bool emb_read_query_result(MYSQL *mysql); +extern "C" void unireg_clear(int exit_code) +{ + DBUG_ENTER("unireg_clear"); + clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */ + my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); + DBUG_VOID_RETURN; +} + + /* Reads error information from the MYSQL_DATA and puts it into proper MYSQL members diff --git a/mysys/default.c b/mysys/default.c index 6b2b31d43ec..c7e1e513e1e 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -144,6 +144,7 @@ static char *remove_end_comment(char *ptr); RETURN 0 ok 1 given cinf_file doesn't exist + 2 out of memory The global variable 'my_defaults_group_suffix' is updated with value for --defaults_group_suffix @@ -190,7 +191,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, if (!(extra_groups= (const char**)alloc_root(ctx->alloc, (2*group->count+1)*sizeof(char*)))) - goto err; + DBUG_RETURN(2); for (i= 0; i < group->count; i++) { @@ -199,7 +200,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, len= strlen(extra_groups[i]); if (!(ptr= alloc_root(ctx->alloc, len+instance_len+1))) - goto err; + DBUG_RETURN(2); extra_groups[i+group->count]= ptr; @@ -254,12 +255,11 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, } } - DBUG_RETURN(error); + DBUG_RETURN(0); err: fprintf(stderr,"Fatal error in defaults handling. Program aborted\n"); - exit(1); - return 0; /* Keep compiler happy */ + DBUG_RETURN(1); } diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index f97550d4429..48174a40c21 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -100,10 +100,10 @@ static void default_reporter(enum loglevel level, one. Call function 'get_one_option()' once for each option. */ -static uchar** (*getopt_get_addr)(const char *, uint, const struct my_option *); +static uchar** (*getopt_get_addr)(const char *, uint, const struct my_option *, int *); void my_getopt_register_get_addr(uchar** (*func_addr)(const char *, uint, - const struct my_option *)) + const struct my_option *, int *)) { getopt_get_addr= func_addr; } @@ -362,8 +362,12 @@ int handle_options(int *argc, char ***argv, my_progname, optp->name); return EXIT_NO_ARGUMENT_ALLOWED; } + error= 0; value= optp->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp) : optp->value; + (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp, &error) : + optp->value; + if (error) + return error; if (optp->arg_type == NO_ARG) { @@ -1092,7 +1096,7 @@ static void init_variables(const struct my_option *options, if (options->value) init_one_value(options, options->value, options->def_value); if (options->var_type & GET_ASK_ADDR && - (variable= (*getopt_get_addr)("", 0, options))) + (variable= (*getopt_get_addr)("", 0, options, 0))) init_one_value(options, variable, options->def_value); } DBUG_VOID_RETURN; @@ -1196,7 +1200,7 @@ void my_print_variables(const struct my_option *options) for (optp= options; optp->id; optp++) { uchar* *value= (optp->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)("", 0, optp) : optp->value); + (*getopt_get_addr)("", 0, optp, 0) : optp->value); if (value) { printf("%s ", optp->name); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3fba9248940..a2fbddd667a 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -2411,7 +2411,8 @@ extern "C" void unireg_abort(int exit_code) __attribute__((noreturn)); void kill_delayed_threads(void); bool check_stack_overrun(THD *thd, long margin, uchar *dummy); #else -#define unireg_abort(exit_code) DBUG_RETURN(exit_code) +extern "C" void unireg_clear(int exit_code); +#define unireg_abort(exit_code) do { unireg_clear(exit_code); DBUG_RETURN(exit_code); } while(0) inline void kill_delayed_threads(void) {} #define check_stack_overrun(A, B, C) 0 #endif diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a9b8c9112f3..7f78b410b05 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -747,12 +747,12 @@ uint connection_count= 0; pthread_handler_t signal_hand(void *arg); static int mysql_init_variables(void); -static void get_options(int *argc,char **argv); +static int get_options(int *argc,char **argv); extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *); static void set_server_version(void); static int init_thread_environment(); static char *get_relative_path(const char *path); -static void fix_paths(void); +static int fix_paths(void); pthread_handler_t handle_connections_sockets(void *arg); pthread_handler_t kill_server_thread(void *arg); static void bootstrap(FILE *file); @@ -766,7 +766,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg); pthread_handler_t handle_slave(void *arg); static ulong find_bit_type(const char *x, TYPELIB *bit_lib); static ulong find_bit_type_or_exit(const char *x, TYPELIB *bit_lib, - const char *option); + const char *option, int *error); static void clean_up(bool print_message); static int test_if_case_insensitive(const char *dir_name); @@ -1190,7 +1190,8 @@ extern "C" void unireg_abort(int exit_code) my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); exit(exit_code); /* purecov: inspected */ } -#endif + +#endif /*EMBEDDED_LIBRARY*/ void clean_up(bool print_message) @@ -3226,7 +3227,8 @@ static int init_common_variables(const char *conf_file_name, int argc, load_defaults(conf_file_name, groups, &argc, &argv); defaults_argv=argv; defaults_argc=argc; - get_options(&defaults_argc, defaults_argv); + if (get_options(&defaults_argc, defaults_argv)) + return 1; set_server_version(); DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname, @@ -7497,6 +7499,7 @@ To see what values a running MySQL server is using, type\n\ static int mysql_init_variables(void) { + int error; /* Things reset to zero */ opt_skip_slave_start= opt_reckless_slave = 0; mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0; @@ -7554,7 +7557,10 @@ static int mysql_init_variables(void) delay_key_write_options= (uint) DELAY_KEY_WRITE_ON; slave_exec_mode_options= 0; slave_exec_mode_options= (uint) - find_bit_type_or_exit(slave_exec_mode_str, &slave_exec_mode_typelib, NULL); + find_bit_type_or_exit(slave_exec_mode_str, &slave_exec_mode_typelib, NULL, + &error); + if (error) + return 1; opt_specialflag= SPECIAL_ENGLISH; unix_sock= ip_sock= INVALID_SOCKET; mysql_home_ptr= mysql_home; @@ -7732,6 +7738,8 @@ mysqld_get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) { + int error; + switch(optid) { case '#': #ifndef DBUG_OFF @@ -7775,7 +7783,9 @@ mysqld_get_one_option(int optid, break; case OPT_SLAVE_EXEC_MODE: slave_exec_mode_options= (uint) - find_bit_type_or_exit(argument, &slave_exec_mode_typelib, ""); + find_bit_type_or_exit(argument, &slave_exec_mode_typelib, "", &error); + if (error) + return 1; break; #endif case OPT_SAFEMALLOC_MEM_LIMIT: @@ -7843,18 +7853,16 @@ mysqld_get_one_option(int optid, if (!(p= strstr(argument, "->"))) { - fprintf(stderr, - "Bad syntax in replicate-rewrite-db - missing '->'!\n"); - exit(1); + sql_print_error("Bad syntax in replicate-rewrite-db - missing '->'!\n"); + return 1; } val= p--; while (my_isspace(mysqld_charset, *p) && p > argument) *p-- = 0; if (p == argument) { - fprintf(stderr, - "Bad syntax in replicate-rewrite-db - empty FROM db!\n"); - exit(1); + sql_print_error("Bad syntax in replicate-rewrite-db - empty FROM db!\n"); + return 1; } *val= 0; val+= 2; @@ -7862,9 +7870,8 @@ mysqld_get_one_option(int optid, *val++; if (!*val) { - fprintf(stderr, - "Bad syntax in replicate-rewrite-db - empty TO db!\n"); - exit(1); + sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!\n"); + return 1; } rpl_filter->add_db_rewrite(key, val); @@ -7892,8 +7899,8 @@ mysqld_get_one_option(int optid, { if (rpl_filter->add_do_table(argument)) { - fprintf(stderr, "Could not add do table rule '%s'!\n", argument); - exit(1); + sql_print_error("Could not add do table rule '%s'!\n", argument); + return 1; } break; } @@ -7901,8 +7908,8 @@ mysqld_get_one_option(int optid, { if (rpl_filter->add_wild_do_table(argument)) { - fprintf(stderr, "Could not add do table rule '%s'!\n", argument); - exit(1); + sql_print_error("Could not add do table rule '%s'!\n", argument); + return 1; } break; } @@ -7910,8 +7917,8 @@ mysqld_get_one_option(int optid, { if (rpl_filter->add_wild_ignore_table(argument)) { - fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument); - exit(1); + sql_print_error("Could not add ignore table rule '%s'!\n", argument); + return 1; } break; } @@ -7919,8 +7926,8 @@ mysqld_get_one_option(int optid, { if (rpl_filter->add_ignore_table(argument)) { - fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument); - exit(1); + sql_print_error("Could not add ignore table rule '%s'!\n", argument); + return 1; } break; } @@ -7941,7 +7948,9 @@ mysqld_get_one_option(int optid, { log_output_str= argument; log_output_options= - find_bit_type_or_exit(argument, &log_output_typelib, opt->name); + find_bit_type_or_exit(argument, &log_output_typelib, opt->name, &error); + if (error) + return 1; } break; } @@ -7951,7 +7960,7 @@ mysqld_get_one_option(int optid, sql_perror("Event scheduler is not supported in embedded build."); #else if (Events::set_opt_event_scheduler(argument)) - exit(1); + return 1; #endif break; case (int) OPT_SKIP_NEW: @@ -7990,7 +7999,7 @@ mysqld_get_one_option(int optid, case (int) OPT_SKIP_NETWORKING: #if defined(__NETWARE__) sql_perror("Can't start server: skip-networking option is currently not supported on NetWare"); - exit(1); + return 1; #endif opt_disable_networking=1; mysqld_port=0; @@ -8161,7 +8170,10 @@ mysqld_get_one_option(int optid, { myisam_recover_options_str=argument; myisam_recover_options= - find_bit_type_or_exit(argument, &myisam_recover_typelib, opt->name); + find_bit_type_or_exit(argument, &myisam_recover_typelib, opt->name, + &error); + if (error) + return 1; } ha_open_options|=HA_OPEN_ABORT_IF_CRASHED; break; @@ -8206,7 +8218,9 @@ mysqld_get_one_option(int optid, { sql_mode_str= argument; global_system_variables.sql_mode= - find_bit_type_or_exit(argument, &sql_mode_typelib, opt->name); + find_bit_type_or_exit(argument, &sql_mode_typelib, opt->name, &error); + if (error) + return 1; global_system_variables.sql_mode= fix_sql_mode(global_system_variables. sql_mode); break; @@ -8245,13 +8259,17 @@ mysqld_get_one_option(int optid, /** Handle arguments for multiple key caches. */ -extern "C" uchar **mysql_getopt_value(const char *keyname, uint key_length, - const struct my_option *option); +extern "C" int mysql_getopt_value(uchar **value, + const char *keyname, uint key_length, + const struct my_option *option, + int *error); -uchar* * +static uchar* * mysql_getopt_value(const char *keyname, uint key_length, - const struct my_option *option) + const struct my_option *option, int *error) { + if (error) + *error= 0; switch (option->id) { case OPT_KEY_BUFFER_SIZE: case OPT_KEY_CACHE_BLOCK_SIZE: @@ -8260,7 +8278,11 @@ mysql_getopt_value(const char *keyname, uint key_length, { KEY_CACHE *key_cache; if (!(key_cache= get_or_create_key_cache(keyname, key_length))) - exit(1); + { + if (error) + *error= EXIT_OUT_OF_MEMORY; + return 0; + } switch (option->id) { case OPT_KEY_BUFFER_SIZE: return (uchar**) &key_cache->param_buff_size; @@ -8298,7 +8320,7 @@ void option_error_reporter(enum loglevel level, const char *format, ...) @todo - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code? */ -static void get_options(int *argc,char **argv) +static int get_options(int *argc,char **argv) { int ho_error; @@ -8312,7 +8334,7 @@ static void get_options(int *argc,char **argv) if ((ho_error= handle_options(argc, &argv, my_long_options, mysqld_get_one_option))) - exit(ho_error); + return ho_error; (*argc)++; /* add back one for the progname handle_options removes */ /* no need to do this for argv as we are discarding it. */ @@ -8351,7 +8373,8 @@ static void get_options(int *argc,char **argv) max_allowed_packet= global_system_variables.max_allowed_packet; net_buffer_length= global_system_variables.net_buffer_length; #endif - fix_paths(); + if (fix_paths()) + return 1; /* Set some global variables from the global_system_variables @@ -8378,7 +8401,7 @@ static void get_options(int *argc,char **argv) &global_system_variables.time_format) || init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME, &global_system_variables.datetime_format)) - exit(1); + return 1; #ifdef EMBEDDED_LIBRARY one_thread_scheduler(&thread_scheduler); @@ -8391,6 +8414,7 @@ static void get_options(int *argc,char **argv) else pool_of_threads_scheduler(&thread_scheduler); /* purecov: tested */ #endif + return 0; } @@ -8454,7 +8478,7 @@ fn_format_relative_to_data_home(char * to, const char *name, } -static void fix_paths(void) +static int fix_paths(void) { char buff[FN_REFLEN],*pos; convert_dirname(mysql_home,mysql_home,NullS); @@ -8501,12 +8525,12 @@ static void fix_paths(void) charsets_dir=mysql_charsets_dir; if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) - exit(1); + return 1; #ifdef HAVE_REPLICATION if (!slave_load_tmpdir) { if (!(slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE)))) - exit(1); + return 1; } #endif /* HAVE_REPLICATION */ /* @@ -8519,30 +8543,37 @@ static void fix_paths(void) my_free(opt_secure_file_priv, MYF(0)); opt_secure_file_priv= my_strdup(buff, MYF(MY_FAE)); } + return 0; } static ulong find_bit_type_or_exit(const char *x, TYPELIB *bit_lib, - const char *option) + const char *option, int *error) { - ulong res; - + ulong result; const char **ptr; - if ((res= find_bit_type(x, bit_lib)) == ~(ulong) 0) + *error= 0; + if ((result= find_bit_type(x, bit_lib)) == ~(ulong) 0) { + char *buff= (char *) my_alloca(2048); + char *cbuf; ptr= bit_lib->type_names; - if (!*x) - fprintf(stderr, "No option given to %s\n", option); - else - fprintf(stderr, "Wrong option to %s. Option(s) given: %s\n", option, x); - fprintf(stderr, "Alternatives are: '%s'", *ptr); + cbuf= buff + ((!*x) ? + my_snprintf(buff, 2048, "No option given to %s\n", option) : + my_snprintf(buff, 2048, "Wrong option to %s. Option(s) given: %s\n", + option, x)); + cbuf+= my_snprintf(cbuf, 2048 - (cbuf-buff), "Alternatives are: '%s'", *ptr); while (*++ptr) - fprintf(stderr, ",'%s'", *ptr); - fprintf(stderr, "\n"); - exit(1); + cbuf+= my_snprintf(cbuf, 2048 - (cbuf-buff), ",'%s'", *ptr); + my_snprintf(cbuf, 2048 - (cbuf-buff), "\n"); + sql_perror(buff); + *error= 1; + my_afree(buff); + return 0; } - return res; + + return result; }