List:Commits« Previous MessageNext Message »
From:Sergei Golubchik Date:May 4 2009 4:52pm
Subject:Re: bzr commit into mysql-5.1-bugteam branch
(kristofer.pettersson:2877) Bug#19027
View as plain text  
Hi, Kristofer!

On May 04, Kristofer Pettersson wrote:
> 
>  2877 Kristofer Pettersson	2009-05-04
>       Bug#19027 MySQL 5.0 starts even with Fatal InnoDB errors

Good.
I'm fine with hoe you removed 'enabled'.

But I think I've found a few bugs, see below - there's a memory
leak, incorrect default behavior, unjustified behavior change.
And a couple of smaller issues.

> === modified file 'sql/sql_plugin.cc'
> --- a/sql/sql_plugin.cc	2009-03-16 10:37:13 +0000
> +++ b/sql/sql_plugin.cc	2009-05-04 08:48:06 +0000
> @@ -29,6 +29,18 @@
>  
>  extern struct st_mysql_plugin *mysqld_builtins[];
>  
> +/**
> +  @note The order of the enumeration is critical.
> +  @see construct_options
> +*/
> +static const char *global_plugin_typelib_names[]=
> +  { "OFF", "ON", "FORCE", NULL };
> +enum plugin_load_policy_t {PLUGIN_OFF, PLUGIN_ON, PLUGIN_FORCE};
> +TYPELIB global_plugin_typelib= { array_elements(global_plugin_typelib_names)-1,

this should be static too (it's not needed outside of sql_plugin.cc)

> +                                 "", global_plugin_typelib_names,
> +                                 NULL };
> +
> +
>  char *opt_plugin_load= NULL;
>  char *opt_plugin_dir_ptr;
>  char opt_plugin_dir[FN_REFLEN];
> @@ -2889,21 +2901,39 @@ my_bool get_one_plugin_option(int optid 
>  }
>  
>  
> +/**
> +  Creates a set of my_option objects associated with a specified plugin-
> +  handle.
> +
> +  @param mem_root Memory allocator to be used.
> +  @param tmp A pointer to a plugin handle
> +  @param[out] options A pointer to a pre-allocated static array
> +
> +  The set is stored in the pre-allocated static array supplied to the function.
> +  The size of the array is calculated as (number_of_plugin_varaibles*2+3). The
> +  reason is that each option can have a prefix '--plugin-' in addtion to the
> +  shorter form '--<plugin-name>'. There is also space allocated for
> +  terminating NULL pointers.
> +
> +  @return
> +    @retval -1 An error occurred
> +    @retval 0 Success
> +*/
> +
>  static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
> -                             my_option *options, my_bool **enabled,
> -                             bool can_disable)
> +                             my_option *options)
>  {
>    const char *plugin_name= tmp->plugin->name;
>    uint namelen= strlen(plugin_name), optnamelen;
> -  uint buffer_length= namelen * 4 + (can_disable ? 75 : 10);
> -  char *name= (char*) alloc_root(mem_root, buffer_length) + 1;
> +  char *name= (char*) alloc_root(mem_root, namelen*2 + 10);
> +  const int comment_length= 80+(namelen*2+10)+strlen(plugin_name);

you have strlen(plugin_name) in namelen, no need to recalculate it

> +  char *comment= (char *) alloc_root(mem_root, comment_length);
> +
>    char *optname, *p;
>    int index= 0, offset= 0;
>    st_mysql_sys_var *opt, **plugin_option;
>    st_bookmark *v;
>    DBUG_ENTER("construct_options");
>  
>    /* support --skip-plugin-foo syntax */
>    memcpy(name, plugin_name, namelen + 1);
> @@ -2915,33 +2945,30 @@ static int construct_options(MEM_ROOT *m
>      if (*p == '_')
>        *p= '-';
>  
> -  if (can_disable)
> -  {
> -    strxmov(name + namelen*2 + 10, "Enable ", plugin_name, " plugin. "
> -            "Disable with --skip-", name," (will save memory).", NullS);
> -    /*
> -      Now we have namelen * 2 + 10 (one char unused) + 7 + namelen + 9 +
> -      20 + namelen + 20 + 1 == namelen * 4 + 67.
> -    */
> -
> -    options[0].comment= name + namelen*2 + 10;
> -  }
> +  options[1].name= (options[0].name= name) + namelen + 1;

I'd suggest to remove the hack of allocating many 'name' in one call -
it's in a memroot anyway, there's no win here. Better:

   options[0].name= (char*) alloc_root(mem_root, namelen);
   options[1].name= (char*) alloc_root(mem_root, namelen + 8);

even better, use a constant instead of 8:

  const LEX_STRING plugin_dash = { STRING_WITH_LEN("plugin-") };
  ...
  options[1].name= (char*) alloc_root(mem_root, namelen + plugin_dash.length);
  
> +  options[0].id= options[1].id= 256; /* must be >255. dup id ok */
> +  options[0].var_type= options[1].var_type= GET_ENUM;
> +  options[0].arg_type= options[1].arg_type= OPT_ARG;
> +  options[0].def_value= options[1].def_value= 1; /* ON */
> +  options[0].typelib= options[1].typelib= &global_plugin_typelib;
>
>    /*
> -    NOTE: 'name' is one char above the allocated buffer!
> -    NOTE: This code assumes that 'my_bool' and 'char' are of same size.
> +    NOTE: Make sure that comment doesn't become longer than comment_length

Why a "NOTE" ? What's wrong with strxnmov ?

>    */
> -  *((my_bool *)(name -1))= **enabled;
> -  *enabled= (my_bool *)(name - 1);
> +  strxmov(comment, "Enable or disable ", plugin_name, " plugin. "
> +          "Disable with --skip-", name," (will save memory).", NullS);
> +  options[0].comment= comment;
...
> @@ -3020,9 +3047,9 @@ static int construct_options(MEM_ROOT *m
>        if (!opt->update)
>        {
>          opt->update= update_func_str;
> -        if (!(opt->flags & PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY))
> +        if (!(opt->flags & (PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY)))
>          {
> -          opt->flags|= PLUGIN_VAR_READONLY;
> +          opt->flags|= (PLUGIN_VAR_READONLY);

I think this looks weird. Why the parentheses ?

>            sql_print_warning("Server variable %s of plugin %s was forced "
>                              "to be read-only: string variable without "
>                              "update_func and PLUGIN_VAR_MEMALLOC flag",
> @@ -3208,64 +3241,80 @@ static int test_plugin_options(MEM_ROOT 
>                         tmp->name.str);
>         goto err;
>      }
> +    /*
> +     Set plugin loading policy from option value. First element in the option
> +     list is always the <plugin name> option value.
> +    */
> +    plugin_load_policy= (plugin_load_policy_t)(uint)*opts[0].value;
> +    disable_plugin= (plugin_load_policy == PLUGIN_OFF);
>    }

uhm, I think this is wrong. You have your default (disable_plugin)
behavior only if handle_options() wasn't called.

You need to set the default value (in opts[] array) from disable_plugin.
Either pass it down to construct_options() like the old code did or fix
the value after construct_options like in

   opts[0].def_value= opts[1].def_value= disable_plugin;

> -  if (!*enabled && !can_disable)
> +  /*
> +    The 'MyISAM' and 'Memory' storage engines currently can't be disabled.
> +    TODO It really isn't possible to select --myisam=OFF as this option name
> +    isn't registered.

why is it not registered ?

> +  */
> +  can_disable=
> +    my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") &&
> +    my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY");
> +
> +  tmp->is_mandatory= (plugin_load_policy == PLUGIN_FORCE);
> +
> +  if (disable_plugin && !can_disable)
>    {
>      sql_print_warning("Plugin '%s' cannot be disabled", tmp->name.str);
> -    *enabled= TRUE;
> +    disable_plugin= FALSE;
>    }

I like the old behavior, when --help message reflected the fact that the
engine is mandatory. Perhaps, again, either pass can_disable down to
construct_options, or fix the array afterwards:

  if (!can_disable)
    opts[0].comment= 0; // hide disabling option from --help

> -  error= 1;
> -
> -  if (*enabled)
> +  /*
> +    If the plugin is disabled it should not be initialized.
> +  */
> +  if (disable_plugin)

you print the warning even if global_system_variables.log_warnings is 0,
old code wasn't. Why the change ?

>    {
> +    sql_print_information("Plugin '%s' is disabled.",
> +                          tmp->name.str);
> +    DBUG_RETURN(1);

by returning early you skip my_cleanup_options() call, which can cause
memoty leaks.

> +  }
> +
> +  error= 1;
>    for (opt= tmp->plugin->system_vars; opt && *opt; opt++)
>    {
>      if (((o= *opt)->flags & PLUGIN_VAR_NOSYSVAR))
>        continue;
> -
>      if ((var= find_bookmark(tmp->name.str, o->name, o->flags)))
>        v= new (mem_root) sys_var_pluginvar(var->key + 1, o);
>      else
>      {
>        len= tmp->name.length + strlen(o->name) + 2;
>        varname= (char*) alloc_root(mem_root, len);
>        strxmov(varname, tmp->name.str, "-", o->name, NullS);
>        my_casedn_str(&my_charset_latin1, varname);
> -
>        for (p= varname; *p; p++)
>          if (*p == '-')
>            *p= '_';
> -
>        v= new (mem_root) sys_var_pluginvar(varname, o);
>      }
>      DBUG_ASSERT(v); /* check that an object was actually constructed */
> -
>      /*
>        Add to the chain of variables.
>        Done like this for easier debugging so that the
>        pointer to v is not lost on optimized builds.
>      */
>      v->chain_sys_var(&chain);
> -  }
> +  } /* end for */
>      if (chain.first)
>      {
>        chain.last->next = NULL;
> @@ -3281,11 +3314,7 @@ static int test_plugin_options(MEM_ROOT 
>        tmp->system_vars= chain.first;
>      }
>      DBUG_RETURN(0);
> -  }
>  
> -  if (enabled_saved && global_system_variables.log_warnings)
> -    sql_print_information("Plugin '%s' disabled by command line option",
> -                          tmp->name.str);
>  err:
>    if (opts)
>      my_cleanup_options(opts);
> 
Regards / Mit vielen Grüßen,
Sergei

-- 
   __  ___     ___ ____  __
  /  |/  /_ __/ __/ __ \/ /   Sergei Golubchik <serg@stripped>
 / /|_/ / // /\ \/ /_/ / /__  Principal Software Engineer/Server Architect
/_/  /_/\_, /___/\___\_\___/  Sun Microsystems GmbH, HRB München 161028
       <___/                  Sonnenallee 1, 85551 Kirchheim-Heimstetten
Geschäftsführer: Thomas Schroeder, Wolfgang Engels, Dr. Roland Boemer
Vorsitzender des Aufsichtsrates: Martin Häring
Thread
bzr commit into mysql-5.1-bugteam branch (kristofer.pettersson:2877)Bug#19027Kristofer Pettersson4 May
  • Re: bzr commit into mysql-5.1-bugteam branch(kristofer.pettersson:2877) Bug#19027Sergei Golubchik4 May
    • Re: bzr commit into mysql-5.1-bugteam branch(kristofer.pettersson:2877) Bug#19027Kristofer Pettersson5 May
      • Re: bzr commit into mysql-5.1-bugteam branch(kristofer.pettersson:2877) Bug#19027Sergei Golubchik5 May