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
1=== modified file 'Percona-Server/include/my_getopt.h'
2--- Percona-Server/include/my_getopt.h 2013-08-06 15:16:34 +0000
3+++ Percona-Server/include/my_getopt.h 2013-10-08 16:56:57 +0000
4@@ -114,6 +114,7 @@
5 my_get_one_option,
6 const char **command_list);
7 extern void my_cleanup_options(const struct my_option *options);
8+extern void my_handle_options_end();
9 extern void my_cleanup_options(const struct my_option *options);
10 extern void my_print_help(const struct my_option *options);
11 extern void my_print_variables(const struct my_option *options);
12
13=== modified file 'Percona-Server/mysql-test/r/percona_enhanced_options_modifiers.result'
14--- Percona-Server/mysql-test/r/percona_enhanced_options_modifiers.result 2012-08-07 18:49:16 +0000
15+++ Percona-Server/mysql-test/r/percona_enhanced_options_modifiers.result 2013-10-08 16:56:57 +0000
16@@ -112,9 +112,11 @@
17 @@GLOBAL.INNODB_IO_CAPACITY
18 150
19 SET @@GLOBAL.INNODB_IO_CAPACITY=300;
20+Warnings:
21+Warning 1292 Truncated incorrect innodb_io_capacity value: '300'
22 SELECT @@GLOBAL.INNODB_IO_CAPACITY;
23 @@GLOBAL.INNODB_IO_CAPACITY
24-300
25+200
26 SET @@GLOBAL.INNODB_IO_CAPACITY=160;
27 SELECT @@GLOBAL.INNODB_IO_CAPACITY;
28 @@GLOBAL.INNODB_IO_CAPACITY
29
30=== modified file 'Percona-Server/mysys_ssl/my_getopt.cc'
31--- Percona-Server/mysys_ssl/my_getopt.cc 2013-08-14 03:57:21 +0000
32+++ Percona-Server/mysys_ssl/my_getopt.cc 2013-10-08 16:56:57 +0000
33@@ -121,18 +121,19 @@
34 my_free(moc);
35 }
36
37+static HASH my_option_constraints;
38+static my_bool my_option_constraints_inited= FALSE;
39+
40 static HASH *getopt_constraint_init(my_bool create)
41 {
42- static HASH my_option_constraints;
43- static int my_option_constraints_inited= 0;
44-
45+
46 if (!my_option_constraints_inited && create)
47 {
48 my_hash_init(&my_option_constraints, &my_charset_utf8_general_ci,
49 20, 0, 0,
50 (my_hash_get_key) getopt_constraint_get_name,
51 (void (*)(void *))getopt_constraint_free, HASH_UNIQUE);
52- my_option_constraints_inited= 1;
53+ my_option_constraints_inited= TRUE;
54 return &my_option_constraints;
55 }
56 else if (my_option_constraints_inited)
57@@ -148,6 +149,8 @@
58 {
59 HASH *opts;
60 struct my_option_constraint *moc;
61+ char* pos;
62+ char *normalized_name;
63
64 opts= getopt_constraint_init(create);
65 if (!opts)
66@@ -155,28 +158,33 @@
67
68 if (length == 0)
69 length= strlen(name);
70-
71+
72+ normalized_name= my_strdup(name, MYF(MY_WME));
73+ for (pos= normalized_name; *pos; pos++)
74+ {
75+ if (*pos == '-')
76+ *pos= '_';
77+ }
78+
79 moc= (struct my_option_constraint *) my_hash_search(opts,
80- (const uchar*) name,
81+ (const uchar*) normalized_name,
82 length);
83
84 if (!moc && create)
85 {
86- char* pos;
87 moc= (struct my_option_constraint *) my_malloc(
88 sizeof(struct my_option_constraint),
89 MYF(MY_WME | MY_ZEROFILL));
90
91- moc->name= my_strdup(name, MYF(MY_WME));
92- for (pos= moc->name; *pos; pos++)
93- {
94- if (*pos == '-')
95- *pos= '_';
96- }
97+ moc->name= normalized_name;
98 moc->length= length;
99-
100+
101 my_hash_insert(opts, (uchar*) moc);
102 }
103+ else
104+ {
105+ my_free(normalized_name);
106+ }
107 return moc;
108 }
109
110@@ -191,7 +199,7 @@
111 moc->min_value= my_malloc(create, MYF(MY_WME | MY_ZEROFILL));
112
113 if (moc && moc->min_value)
114- return &moc->min_value;
115+ return moc->min_value;
116
117 return NULL;
118 }
119@@ -207,7 +215,7 @@
120 moc->max_value= my_malloc(create, MYF(MY_WME | MY_ZEROFILL));
121
122 if (moc && moc->max_value)
123- return &moc->max_value;
124+ return moc->max_value;
125
126 return NULL;
127 }
128@@ -867,6 +875,19 @@
129
130
131 /*
132+ Clean up any allocations made during handle_options on shutdown.
133+*/
134+void my_handle_options_end()
135+{
136+ if (my_option_constraints_inited)
137+ {
138+ my_hash_free(&my_option_constraints);
139+ my_option_constraints_inited= FALSE;
140+ }
141+}
142+
143+
144+/*
145 function: check_struct_option
146
147 Arguments: Current argument under processing from argv and a variable
148
149=== modified file 'Percona-Server/sql/mysqld.cc'
150--- Percona-Server/sql/mysqld.cc 2013-10-01 13:00:50 +0000
151+++ Percona-Server/sql/mysqld.cc 2013-10-08 16:56:57 +0000
152@@ -1915,6 +1915,8 @@
153 if (THR_MALLOC)
154 (void) pthread_key_delete(THR_MALLOC);
155
156+ my_handle_options_end();
157+
158 /*
159 The following lines may never be executed as the main thread may have
160 killed us

Subscribers

People subscribed via source and target branches