Merge lp:~gl-az/percona-server/BT-23598-bug1167487-5.6 into lp:percona-server/5.6

Proposed by George Ormond Lorch III
Status: Merged
Approved by: Laurynas Biveinis
Approved revision: no longer in the source branch.
Merged at revision: 468
Proposed branch: lp:~gl-az/percona-server/BT-23598-bug1167487-5.6
Merge into: lp:percona-server/5.6
Diff against target: 160 lines (+43/-17)
4 files modified
Percona-Server/include/my_getopt.h (+1/-0)
Percona-Server/mysql-test/r/percona_enhanced_options_modifiers.result (+3/-1)
Percona-Server/mysys_ssl/my_getopt.cc (+37/-16)
Percona-Server/sql/mysqld.cc (+2/-0)
To merge this branch: bzr merge lp:~gl-az/percona-server/BT-23598-bug1167487-5.6
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) Approve
Review via email: mp+187664@code.launchpad.net

Description of the change

Merged from 5.5:
Fix for https://bugs.launchpad.net/percona-server/+bug/1167487 -Enhanced option modifiers do not deallocate memory | Valgrind: getopt_constraint_get_min_value and getopt_constraint_find definitely lost / still reachable

Originally this was just written off as a known, one time leak, which is is, but the failure causes scripted testing to fail and is really just sloppy.

To fix, a new path needed to be created from mysqld main() through my_cleanup and into the my_getopt.c to properly free the options modifiers structures created and saved during option parsing.
A new function was created called handle_options_end() which is called from cleanup() in mysqld.cc. handle_options_end() calls getopt_constraint_deinit() to signal it that it needs to free its internal static data.
getopt_constraint_init() used to contain a static hash table and initialization flag. These were moved out to global scope so that getopt_constraint_deinit() could have access to them.

While testing, a bad memory read/write was discovered in the min and max constraints which caused a crash during freeing of the constraints structs on shutdown. That has been fixed.

While testing, discovered a bug that caused incorrect behavior, reported as https://bugs.launchpad.net/percona-server/+bug/1233294 - certain option modifiers do not have effect
The my_option_constraints hash is hashed on the option name. Option names are normalized ('-' made '_') before inserting into the hash since 'finds' get called from both main where names have not been transformed and from plugins and other places where the names have been transformed.
The issue is that the searches were performed with non-normalized names, so the find function would not find a record for the same option name (innodb_io_capacity vs innodb-io-capacity). It would then create a new record, transform the name and attempt insertion, which would fail silently due to duplicate.
The new record would be returned and used for that particular constraint setting but would be leaked because it did not exist in the hash. The constraing is then not 'recorded' so any attempt to set outside of the constraint would succeed.
Fixed by transforming the name before looking up the constraint in the hash.

To post a comment you must log in.
Revision history for this message
George Ormond Lorch III (gl-az) wrote :

http://jenkins.percona.com/view/PS%205.6/job/percona-server-5.6-param/309/

Same as mentioned in 5.5 MP, there are a few different failures from prior jenkins runs but have nothing to do w/ this fix. Please take a bit of a close look (I already did) to double check my work and make sure nothing was introduced.

Revision history for this message
George Ormond Lorch III (gl-az) wrote :
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

Same comment as for 5.5 MP.

review: Approve
Revision history for this message
George Ormond Lorch III (gl-az) wrote :

New bug link added

Revision history for this message
George Ormond Lorch III (gl-az) wrote :

Same as 5.5, fixed up commit message and touched up MP description.

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Percona-Server/include/my_getopt.h'
--- Percona-Server/include/my_getopt.h 2013-08-06 15:16:34 +0000
+++ Percona-Server/include/my_getopt.h 2013-10-08 16:56:57 +0000
@@ -114,6 +114,7 @@
114 my_get_one_option,114 my_get_one_option,
115 const char **command_list);115 const char **command_list);
116extern void my_cleanup_options(const struct my_option *options);116extern void my_cleanup_options(const struct my_option *options);
117extern void my_handle_options_end();
117extern void my_cleanup_options(const struct my_option *options);118extern void my_cleanup_options(const struct my_option *options);
118extern void my_print_help(const struct my_option *options);119extern void my_print_help(const struct my_option *options);
119extern void my_print_variables(const struct my_option *options);120extern void my_print_variables(const struct my_option *options);
120121
=== modified file 'Percona-Server/mysql-test/r/percona_enhanced_options_modifiers.result'
--- Percona-Server/mysql-test/r/percona_enhanced_options_modifiers.result 2012-08-07 18:49:16 +0000
+++ Percona-Server/mysql-test/r/percona_enhanced_options_modifiers.result 2013-10-08 16:56:57 +0000
@@ -112,9 +112,11 @@
112@@GLOBAL.INNODB_IO_CAPACITY112@@GLOBAL.INNODB_IO_CAPACITY
113150113150
114SET @@GLOBAL.INNODB_IO_CAPACITY=300;114SET @@GLOBAL.INNODB_IO_CAPACITY=300;
115Warnings:
116Warning 1292 Truncated incorrect innodb_io_capacity value: '300'
115SELECT @@GLOBAL.INNODB_IO_CAPACITY;117SELECT @@GLOBAL.INNODB_IO_CAPACITY;
116@@GLOBAL.INNODB_IO_CAPACITY118@@GLOBAL.INNODB_IO_CAPACITY
117300119200
118SET @@GLOBAL.INNODB_IO_CAPACITY=160;120SET @@GLOBAL.INNODB_IO_CAPACITY=160;
119SELECT @@GLOBAL.INNODB_IO_CAPACITY;121SELECT @@GLOBAL.INNODB_IO_CAPACITY;
120@@GLOBAL.INNODB_IO_CAPACITY122@@GLOBAL.INNODB_IO_CAPACITY
121123
=== modified file 'Percona-Server/mysys_ssl/my_getopt.cc'
--- Percona-Server/mysys_ssl/my_getopt.cc 2013-08-14 03:57:21 +0000
+++ Percona-Server/mysys_ssl/my_getopt.cc 2013-10-08 16:56:57 +0000
@@ -121,18 +121,19 @@
121 my_free(moc);121 my_free(moc);
122}122}
123123
124static HASH my_option_constraints;
125static my_bool my_option_constraints_inited= FALSE;
126
124static HASH *getopt_constraint_init(my_bool create)127static HASH *getopt_constraint_init(my_bool create)
125{128{
126 static HASH my_option_constraints;129
127 static int my_option_constraints_inited= 0;
128
129 if (!my_option_constraints_inited && create)130 if (!my_option_constraints_inited && create)
130 {131 {
131 my_hash_init(&my_option_constraints, &my_charset_utf8_general_ci,132 my_hash_init(&my_option_constraints, &my_charset_utf8_general_ci,
132 20, 0, 0,133 20, 0, 0,
133 (my_hash_get_key) getopt_constraint_get_name,134 (my_hash_get_key) getopt_constraint_get_name,
134 (void (*)(void *))getopt_constraint_free, HASH_UNIQUE);135 (void (*)(void *))getopt_constraint_free, HASH_UNIQUE);
135 my_option_constraints_inited= 1;136 my_option_constraints_inited= TRUE;
136 return &my_option_constraints;137 return &my_option_constraints;
137 }138 }
138 else if (my_option_constraints_inited)139 else if (my_option_constraints_inited)
@@ -148,6 +149,8 @@
148{149{
149 HASH *opts;150 HASH *opts;
150 struct my_option_constraint *moc;151 struct my_option_constraint *moc;
152 char* pos;
153 char *normalized_name;
151154
152 opts= getopt_constraint_init(create);155 opts= getopt_constraint_init(create);
153 if (!opts)156 if (!opts)
@@ -155,28 +158,33 @@
155 158
156 if (length == 0)159 if (length == 0)
157 length= strlen(name);160 length= strlen(name);
158 161
162 normalized_name= my_strdup(name, MYF(MY_WME));
163 for (pos= normalized_name; *pos; pos++)
164 {
165 if (*pos == '-')
166 *pos= '_';
167 }
168
159 moc= (struct my_option_constraint *) my_hash_search(opts,169 moc= (struct my_option_constraint *) my_hash_search(opts,
160 (const uchar*) name,170 (const uchar*) normalized_name,
161 length);171 length);
162172
163 if (!moc && create)173 if (!moc && create)
164 {174 {
165 char* pos;
166 moc= (struct my_option_constraint *) my_malloc(175 moc= (struct my_option_constraint *) my_malloc(
167 sizeof(struct my_option_constraint),176 sizeof(struct my_option_constraint),
168 MYF(MY_WME | MY_ZEROFILL));177 MYF(MY_WME | MY_ZEROFILL));
169178
170 moc->name= my_strdup(name, MYF(MY_WME));179 moc->name= normalized_name;
171 for (pos= moc->name; *pos; pos++)
172 {
173 if (*pos == '-')
174 *pos= '_';
175 }
176 moc->length= length;180 moc->length= length;
177 181
178 my_hash_insert(opts, (uchar*) moc);182 my_hash_insert(opts, (uchar*) moc);
179 }183 }
184 else
185 {
186 my_free(normalized_name);
187 }
180 return moc;188 return moc;
181}189}
182190
@@ -191,7 +199,7 @@
191 moc->min_value= my_malloc(create, MYF(MY_WME | MY_ZEROFILL));199 moc->min_value= my_malloc(create, MYF(MY_WME | MY_ZEROFILL));
192200
193 if (moc && moc->min_value)201 if (moc && moc->min_value)
194 return &moc->min_value;202 return moc->min_value;
195203
196 return NULL;204 return NULL;
197}205}
@@ -207,7 +215,7 @@
207 moc->max_value= my_malloc(create, MYF(MY_WME | MY_ZEROFILL));215 moc->max_value= my_malloc(create, MYF(MY_WME | MY_ZEROFILL));
208216
209 if (moc && moc->max_value)217 if (moc && moc->max_value)
210 return &moc->max_value;218 return moc->max_value;
211219
212 return NULL;220 return NULL;
213}221}
@@ -867,6 +875,19 @@
867875
868876
869/*877/*
878 Clean up any allocations made during handle_options on shutdown.
879*/
880void my_handle_options_end()
881{
882 if (my_option_constraints_inited)
883 {
884 my_hash_free(&my_option_constraints);
885 my_option_constraints_inited= FALSE;
886 }
887}
888
889
890/*
870 function: check_struct_option891 function: check_struct_option
871892
872 Arguments: Current argument under processing from argv and a variable893 Arguments: Current argument under processing from argv and a variable
873894
=== modified file 'Percona-Server/sql/mysqld.cc'
--- Percona-Server/sql/mysqld.cc 2013-10-01 13:00:50 +0000
+++ Percona-Server/sql/mysqld.cc 2013-10-08 16:56:57 +0000
@@ -1915,6 +1915,8 @@
1915 if (THR_MALLOC)1915 if (THR_MALLOC)
1916 (void) pthread_key_delete(THR_MALLOC);1916 (void) pthread_key_delete(THR_MALLOC);
19171917
1918 my_handle_options_end();
1919
1918 /*1920 /*
1919 The following lines may never be executed as the main thread may have1921 The following lines may never be executed as the main thread may have
1920 killed us1922 killed us

Subscribers

People subscribed via source and target branches