Skip to content

Commit d28ed8e

Browse files
committed
Address feedback
Rename counter Add more comments describing the blocking behavior Add comments for potential deadlock scenario
1 parent 520635a commit d28ed8e

File tree

4 files changed

+21
-11
lines changed

4 files changed

+21
-11
lines changed

src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventProvider.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ internal override unsafe void Register(EventSource eventSource)
8585
}
8686

8787
// Unregister an event provider.
88+
// Calling Unregister within a Callback will result in a deadlock
89+
// as deleting the provider with an active tracing session will block
90+
// until all of the provider's callbacks are completed.
8891
internal override void Unregister()
8992
{
9093
if (_provHandle != 0)

src/native/eventpipe/ep-provider.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ provider_prepare_callback_data (
8181
ep_requires_lock_held ();
8282

8383
if (provider->callback_func != NULL)
84-
provider->uninvoked_prepared_callbacks_counter++;
84+
provider->callbacks_pending++;
8585

8686
return ep_provider_callback_data_init (
8787
provider_callback_data,
@@ -209,7 +209,7 @@ ep_provider_alloc (
209209
instance->config = config;
210210
instance->delete_deferred = false;
211211
instance->sessions = 0;
212-
instance->uninvoked_prepared_callbacks_counter = 0;
212+
instance->callbacks_pending = 0;
213213

214214
ep_on_exit:
215215
return instance;
@@ -444,8 +444,8 @@ provider_invoke_callback (EventPipeProviderCallbackData *provider_callback_data)
444444
EP_LOCK_ENTER (section1)
445445
if (callback_function != NULL) {
446446
EventPipeProvider *provider = provider_callback_data->provider;
447-
provider->uninvoked_prepared_callbacks_counter--;
448-
if (provider->uninvoked_prepared_callbacks_counter == 0 && provider->callback_func == NULL) {
447+
provider->callbacks_pending--;
448+
if (provider->callbacks_pending == 0 && provider->callback_func == NULL) {
449449
// ep_delete_provider deferred provider deletion and is waiting for all in-flight callbacks
450450
// to complete. This is the last callback, so signal completion.
451451
ep_rt_wait_event_set (&provider->callbacks_complete_event);

src/native/eventpipe/ep-provider.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,9 @@ struct _EventPipeProvider_Internal {
4242
// True if the provider has been deleted, but that deletion
4343
// has been deferred until tracing is stopped.
4444
bool delete_deferred;
45-
// The number of EventPipeProvider callbacks that have been
46-
// prepared but not yet invoked.
47-
// Used to determine when it is safe to delete a provider.
48-
int64_t uninvoked_prepared_callbacks_counter;
45+
// The number of pending EventPipeProvider callbacks that have
46+
// not completed.
47+
int64_t callbacks_pending;
4948
// Event object used to signal eventpipe provider deletion
5049
// that all in flight callbacks have completed.
5150
ep_rt_wait_event_handle_t callbacks_complete_event;

src/native/eventpipe/ep.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,16 +1323,24 @@ ep_delete_provider (EventPipeProvider *provider)
13231323
// Save the provider until the end of the tracing session.
13241324
ep_provider_set_delete_deferred (provider, true);
13251325

1326-
// the callback func must be previously set to null,
1327-
// otherwise callbacks might never stop coming
1326+
// The callback func must be previously set to null,
1327+
// otherwise callbacks might never stop coming.
13281328
EP_ASSERT (provider->callback_func == NULL);
1329-
if (provider->uninvoked_prepared_callbacks_counter > 0)
1329+
1330+
// Calling ep_delete_provider within a Callback will result in a deadlock
1331+
// as deleting the provider with an active tracing session will block
1332+
// until all of the provider's callbacks are completed.
1333+
if (provider->callbacks_pending > 0)
13301334
wait_for_provider_callbacks_completion = true;
13311335
} else {
13321336
config_delete_provider (ep_config_get (), provider);
13331337
}
13341338
EP_LOCK_EXIT (section1)
13351339

1340+
// Block provider deletion until all pending callbacks are completed.
1341+
// Helps prevent the EventPipeEventProvider Unregister logic from
1342+
// freeing freeing the provider's weak reference gchandle before
1343+
// callbacks using that handle have completed.
13361344
if (wait_for_provider_callbacks_completion)
13371345
ep_rt_wait_event_wait (&provider->callbacks_complete_event, EP_INFINITE_WAIT, false);
13381346

0 commit comments

Comments
 (0)