Skip to content

Commit 59f5157

Browse files
[release/6.0] Fix memory leak in enqueue/dequeue of EventPipe callback data. (#58244)
* Fix memory leak in enqueue/dequeue of EventPipe callback data. #56104 made sure provider callback data gets its own copy of filter data. This created a couple of memory leaks when queue/dequeue the callback data since callback data was not correctly freed in these scenarios leading to leaks of the copied filter data. Was detected running the manual EventPipe native unit tests on Windows using its build in use of _CrtMemCheckpoint (only available in debug builds) automatically detecting memory leaks. Fix makes sure callback data is moved into queue on enqueue and moved out in dequeue and that caller of dequeue make sure to free returned callback data using ep_provider_callback_data_fini when done using it. Doing a move instead of copy will also reduce the number of allocations when enqueue/dequeue callback data in provider callback queue. * Fix build error. Co-authored-by: lateralusX <lateralusx.github@gmail.com>
1 parent a021027 commit 59f5157

File tree

5 files changed

+70
-18
lines changed

5 files changed

+70
-18
lines changed

src/mono/mono/eventpipe/test/ep-provider-callback-dataqueue-tests.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,26 @@ test_provider_callback_data_queue (void)
4646
EventPipeProviderCallbackDataQueue callback_data_queue;
4747
EventPipeProviderCallbackDataQueue *provider_callback_data_queue = ep_provider_callback_data_queue_init (&callback_data_queue);
4848

49-
EventPipeProviderCallbackData enqueue_callback_data;
50-
EventPipeProviderCallbackData *provider_enqueue_callback_data = ep_provider_callback_data_init (
51-
&enqueue_callback_data,
52-
"",
53-
provider_callback,
54-
NULL,
55-
1,
56-
EP_EVENT_LEVEL_LOGALWAYS,
57-
true);
58-
59-
for (uint32_t i = 0; i < 1000; ++i)
49+
for (uint32_t i = 0; i < 1000; ++i) {
50+
EventPipeProviderCallbackData enqueue_callback_data;
51+
EventPipeProviderCallbackData *provider_enqueue_callback_data = ep_provider_callback_data_init (
52+
&enqueue_callback_data,
53+
"",
54+
provider_callback,
55+
NULL,
56+
1,
57+
EP_EVENT_LEVEL_LOGALWAYS,
58+
true);
6059
ep_provider_callback_data_queue_enqueue (provider_callback_data_queue, provider_enqueue_callback_data);
60+
ep_provider_callback_data_fini (provider_enqueue_callback_data);
61+
}
6162

6263
EventPipeProviderCallbackData dequeue_callback_data;
6364
uint32_t deque_counter = 0;
64-
while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &dequeue_callback_data))
65+
while (ep_provider_callback_data_queue_try_dequeue(provider_callback_data_queue, &dequeue_callback_data)) {
6566
deque_counter++;
67+
ep_provider_callback_data_fini (&dequeue_callback_data);
68+
}
6669

6770
if (deque_counter != 1000) {
6871
result = FAILED ("Unexpected number of provider callback invokes");

src/mono/mono/eventpipe/test/ep-tests.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ test_create_delete_provider_with_callback (void)
620620
EventPipeProvider *test_provider = NULL;
621621
EventPipeProviderConfiguration provider_config;
622622

623-
EventPipeProviderConfiguration *current_provider_config =ep_provider_config_init (&provider_config, TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOGALWAYS, "");
623+
EventPipeProviderConfiguration *current_provider_config = ep_provider_config_init (&provider_config, TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOGALWAYS, "");
624624
ep_raise_error_if_nok (current_provider_config != NULL);
625625

626626
test_location = 1;

src/native/eventpipe/ep-config.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ config_register_provider (
113113
EventPipeSessionProvider *session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_cref (providers), ep_provider_get_provider_name (provider));
114114
if (session_provider) {
115115
EventPipeProviderCallbackData provider_callback_data;
116+
memset (&provider_callback_data, 0, sizeof (provider_callback_data));
116117
provider_set_config (
117118
provider,
118119
keyword_for_all_sessions,
@@ -124,6 +125,7 @@ config_register_provider (
124125
&provider_callback_data);
125126
if (provider_callback_data_queue)
126127
ep_provider_callback_data_queue_enqueue (provider_callback_data_queue, &provider_callback_data);
128+
ep_provider_callback_data_fini (&provider_callback_data);
127129
}
128130
}
129131
}
@@ -179,6 +181,7 @@ ep_config_init (EventPipeConfiguration *config)
179181
while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) {
180182
ep_rt_prepare_provider_invoke_callback (&provider_callback_data);
181183
provider_invoke_callback (&provider_callback_data);
184+
ep_provider_callback_data_fini (&provider_callback_data);
182185
}
183186

184187
// Create the metadata event.
@@ -552,6 +555,7 @@ config_enable_disable (
552555
int64_t keyword_for_all_sessions;
553556
EventPipeEventLevel level_for_all_sessions;
554557
EventPipeProviderCallbackData provider_callback_data;
558+
memset (&provider_callback_data, 0, sizeof (provider_callback_data));
555559
config_compute_keyword_and_level (config, provider, &keyword_for_all_sessions, &level_for_all_sessions);
556560
if (enable) {
557561
provider_set_config (
@@ -576,6 +580,7 @@ config_enable_disable (
576580
}
577581
if (provider_callback_data_queue)
578582
ep_provider_callback_data_queue_enqueue (provider_callback_data_queue, &provider_callback_data);
583+
ep_provider_callback_data_fini (&provider_callback_data);
579584
}
580585
}
581586
}

src/native/eventpipe/ep-types.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ ep_provider_callback_data_alloc (
9696
EventPipeProviderCallbackData *
9797
ep_provider_callback_data_alloc_copy (EventPipeProviderCallbackData *provider_callback_data_src);
9898

99+
EventPipeProviderCallbackData *
100+
ep_provider_callback_data_alloc_move (EventPipeProviderCallbackData *provider_callback_data_src);
101+
99102
EventPipeProviderCallbackData *
100103
ep_provider_callback_data_init (
101104
EventPipeProviderCallbackData *provider_callback_data,
@@ -111,6 +114,11 @@ ep_provider_callback_data_init_copy (
111114
EventPipeProviderCallbackData *provider_callback_data_dst,
112115
EventPipeProviderCallbackData *provider_callback_data_src);
113116

117+
EventPipeProviderCallbackData *
118+
ep_provider_callback_data_init_move (
119+
EventPipeProviderCallbackData *provider_callback_data_dst,
120+
EventPipeProviderCallbackData *provider_callback_data_src);
121+
114122
void
115123
ep_provider_callback_data_fini (EventPipeProviderCallbackData *provider_callback_data);
116124

src/native/eventpipe/ep.c

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,26 @@ ep_provider_callback_data_alloc_copy (EventPipeProviderCallbackData *provider_ca
260260
ep_exit_error_handler ();
261261
}
262262

263+
EventPipeProviderCallbackData *
264+
ep_provider_callback_data_alloc_move (EventPipeProviderCallbackData *provider_callback_data_src)
265+
{
266+
EventPipeProviderCallbackData *instance = ep_rt_object_alloc (EventPipeProviderCallbackData);
267+
ep_raise_error_if_nok (instance != NULL);
268+
269+
if (provider_callback_data_src) {
270+
*instance = *provider_callback_data_src;
271+
memset (provider_callback_data_src, 0, sizeof (*provider_callback_data_src));
272+
}
273+
274+
ep_on_exit:
275+
return instance;
276+
277+
ep_on_error:
278+
ep_provider_callback_data_free (instance);
279+
instance = NULL;
280+
ep_exit_error_handler ();
281+
}
282+
263283
EventPipeProviderCallbackData *
264284
ep_provider_callback_data_init (
265285
EventPipeProviderCallbackData *provider_callback_data,
@@ -295,6 +315,19 @@ ep_provider_callback_data_init_copy (
295315
return provider_callback_data_dst;
296316
}
297317

318+
EventPipeProviderCallbackData *
319+
ep_provider_callback_data_init_move (
320+
EventPipeProviderCallbackData *provider_callback_data_dst,
321+
EventPipeProviderCallbackData *provider_callback_data_src)
322+
{
323+
EP_ASSERT (provider_callback_data_dst != NULL);
324+
EP_ASSERT (provider_callback_data_src != NULL);
325+
326+
*provider_callback_data_dst = *provider_callback_data_src;
327+
memset (provider_callback_data_src, 0, sizeof (*provider_callback_data_src));
328+
return provider_callback_data_dst;
329+
}
330+
298331
void
299332
ep_provider_callback_data_fini (EventPipeProviderCallbackData *provider_callback_data)
300333
{
@@ -621,6 +654,7 @@ disable_helper (EventPipeSessionID id)
621654
while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) {
622655
ep_rt_prepare_provider_invoke_callback (&provider_callback_data);
623656
provider_invoke_callback (&provider_callback_data);
657+
ep_provider_callback_data_fini (&provider_callback_data);
624658
}
625659

626660
ep_provider_callback_data_queue_fini (provider_callback_data_queue);
@@ -951,6 +985,7 @@ ep_enable (
951985
while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) {
952986
ep_rt_prepare_provider_invoke_callback (&provider_callback_data);
953987
provider_invoke_callback (&provider_callback_data);
988+
ep_provider_callback_data_fini (&provider_callback_data);
954989
}
955990

956991
ep_on_exit:
@@ -1185,6 +1220,7 @@ ep_create_provider (
11851220
while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) {
11861221
ep_rt_prepare_provider_invoke_callback (&provider_callback_data);
11871222
provider_invoke_callback (&provider_callback_data);
1223+
ep_provider_callback_data_fini (&provider_callback_data);
11881224
}
11891225

11901226
ep_rt_notify_profiler_provider_created (provider);
@@ -1556,14 +1592,14 @@ ep_provider_callback_data_queue_enqueue (
15561592
EventPipeProviderCallbackData *provider_callback_data)
15571593
{
15581594
EP_ASSERT (provider_callback_data_queue != NULL);
1559-
EventPipeProviderCallbackData *provider_callback_data_copy = ep_provider_callback_data_alloc_copy (provider_callback_data);
1560-
ep_raise_error_if_nok (provider_callback_data_copy != NULL);
1561-
ep_raise_error_if_nok (ep_rt_provider_callback_data_queue_push_tail (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue), provider_callback_data_copy));
1595+
EventPipeProviderCallbackData *provider_callback_data_move = ep_provider_callback_data_alloc_move (provider_callback_data);
1596+
ep_raise_error_if_nok (provider_callback_data_move != NULL);
1597+
ep_raise_error_if_nok (ep_rt_provider_callback_data_queue_push_tail (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue), provider_callback_data_move));
15621598

15631599
return true;
15641600

15651601
ep_on_error:
1566-
ep_provider_callback_data_free (provider_callback_data_copy);
1602+
ep_provider_callback_data_free (provider_callback_data_move);
15671603
return false;
15681604
}
15691605

@@ -1578,7 +1614,7 @@ ep_provider_callback_data_queue_try_dequeue (
15781614

15791615
EventPipeProviderCallbackData *value = NULL;
15801616
ep_raise_error_if_nok (ep_rt_provider_callback_data_queue_pop_head (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue), &value));
1581-
ep_provider_callback_data_init_copy (provider_callback_data, value);
1617+
ep_provider_callback_data_init_move (provider_callback_data, value);
15821618
ep_provider_callback_data_free (value);
15831619

15841620
return true;

0 commit comments

Comments
 (0)