From: Sergey Vojtovich Date: November 10 2011 9:57am Subject: bzr push into mysql-trunk branch (sergey.vojtovich:3586 to 3588) List-Archive: http://lists.mysql.com/commits/141807 Message-Id: <201111100956.pAA9uC3N027367@acsmt358.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3588 Sergey Vojtovich 2011-11-10 [merge] (no message) 3587 Sergey Vojtovich 2011-11-10 [merge] (no message) modified: sql/sql_class.h sql/sql_plugin.cc 3586 Raghav Kapoor 2011-11-10 BUG#11761014 - 53466: END_CONNECTION() SHOULD REFERENCE GLOBAL_SYSTEM_VARIABLES.LOG_WARNINGS BACKGROUND: end_connection prints out messages like this, depending on *session* log_warnings value: Aborted connection 2 to db: 'unconnected' user: 'root' host: '' (Got timeout reading communication packets). This is wrong because it allows a minimally privileged user to write copious amounts of errors to the .err file, unless he is restricted by the number of MAX_CONNECTIONS_PER_HOUR in his user account. FIX: "Aborted connection..." messages are now printed based on the *global* log_warnings value. Since this was the only real remaining use of the session value of log_warnings, the log_warnings system variable has now been made to a global only variable. This is a change of behavior and must be reflected in the documentation. modified: mysql-test/r/variables.result mysql-test/suite/sys_vars/inc/log_warnings_basic.inc mysql-test/suite/sys_vars/r/log_warnings_basic_32.result mysql-test/suite/sys_vars/r/log_warnings_basic_64.result mysql-test/t/variables.test sql/binlog.cc sql/filesort.cc sql/log_event.cc sql/mysqld.cc sql/mysqld.h sql/rpl_reporting.cc sql/rpl_rli_pdb.cc sql/rpl_slave.cc sql/sql_acl.cc sql/sql_class.h sql/sql_connect.cc sql/sql_plugin.cc sql/sql_udf.cc sql/sys_vars.cc storage/innobase/handler/ha_innodb.cc === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2011-11-10 06:53:27 +0000 +++ b/sql/sql_class.h 2011-11-10 09:55:20 +0000 @@ -435,8 +435,9 @@ typedef struct system_variables */ ulong dynamic_variables_version; char* dynamic_variables_ptr; - uint dynamic_variables_head; /* largest valid variable offset */ - uint dynamic_variables_size; /* how many bytes are in use */ + uint dynamic_variables_head; /* largest valid variable offset */ + uint dynamic_variables_size; /* how many bytes are in use */ + LIST *dynamic_variables_allocs; /* memory hunks for PLUGIN_VAR_MEMALLOC */ ulonglong max_heap_table_size; ulonglong tmp_table_size; === modified file 'sql/sql_plugin.cc' --- a/sql/sql_plugin.cc 2011-11-10 06:53:27 +0000 +++ b/sql/sql_plugin.cc 2011-11-10 09:55:20 +0000 @@ -261,6 +261,13 @@ static bool register_builtin(struct st_m 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 bool plugin_var_memalloc_session_update(THD *thd, + struct st_mysql_sys_var *var, + char **dest, const char *value); +static bool plugin_var_memalloc_global_update(THD *thd, + struct st_mysql_sys_var *var, + char **dest, const char *value); +static void plugin_var_memalloc_free(struct system_variables *vars); static void restore_pluginvar_names(sys_var *first); static void plugin_opt_set_limits(struct my_option *, const struct st_mysql_sys_var *); @@ -2317,15 +2324,7 @@ static void update_func_longlong(THD *th static void update_func_str(THD *thd, struct st_mysql_sys_var *var, void *tgt, const void *save) { - char *old= *(char **) tgt; - *(char **)tgt= *(char **) save; - if (var->flags & PLUGIN_VAR_MEMALLOC) - { - if (*(char **) save != NULL) { - *(char **)tgt= my_strdup(*(char **) save, MYF(0)); - } - my_free(old); - } + *(char **) tgt= *(char **) save; } @@ -2584,11 +2583,13 @@ static uchar *intern_sys_var_ptr(THD* th if ((pi->plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR && pi->plugin_var->flags & PLUGIN_VAR_MEMALLOC) { - char **pp= (char**) (thd->variables.dynamic_variables_ptr + - *(int*)(pi->plugin_var + 1)); - if ((*pp= *(char**) (global_system_variables.dynamic_variables_ptr + - *(int*)(pi->plugin_var + 1)))) - *pp= my_strdup(*pp, MYF(MY_WME|MY_FAE)); + int varoff= *(int *) (pi->plugin_var + 1); + char **thdvar= (char **) (thd->variables. + dynamic_variables_ptr + varoff); + char **sysvar= (char **) (global_system_variables. + dynamic_variables_ptr + varoff); + *thdvar= NULL; + plugin_var_memalloc_session_update(thd, NULL, thdvar, *sysvar); } } @@ -2705,33 +2706,8 @@ static void unlock_variables(THD *thd, s */ static void cleanup_variables(THD *thd, struct system_variables *vars) { - st_bookmark *v; - sys_var_pluginvar *pivar; - sys_var *var; - int flags; - uint idx; - - mysql_rwlock_rdlock(&LOCK_system_variables_hash); - for (idx= 0; idx < bookmark_hash.records; idx++) - { - v= (st_bookmark*) my_hash_element(&bookmark_hash, idx); - if (v->version > vars->dynamic_variables_version || - !(var= intern_find_sys_var(v->key + 1, v->name_len)) || - !(pivar= var->cast_pluginvar()) || - v->key[0] != (pivar->plugin_var->flags & PLUGIN_VAR_TYPEMASK)) - continue; - - flags= pivar->plugin_var->flags; - - if ((flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR && - flags & PLUGIN_VAR_THDLOCAL && flags & PLUGIN_VAR_MEMALLOC) - { - char **ptr= (char**) pivar->real_value_ptr(thd, OPT_SESSION); - my_free(*ptr); - *ptr= NULL; - } - } - mysql_rwlock_unlock(&LOCK_system_variables_hash); + if (thd) + plugin_var_memalloc_free(&thd->variables); DBUG_ASSERT(vars->table_plugin == NULL); DBUG_ASSERT(vars->temp_table_plugin == NULL); @@ -2827,6 +2803,136 @@ static SHOW_TYPE pluginvar_show_type(st_ } +/** + Set value for thread local variable with PLUGIN_VAR_MEMALLOC flag. + + @param[in] thd Thread context. + @param[in] var Plugin variable. + @param[in,out] dest Destination memory pointer. + @param[in] value '\0'-terminated new value. + + Most plugin variable values are stored on dynamic_variables_ptr. + Releasing memory occupied by these values is as simple as freeing + dynamic_variables_ptr. + + An exception to the rule are PLUGIN_VAR_MEMALLOC variables, which + are stored on individual memory hunks. All of these hunks has to + be freed when it comes to cleanup. + + It may happen that a plugin was uninstalled and descriptors of + it's variables are lost. In this case it is impossible to locate + corresponding values. + + In addition to allocating and setting variable value, new element + is added to dynamic_variables_allocs list. When thread is done, it + has to call plugin_var_memalloc_free() to release memory used by + PLUGIN_VAR_MEMALLOC variables. + + If var is NULL, variable update function is not called. This is + needed when we take snapshot of system variables during thread + initialization. + + @note List element and variable value are stored on the same memory + hunk. List element is followed by variable value. + + @return Completion status + @retval false Success + @retval true Failure +*/ + +static bool plugin_var_memalloc_session_update(THD *thd, + struct st_mysql_sys_var *var, + char **dest, const char *value) + +{ + LIST *old_element= NULL; + struct system_variables *vars= &thd->variables; + DBUG_ENTER("plugin_var_memalloc_session_update"); + + if (value) + { + size_t length= strlen(value) + 1; + LIST *element; + if (!(element= (LIST *) my_malloc(sizeof(LIST) + length, MYF(MY_WME)))) + DBUG_RETURN(true); + memcpy(element + 1, value, length); + value= (const char *) (element + 1); + vars->dynamic_variables_allocs= list_add(vars->dynamic_variables_allocs, + element); + } + + if (*dest) + old_element= (LIST *) (*dest - sizeof(LIST)); + + if (var) + var->update(thd, var, (void **) dest, (const void *) &value); + else + *dest= (char *) value; + + if (old_element) + { + vars->dynamic_variables_allocs= list_delete(vars->dynamic_variables_allocs, + old_element); + my_free(old_element); + } + DBUG_RETURN(false); +} + + +/** + Free all elements allocated by plugin_var_memalloc_session_update(). + + @param[in] vars system variables structure + + @see plugin_var_memalloc_session_update +*/ + +static void plugin_var_memalloc_free(struct system_variables *vars) +{ + LIST *next, *root; + DBUG_ENTER("plugin_var_memalloc_free"); + for (root= vars->dynamic_variables_allocs; root; root= next) + { + next= root->next; + my_free(root); + } + vars->dynamic_variables_allocs= NULL; + DBUG_VOID_RETURN; +} + + +/** + Set value for global variable with PLUGIN_VAR_MEMALLOC flag. + + @param[in] thd Thread context. + @param[in] var Plugin variable. + @param[in,out] dest Destination memory pointer. + @param[in] value '\0'-terminated new value. + + @return Completion status + @retval false Success + @retval true Failure +*/ + +static bool plugin_var_memalloc_global_update(THD *thd, + struct st_mysql_sys_var *var, + char **dest, const char *value) +{ + char *old_value= *dest; + DBUG_ENTER("plugin_var_memalloc_global_update"); + + if (value && !(value= my_strdup(value, MYF(MY_WME)))) + DBUG_RETURN(true); + + var->update(thd, var, (void **) dest, (const void *) &value); + + if (old_value) + my_free(old_value); + + DBUG_RETURN(false); +} + + bool sys_var_pluginvar::check_update_type(Item_result type) { switch (plugin_var->flags & PLUGIN_VAR_TYPEMASK) { @@ -2911,6 +3017,7 @@ bool sys_var_pluginvar::do_check(THD *th bool sys_var_pluginvar::session_update(THD *thd, set_var *var) { + bool rc= false; DBUG_ASSERT(!is_readonly()); DBUG_ASSERT(plugin_var->flags & PLUGIN_VAR_THDLOCAL); DBUG_ASSERT(thd == current_thd); @@ -2920,13 +3027,20 @@ bool sys_var_pluginvar::session_update(T const void *src= var->value ? (void*)&var->save_result : (void*)real_value_ptr(thd, OPT_GLOBAL); mysql_mutex_unlock(&LOCK_global_system_variables); - plugin_var->update(thd, plugin_var, tgt, src); - return false; + if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR && + plugin_var->flags & PLUGIN_VAR_MEMALLOC) + rc= plugin_var_memalloc_session_update(thd, plugin_var, (char **) tgt, + *(const char **) src); + else + plugin_var->update(thd, plugin_var, tgt, src); + + return rc; } bool sys_var_pluginvar::global_update(THD *thd, set_var *var) { + bool rc= false; DBUG_ASSERT(!is_readonly()); mysql_mutex_assert_owner(&LOCK_global_system_variables); @@ -2983,9 +3097,14 @@ bool sys_var_pluginvar::global_update(TH } } - plugin_var->update(thd, plugin_var, tgt, src); + if ((plugin_var->flags & PLUGIN_VAR_TYPEMASK) == PLUGIN_VAR_STR && + plugin_var->flags & PLUGIN_VAR_MEMALLOC) + rc= plugin_var_memalloc_global_update(thd, plugin_var, (char **) tgt, + *(const char **) src); + else + plugin_var->update(thd, plugin_var, tgt, src); - return false; + return rc; } No bundle (reason: useless for push emails).