Skip to content

Commit 31be19d

Browse files
committed
Bug#14771682 PERFORMANCE SCHEMA LEAKS MEMORY ON SHUTDOWN
Currently, memory allocated for the performance schema is never freed, which causes valgrind warnings. To resolve completely the issue, two changes are needed: 1) Resolve bug#56666 Race condition between the server main thread and the kill server thread, which is the scope of WL#6407. 2) Fix the function cleanup_performance_schema() itself to free all memory used by the performance schema. This fix implements the second part only. Code is commented out using #ifdef HAVE_WL6407, while waiting for part 1). The function cleanup_performance_schema() has been tested (with #define HAVE_WL6407), which exposed some leaks, which have been all fixed. Executing unit tests under valgrind also exposed additional issues, all fixed in the unit tests.
1 parent 3727638 commit 31be19d

File tree

8 files changed

+190
-24
lines changed

8 files changed

+190
-24
lines changed

storage/perfschema/pfs_account.cc

+7-2
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,19 @@ int init_account(const PFS_global_param *param)
125125
return 0;
126126
}
127127

128-
/** Cleanup all the user buffers. */
128+
/** Cleanup all the account buffers. */
129129
void cleanup_account(void)
130130
{
131-
// FIXME, seems incomplete
132131
pfs_free(account_array);
133132
account_array= NULL;
134133
pfs_free(account_instr_class_waits_array);
135134
account_instr_class_waits_array= NULL;
135+
pfs_free(account_instr_class_stages_array);
136+
account_instr_class_stages_array= NULL;
137+
pfs_free(account_instr_class_statements_array);
138+
account_instr_class_statements_array= NULL;
139+
pfs_free(account_instr_class_memory_array);
140+
account_instr_class_memory_array= NULL;
136141
account_max= 0;
137142
}
138143

storage/perfschema/pfs_instr.cc

+6
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,12 @@ void cleanup_instruments(void)
547547
thread_statements_stack_array= NULL;
548548
pfs_free(thread_instr_class_waits_array);
549549
thread_instr_class_waits_array= NULL;
550+
pfs_free(thread_instr_class_stages_array);
551+
thread_instr_class_stages_array= NULL;
552+
pfs_free(thread_instr_class_statements_array);
553+
thread_instr_class_statements_array= NULL;
554+
pfs_free(thread_instr_class_memory_array);
555+
thread_instr_class_memory_array= NULL;
550556
pfs_free(global_instr_class_stages_array);
551557
global_instr_class_stages_array= NULL;
552558
pfs_free(global_instr_class_statements_array);

storage/perfschema/pfs_program.cc

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ void cleanup_program(void)
8888
/* Free memory allocated to program_array. */
8989
pfs_free(program_array);
9090
program_array= NULL;
91+
program_max= 0;
9192
}
9293

9394
C_MODE_START

storage/perfschema/pfs_server.cc

+80-19
Original file line numberDiff line numberDiff line change
@@ -168,39 +168,100 @@ static void destroy_pfs_thread(void *key)
168168

169169
static void cleanup_performance_schema(void)
170170
{
171+
/*
172+
my.cnf options
173+
*/
174+
171175
cleanup_instrument_config();
172-
/* Disabled: Bug#5666
173-
cleanup_instruments();
176+
177+
// Waiting for Bug#56666 / WL#6407
178+
//
179+
// #define HAVE_WL6407
180+
181+
#ifdef HAVE_WL6407
182+
183+
/*
184+
All the LF_HASH
185+
*/
186+
187+
cleanup_setup_actor_hash();
188+
cleanup_setup_object_hash();
189+
cleanup_account_hash();
190+
cleanup_host_hash();
191+
cleanup_user_hash();
192+
cleanup_program_hash();
193+
cleanup_table_share_hash();
194+
cleanup_file_hash();
195+
196+
/*
197+
Then the lookup tables
198+
*/
199+
200+
cleanup_setup_actor();
201+
cleanup_setup_object();
202+
203+
/*
204+
Then the history tables
205+
*/
206+
207+
cleanup_events_waits_history_long();
208+
cleanup_events_stages_history_long();
209+
cleanup_events_statements_history_long();
210+
211+
/*
212+
Then the various aggregations
213+
*/
214+
215+
cleanup_digest();
216+
cleanup_account();
217+
cleanup_host();
218+
cleanup_user();
219+
220+
/*
221+
Then the instrument classes.
222+
Once a class is cleaned up,
223+
find_XXX_class(key)
224+
will return PSI_NOT_INSTRUMENTED
225+
*/
226+
cleanup_program();
174227
cleanup_sync_class();
175228
cleanup_thread_class();
176229
cleanup_table_share();
177230
cleanup_file_class();
178231
cleanup_stage_class();
179232
cleanup_statement_class();
180233
cleanup_socket_class();
181-
cleanup_events_waits_history_long();
182-
cleanup_events_stages_history_long();
183-
cleanup_events_statements_history_long();
184-
cleanup_table_share_hash();
185-
cleanup_file_hash();
186-
cleanup_setup_actor();
187-
cleanup_setup_actor_hash();
188-
cleanup_setup_object();
189-
cleanup_setup_object_hash();
190-
cleanup_host();
191-
cleanup_host_hash();
192-
cleanup_user();
193-
cleanup_user_hash();
194-
cleanup_account();
195-
cleanup_account_hash();
196-
cleanup_digest();
234+
cleanup_memory_class();
235+
236+
cleanup_instruments();
237+
197238
PFS_atomic::cleanup();
198-
*/
239+
#endif
199240
}
200241

201242
void shutdown_performance_schema(void)
202243
{
203244
pfs_initialized= false;
245+
246+
/* disable everything, especially for this thread. */
247+
flag_events_stages_current= false;
248+
flag_events_stages_history= false;
249+
flag_events_stages_history_long= false;
250+
flag_events_statements_current= false;
251+
flag_events_statements_history= false;
252+
flag_events_statements_history_long= false;
253+
flag_events_waits_current= false;
254+
flag_events_waits_history= false;
255+
flag_events_waits_history_long= false;
256+
flag_global_instrumentation= false;
257+
flag_thread_instrumentation= false;
258+
flag_statements_digest= false;
259+
260+
global_table_io_class.m_enabled= false;
261+
global_table_lock_class.m_enabled= false;
262+
global_idle_class.m_enabled= false;
263+
global_metadata_class.m_enabled= false;
264+
204265
cleanup_performance_schema();
205266
#if 0
206267
/*

storage/perfschema/unittest/pfs-t.cc

+55-1
Original file line numberDiff line numberDiff line change
@@ -1633,6 +1633,8 @@ void test_event_name_index()
16331633
ok(global_table_io_class.m_event_name_index == 0, "index 0");
16341634
ok(global_table_lock_class.m_event_name_index == 1, "index 1");
16351635
ok(wait_class_max= 314, "314 event names"); // 4 global classes
1636+
1637+
shutdown_performance_schema();
16361638
}
16371639

16381640
void test_memory_instruments()
@@ -1720,6 +1722,57 @@ void test_memory_instruments()
17201722
shutdown_performance_schema();
17211723
}
17221724

1725+
void test_leaks()
1726+
{
1727+
PSI_bootstrap *boot;
1728+
PFS_global_param param;
1729+
1730+
/* Allocate everything, to make sure cleanup does not forget anything. */
1731+
1732+
memset(& param, 0xFF, sizeof(param));
1733+
param.m_enabled= true;
1734+
param.m_mutex_class_sizing= 10;
1735+
param.m_rwlock_class_sizing= 10;
1736+
param.m_cond_class_sizing= 10;
1737+
param.m_thread_class_sizing= 10;
1738+
param.m_table_share_sizing= 10;
1739+
param.m_file_class_sizing= 10;
1740+
param.m_socket_class_sizing= 10;
1741+
param.m_mutex_sizing= 1000;
1742+
param.m_rwlock_sizing= 1000;
1743+
param.m_cond_sizing= 1000;
1744+
param.m_thread_sizing= 1000;
1745+
param.m_table_sizing= 1000;
1746+
param.m_file_sizing= 1000;
1747+
param.m_file_handle_sizing= 1000;
1748+
param.m_socket_sizing= 1000;
1749+
param.m_events_waits_history_sizing= 10;
1750+
param.m_events_waits_history_long_sizing= 1000;
1751+
param.m_setup_actor_sizing= 1000;
1752+
param.m_setup_object_sizing= 1000;
1753+
param.m_host_sizing= 1000;
1754+
param.m_user_sizing= 1000;
1755+
param.m_account_sizing= 1000;
1756+
param.m_stage_class_sizing= 10;
1757+
param.m_events_stages_history_sizing= 10;
1758+
param.m_events_stages_history_long_sizing= 1000;
1759+
param.m_statement_class_sizing= 10;
1760+
param.m_events_statements_history_sizing= 10;
1761+
param.m_events_statements_history_long_sizing= 1000;
1762+
param.m_session_connect_attrs_sizing= 1000;
1763+
param.m_memory_class_sizing= 10;
1764+
param.m_metadata_lock_sizing= 1000;
1765+
param.m_digest_sizing= 1000;
1766+
param.m_program_sizing= 1000;
1767+
param.m_statement_stack_sizing= 10;
1768+
1769+
boot= initialize_performance_schema(& param);
1770+
ok(boot != NULL, "bootstrap");
1771+
shutdown_performance_schema();
1772+
1773+
/* Leaks will be reported with valgrind */
1774+
}
1775+
17231776
void do_all_tests()
17241777
{
17251778
/* Using initialize_performance_schema(), no partial init needed. */
@@ -1731,11 +1784,12 @@ void do_all_tests()
17311784
test_file_instrumentation_leak();
17321785
test_event_name_index();
17331786
test_memory_instruments();
1787+
test_leaks();
17341788
}
17351789

17361790
int main(int, char **)
17371791
{
1738-
plan(228);
1792+
plan(229);
17391793

17401794
MY_INIT("pfs-t");
17411795
do_all_tests();

0 commit comments

Comments
 (0)