1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

fixed: memleak in --help, sigsegv on shutdown

Ingo's patch:
WL#2936 - Falcon & MySQL plugin interface: server variables
Added initialization for plugin string variables with their
default values.
Added deallocation of string values before a plugin and its
variables is deleted.
Added examples to plugin_example
This commit is contained in:
serg@sergbook.mysql.com
2007-04-26 21:26:04 +02:00
parent a90109dd2b
commit 31c1a1c9c3
4 changed files with 105 additions and 14 deletions

View File

@ -196,6 +196,7 @@ static bool register_builtin(struct st_mysql_plugin *, struct st_plugin_int *,
struct st_plugin_int **);
static void unlock_variables(THD *thd, struct system_variables *vars);
static void cleanup_variables(THD *thd, struct system_variables *vars);
static void plugin_vars_free_values(sys_var *vars);
static void plugin_opt_set_limits(struct my_option *options,
const struct st_mysql_sys_var *opt);
#define my_intern_plugin_lock(A,B) intern_plugin_lock(A,B CALLER_INFO)
@ -829,8 +830,11 @@ static void plugin_del(struct st_plugin_int *plugin)
{
DBUG_ENTER("plugin_del(plugin)");
safe_mutex_assert_owner(&LOCK_plugin);
/* Free allocated strings before deleting the plugin. */
plugin_vars_free_values(plugin->system_vars);
hash_delete(&plugin_hash[plugin->plugin->type], (byte*)plugin);
plugin_dl_del(&plugin->plugin_dl->dl);
if (plugin->plugin_dl)
plugin_dl_del(&plugin->plugin_dl->dl);
plugin->state= PLUGIN_IS_FREED;
plugin_array_version++;
rw_wrlock(&LOCK_system_variables_hash);
@ -1588,8 +1592,9 @@ bool mysql_install_plugin(THD *thd, const LEX_STRING *name, const LEX_STRING *dl
pthread_mutex_lock(&LOCK_plugin);
rw_wrlock(&LOCK_system_variables_hash);
argv[0]= ""; /* handle_options() assumes arg0 (program name) always exists */
argv[1]= NULL;
/* handle_options() assumes arg0 (program name) always exists */
argv[0]= const_cast<char*>(""); // without a cast gcc emits a warning
argv[1]= 0;
argc= 1;
error= plugin_add(thd->mem_root, name, dl, &argc, argv, REPORT_TO_USER);
rw_unlock(&LOCK_system_variables_hash);
@ -2171,6 +2176,17 @@ static st_bookmark *register_var(const char *plugin, const char *name,
max_system_variables.dynamic_variables_ptr=
my_realloc(max_system_variables.dynamic_variables_ptr, new_size,
MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
/*
Clear the new variable value space. This is required for string
variables. If their value is non-NULL, it must point to a valid
string.
*/
bzero(global_system_variables.dynamic_variables_ptr +
global_variables_dynamic_size,
new_size - global_variables_dynamic_size);
bzero(max_system_variables.dynamic_variables_ptr +
global_variables_dynamic_size,
new_size - global_variables_dynamic_size);
global_variables_dynamic_size= new_size;
}
@ -2311,6 +2327,9 @@ static void unlock_variables(THD *thd, struct system_variables *vars)
/*
Frees memory used by system variables
Unlike plugin_vars_free_values() it frees all variables of all plugins,
it's used on shutdown.
*/
static void cleanup_variables(THD *thd, struct system_variables *vars)
{
@ -2379,6 +2398,40 @@ void plugin_thdvar_cleanup(THD *thd)
}
/**
@brief Free values of thread variables of a plugin.
@detail This must be called before a plugin is deleted. Otherwise its
variables are no longer accessible and the value space is lost. Note
that only string values with PLUGIN_VAR_MEMALLOC are allocated and
must be freed.
@param[in] vars Chain of system variables of a plugin
*/
static void plugin_vars_free_values(sys_var *vars)
{
DBUG_ENTER("plugin_vars_free_values");
for (sys_var *var= vars; var; var= var->next)
{
sys_var_pluginvar *piv= var->cast_pluginvar();
if (piv &&
((piv->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR) &&
(piv->plugin_var->flags & PLUGIN_VAR_MEMALLOC))
{
/* Free the string from global_system_variables. */
char **valptr= (char**) piv->real_value_ptr(NULL, OPT_GLOBAL);
DBUG_PRINT("plugin", ("freeing value for: '%s' addr: 0x%lx",
var->name, (long) valptr));
my_free(*valptr, MYF(MY_WME | MY_FAE | MY_ALLOW_ZERO_PTR));
*valptr= NULL;
}
}
DBUG_VOID_RETURN;
}
bool sys_var_pluginvar::check_update_type(Item_result type)
{
if (is_readonly())
@ -2421,10 +2474,10 @@ SHOW_TYPE sys_var_pluginvar::show_type()
byte* sys_var_pluginvar::real_value_ptr(THD *thd, enum_var_type type)
{
DBUG_ASSERT(thd);
DBUG_ASSERT(thd || (type != OPT_SESSION));
if (plugin_var->flags & PLUGIN_VAR_THDLOCAL)
{
if (type == OPT_GLOBAL)
if (type != OPT_SESSION)
thd= NULL;
return intern_sys_var_ptr(thd, *(int*) (plugin_var+1), false);
@ -2614,7 +2667,9 @@ static void plugin_opt_set_limits(struct my_option *options,
options->def_value= *(my_bool*) ((void**)(opt + 1) + 1);
break;
case PLUGIN_VAR_STR:
options->var_type= GET_STR;
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
GET_STR_ALLOC : GET_STR);
options->def_value= (ulonglong)(intptr) *((char**) ((void**) (opt + 1) + 1));
break;
/* threadlocal variables */
case PLUGIN_VAR_INT | PLUGIN_VAR_THDLOCAL:
@ -2654,7 +2709,9 @@ static void plugin_opt_set_limits(struct my_option *options,
options->def_value= *(my_bool*) ((int*) (opt + 1) + 1);
break;
case PLUGIN_VAR_STR | PLUGIN_VAR_THDLOCAL:
options->var_type= GET_STR;
options->var_type= ((opt->flags & PLUGIN_VAR_MEMALLOC) ?
GET_STR_ALLOC : GET_STR);
options->def_value= (intptr) *((char**) ((void**) (opt + 1) + 1));
break;
default:
DBUG_ASSERT(0);