diff --git a/src/native/eventpipe/ep-provider.c b/src/native/eventpipe/ep-provider.c index 0c4f4441bba567..cf7d9eb51d3a2a 100644 --- a/src/native/eventpipe/ep-provider.c +++ b/src/native/eventpipe/ep-provider.c @@ -493,6 +493,7 @@ provider_free (EventPipeProvider * provider) dn_list_custom_free (provider->event_list, event_free_func); + ep_rt_wait_event_free (&provider->callbacks_complete_event); ep_rt_utf16_string_free (provider->provider_name_utf16); ep_rt_utf8_string_free (provider->provider_name); ep_rt_object_free (provider); diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index ae0af76d64680d..d57a01d9c0978d 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -644,7 +644,9 @@ disable_holding_lock ( ep_session_free (session); // Providers can't be deleted during tracing because they may be needed when serializing the file. - config_delete_deferred_providers(ep_config_get ()); + // Allow delete deferred providers to accumulate to mitigate potential use-after-free should + // another EventPipe session hold a reference to a provider set for deferred deletion. + // config_delete_deferred_providers(ep_config_get ()); } ep_requires_lock_held (); @@ -1319,22 +1321,18 @@ ep_delete_provider (EventPipeProvider *provider) // where we hold a provider after tracing has been disabled. bool wait_for_provider_callbacks_completion = false; EP_LOCK_ENTER (section1) - if (enabled ()) { - // Save the provider until the end of the tracing session. - ep_provider_set_delete_deferred (provider, true); - - // The callback func must be previously set to null, - // otherwise callbacks might never stop coming. - EP_ASSERT (provider->callback_func == NULL); - - // Calling ep_delete_provider within a Callback will result in a deadlock - // as deleting the provider with an active tracing session will block - // until all of the provider's callbacks are completed. - if (provider->callbacks_pending > 0) - wait_for_provider_callbacks_completion = true; - } else { - config_delete_provider (ep_config_get (), provider); - } + // Save the provider until the end of the tracing session. + ep_provider_set_delete_deferred (provider, true); + + // The callback func must be set to null, + // otherwise callbacks might never stop coming. + EP_ASSERT (provider->callback_func == NULL); + + // Calling ep_delete_provider within a Callback will result in a deadlock + // as deleting the provider with an active tracing session will block + // until all of the provider's callbacks are completed. + if (provider->callbacks_pending > 0) + wait_for_provider_callbacks_completion = true; EP_LOCK_EXIT (section1) // Block provider deletion until all pending callbacks are completed. @@ -1344,6 +1342,11 @@ ep_delete_provider (EventPipeProvider *provider) if (wait_for_provider_callbacks_completion) ep_rt_wait_event_wait (&provider->callbacks_complete_event, EP_INFINITE_WAIT, false); + EP_LOCK_ENTER (section2) + if (!enabled ()) + config_delete_provider (ep_config_get (), provider); + EP_LOCK_EXIT (section2) + ep_on_exit: ep_requires_lock_not_held (); return;