Commit be66e43d authored by Alexey Botchkov's avatar Alexey Botchkov

Bug#39289 libmysqld.a calls exit() upon error

Several functions (mostly in mysqld.cc) directly call
exit() function in case of errors, which is not a desired
behaviour expecially in the embedded-server library.

Fixed by making these functions return error sign instead
of exiting.

per-file comments:
  include/my_getopt.h
Bug#39289 libmysqld.a calls exit() upon error 
  added 'error' retvalue for my_getopt_register_get_addr

  libmysqld/lib_sql.cc
Bug#39289 libmysqld.a calls exit() upon error 
  unireg_clear() function implemented

  mysys/default.c
Bug#39289 libmysqld.a calls exit() upon error 
  error returned instead of exit() call

  mysys/mf_tempdir.c
Bug#39289 libmysqld.a calls exit() upon error 
  free_tmpdir() - fixed so it's not produce crash on uninitialized
    tmpdir structure

  mysys/my_getopt.c
Bug#39289 libmysqld.a calls exit() upon error 
  error returned instead of exit() call

  sql/mysql_priv.h
Bug#39289 libmysqld.a calls exit() upon error 
  unireg_abort definition fixed for the embedded server

  sql/mysqld.cc
Bug#39289 libmysqld.a calls exit() upon error 
  various functions fixed
  error returned instead of exit() call
parent b6704027
...@@ -72,7 +72,7 @@ extern void my_cleanup_options(const struct my_option *options); ...@@ -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_help(const struct my_option *options);
extern void my_print_variables(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, 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, ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp,
my_bool *fix); my_bool *fix);
......
...@@ -43,6 +43,15 @@ extern char mysql_server_last_error[MYSQL_ERRMSG_SIZE]; ...@@ -43,6 +43,15 @@ extern char mysql_server_last_error[MYSQL_ERRMSG_SIZE];
static my_bool emb_read_query_result(MYSQL *mysql); 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 Reads error information from the MYSQL_DATA and puts
it into proper MYSQL members it into proper MYSQL members
......
...@@ -144,6 +144,7 @@ static char *remove_end_comment(char *ptr); ...@@ -144,6 +144,7 @@ static char *remove_end_comment(char *ptr);
RETURN RETURN
0 ok 0 ok
1 given cinf_file doesn't exist 1 given cinf_file doesn't exist
2 out of memory
The global variable 'my_defaults_group_suffix' is updated with value for The global variable 'my_defaults_group_suffix' is updated with value for
--defaults_group_suffix --defaults_group_suffix
...@@ -190,7 +191,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, ...@@ -190,7 +191,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
if (!(extra_groups= if (!(extra_groups=
(const char**)alloc_root(ctx->alloc, (const char**)alloc_root(ctx->alloc,
(2*group->count+1)*sizeof(char*)))) (2*group->count+1)*sizeof(char*))))
goto err; DBUG_RETURN(2);
for (i= 0; i < group->count; i++) for (i= 0; i < group->count; i++)
{ {
...@@ -199,7 +200,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, ...@@ -199,7 +200,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
len= strlen(extra_groups[i]); len= strlen(extra_groups[i]);
if (!(ptr= alloc_root(ctx->alloc, len+instance_len+1))) if (!(ptr= alloc_root(ctx->alloc, len+instance_len+1)))
goto err; DBUG_RETURN(2);
extra_groups[i+group->count]= ptr; extra_groups[i+group->count]= ptr;
...@@ -254,12 +255,11 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, ...@@ -254,12 +255,11 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv,
} }
} }
DBUG_RETURN(error); DBUG_RETURN(0);
err: err:
fprintf(stderr,"Fatal error in defaults handling. Program aborted\n"); fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
exit(1); DBUG_RETURN(1);
return 0; /* Keep compiler happy */
} }
......
...@@ -85,8 +85,11 @@ char *my_tmpdir(MY_TMPDIR *tmpdir) ...@@ -85,8 +85,11 @@ char *my_tmpdir(MY_TMPDIR *tmpdir)
void free_tmpdir(MY_TMPDIR *tmpdir) void free_tmpdir(MY_TMPDIR *tmpdir)
{ {
uint i; uint i;
for (i=0; i<=tmpdir->max; i++) if (tmpdir->full_list.elements)
my_free(tmpdir->list[i], MYF(0)); {
for (i=0; i<=tmpdir->max; i++)
my_free(tmpdir->list[i], MYF(0));
}
delete_dynamic(&tmpdir->full_list); delete_dynamic(&tmpdir->full_list);
pthread_mutex_destroy(&tmpdir->mutex); pthread_mutex_destroy(&tmpdir->mutex);
} }
......
...@@ -100,10 +100,10 @@ static void default_reporter(enum loglevel level, ...@@ -100,10 +100,10 @@ static void default_reporter(enum loglevel level,
one. Call function 'get_one_option()' once for each option. 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, 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; getopt_get_addr= func_addr;
} }
...@@ -362,8 +362,12 @@ int handle_options(int *argc, char ***argv, ...@@ -362,8 +362,12 @@ int handle_options(int *argc, char ***argv,
my_progname, optp->name); my_progname, optp->name);
return EXIT_NO_ARGUMENT_ALLOWED; return EXIT_NO_ARGUMENT_ALLOWED;
} }
error= 0;
value= optp->var_type & GET_ASK_ADDR ? 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) if (optp->arg_type == NO_ARG)
{ {
...@@ -397,9 +401,10 @@ invalid value '%s'", ...@@ -397,9 +401,10 @@ invalid value '%s'",
my_progname, optp->name, optend); my_progname, optp->name, optend);
continue; continue;
} }
get_one_option(optp->id, optp, if (get_one_option(optp->id, optp,
*((my_bool*) value) ? *((my_bool*) value) ?
(char*) "1" : disabled_my_option); (char*) "1" : disabled_my_option))
return EXIT_UNSPECIFIED_ERROR;
continue; continue;
} }
argument= optend; argument= optend;
...@@ -457,7 +462,8 @@ invalid value '%s'", ...@@ -457,7 +462,8 @@ invalid value '%s'",
optp->arg_type == NO_ARG) optp->arg_type == NO_ARG)
{ {
*((my_bool*) optp->value)= (my_bool) 1; *((my_bool*) optp->value)= (my_bool) 1;
get_one_option(optp->id, optp, argument); if (get_one_option(optp->id, optp, argument))
return EXIT_UNSPECIFIED_ERROR;
continue; continue;
} }
else if (optp->arg_type == REQUIRED_ARG || else if (optp->arg_type == REQUIRED_ARG ||
...@@ -476,7 +482,8 @@ invalid value '%s'", ...@@ -476,7 +482,8 @@ invalid value '%s'",
{ {
if (optp->var_type == GET_BOOL) if (optp->var_type == GET_BOOL)
*((my_bool*) optp->value)= (my_bool) 1; *((my_bool*) optp->value)= (my_bool) 1;
get_one_option(optp->id, optp, argument); if (get_one_option(optp->id, optp, argument))
return EXIT_UNSPECIFIED_ERROR;
continue; continue;
} }
/* Check if there are more arguments after this one */ /* Check if there are more arguments after this one */
...@@ -501,7 +508,8 @@ invalid value '%s'", ...@@ -501,7 +508,8 @@ invalid value '%s'",
my_progname, argument, optp->name); my_progname, argument, optp->name);
return error; return error;
} }
get_one_option(optp->id, optp, argument); if (get_one_option(optp->id, optp, argument))
return EXIT_UNSPECIFIED_ERROR;
break; break;
} }
} }
...@@ -524,7 +532,8 @@ invalid value '%s'", ...@@ -524,7 +532,8 @@ invalid value '%s'",
my_progname, argument, optp->name); my_progname, argument, optp->name);
return error; return error;
} }
get_one_option(optp->id, optp, argument); if (get_one_option(optp->id, optp, argument))
return EXIT_UNSPECIFIED_ERROR;
(*argc)--; /* option handled (short or long), decrease argument count */ (*argc)--; /* option handled (short or long), decrease argument count */
} }
...@@ -1085,7 +1094,7 @@ static void init_variables(const struct my_option *options, ...@@ -1085,7 +1094,7 @@ static void init_variables(const struct my_option *options,
if (options->value) if (options->value)
init_one_value(options, options->value, options->def_value); init_one_value(options, options->value, options->def_value);
if (options->var_type & GET_ASK_ADDR && 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); init_one_value(options, variable, options->def_value);
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -1189,7 +1198,7 @@ void my_print_variables(const struct my_option *options) ...@@ -1189,7 +1198,7 @@ void my_print_variables(const struct my_option *options)
for (optp= options; optp->id; optp++) for (optp= options; optp->id; optp++)
{ {
uchar* *value= (optp->var_type & GET_ASK_ADDR ? 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) if (value)
{ {
printf("%s ", optp->name); printf("%s ", optp->name);
......
...@@ -2406,7 +2406,8 @@ extern "C" void unireg_abort(int exit_code) __attribute__((noreturn)); ...@@ -2406,7 +2406,8 @@ extern "C" void unireg_abort(int exit_code) __attribute__((noreturn));
void kill_delayed_threads(void); void kill_delayed_threads(void);
bool check_stack_overrun(THD *thd, long margin, uchar *dummy); bool check_stack_overrun(THD *thd, long margin, uchar *dummy);
#else #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) {} inline void kill_delayed_threads(void) {}
#define check_stack_overrun(A, B, C) 0 #define check_stack_overrun(A, B, C) 0
#endif #endif
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment