Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 40b87c9

Browse files
authored
Allow provider deletion to be deferred until after tracing is stopped. (#11651)
1 parent 36e988e commit 40b87c9

File tree

8 files changed

+117
-6
lines changed

8 files changed

+117
-6
lines changed

src/scripts/genEventPipe.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def generateClrEventPipeWriteEventsImpl(
122122
WriteEventImpl.append(
123123
" EventPipeProvider" +
124124
providerPrettyName +
125-
" = new EventPipeProvider(" +
125+
" = EventPipe::CreateProvider(" +
126126
providerPrettyName +
127127
"GUID);\n")
128128
for eventNode in eventNodes:

src/vm/eventpipe.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,10 @@ void EventPipe::Disable()
218218

219219
// De-allocate buffers.
220220
s_pBufferManager->DeAllocateBuffers();
221+
222+
// Delete deferred providers.
223+
// Providers can't be deleted during tracing because they may be needed when serializing the file.
224+
s_pConfig->DeleteDeferredProviders();
221225
}
222226
}
223227

@@ -234,6 +238,50 @@ bool EventPipe::Enabled()
234238
return enabled;
235239
}
236240

241+
EventPipeProvider* EventPipe::CreateProvider(const GUID &providerID, EventPipeCallback pCallbackFunction, void *pCallbackData)
242+
{
243+
CONTRACTL
244+
{
245+
THROWS;
246+
GC_TRIGGERS;
247+
MODE_ANY;
248+
}
249+
CONTRACTL_END;
250+
251+
return new EventPipeProvider(providerID, pCallbackFunction, pCallbackData);
252+
}
253+
254+
void EventPipe::DeleteProvider(EventPipeProvider *pProvider)
255+
{
256+
CONTRACTL
257+
{
258+
THROWS;
259+
GC_TRIGGERS;
260+
MODE_ANY;
261+
}
262+
CONTRACTL_END;
263+
264+
// Take the lock to make sure that we don't have a race
265+
// between disabling tracing and deleting a provider
266+
// where we hold a provider after tracing has been disabled.
267+
CrstHolder _crst(GetLock());
268+
269+
if(pProvider != NULL)
270+
{
271+
if(Enabled())
272+
{
273+
// Save the provider until the end of the tracing session.
274+
pProvider->SetDeleteDeferred();
275+
}
276+
else
277+
{
278+
// Delete the provider now.
279+
// NOTE: This will remove it from all of the EventPipe data structures.
280+
delete(pProvider);
281+
}
282+
}
283+
}
284+
237285
void EventPipe::WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length)
238286
{
239287
CONTRACTL
@@ -477,7 +525,7 @@ INT_PTR QCALLTYPE EventPipeInternal::CreateProvider(
477525

478526
BEGIN_QCALL;
479527

480-
pProvider = new EventPipeProvider(providerID, pCallbackFunc, NULL);
528+
pProvider = EventPipe::CreateProvider(providerID, pCallbackFunc, NULL);
481529

482530
END_QCALL;
483531

@@ -519,7 +567,7 @@ void QCALLTYPE EventPipeInternal::DeleteProvider(
519567
if(provHandle != NULL)
520568
{
521569
EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider*>(provHandle);
522-
delete pProvider;
570+
EventPipe::DeleteProvider(pProvider);
523571
}
524572

525573
END_QCALL;

src/vm/eventpipe.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class EventPipeFile;
1414
class EventPipeJsonFile;
1515
class EventPipeBuffer;
1616
class EventPipeBufferManager;
17+
class EventPipeProvider;
1718
class MethodDesc;
1819
class SampleProfilerEventInstance;
1920
struct EventPipeProviderConfiguration;
@@ -179,6 +180,12 @@ class EventPipe
179180
// Specifies whether or not the event pipe is enabled.
180181
static bool Enabled();
181182

183+
// Create a provider.
184+
static EventPipeProvider* CreateProvider(const GUID &providerID, EventPipeCallback pCallbackFunction = NULL, void *pCallbackData = NULL);
185+
186+
// Delete a provider.
187+
static void DeleteProvider(EventPipeProvider *pProvider);
188+
182189
// Write out an event.
183190
// Data is written as a serialized blob matching the ETW serialization conventions.
184191
static void WriteEvent(EventPipeEvent &event, BYTE *pData, unsigned int length);

src/vm/eventpipeconfiguration.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void EventPipeConfiguration::Initialize()
5959
CONTRACTL_END;
6060

6161
// Create the configuration provider.
62-
m_pConfigProvider = new EventPipeProvider(s_configurationProviderID);
62+
m_pConfigProvider = EventPipe::CreateProvider(s_configurationProviderID);
6363

6464
// Create the metadata event.
6565
m_pMetadataEvent = m_pConfigProvider->AddEvent(
@@ -379,6 +379,33 @@ EventPipeEventInstance* EventPipeConfiguration::BuildEventMetadataEvent(EventPip
379379
return pInstance;
380380
}
381381

382+
void EventPipeConfiguration::DeleteDeferredProviders()
383+
{
384+
CONTRACTL
385+
{
386+
THROWS;
387+
GC_TRIGGERS;
388+
MODE_ANY;
389+
// Lock must be held by EventPipe::Disable.
390+
PRECONDITION(EventPipe::GetLock()->OwnedByCurrentThread());
391+
392+
}
393+
CONTRACTL_END;
394+
395+
SListElem<EventPipeProvider*> *pElem = m_pProviderList->GetHead();
396+
while(pElem != NULL)
397+
{
398+
EventPipeProvider *pProvider = pElem->GetValue();
399+
if(pProvider->GetDeleteDeferred())
400+
{
401+
// The act of deleting the provider unregisters it and removes it from the list.
402+
delete(pProvider);
403+
}
404+
405+
pElem = m_pProviderList->GetNext(pElem);
406+
}
407+
}
408+
382409
EventPipeEnabledProviderList::EventPipeEnabledProviderList(
383410
EventPipeProviderConfiguration *pConfigs,
384411
unsigned int numConfigs)

src/vm/eventpipeconfiguration.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ class EventPipeConfiguration
7171
// Get the event used to write metadata to the event stream.
7272
EventPipeEventInstance* BuildEventMetadataEvent(EventPipeEventInstance &sourceInstance);
7373

74+
// Delete deferred providers.
75+
void DeleteDeferredProviders();
76+
7477
private:
7578

7679
// Get the provider without taking the lock.

src/vm/eventpipeprovider.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,18 @@ void EventPipeProvider::InvokeCallback()
208208
}
209209
}
210210

211+
bool EventPipeProvider::GetDeleteDeferred() const
212+
{
213+
LIMITED_METHOD_CONTRACT;
214+
return m_deleteDeferred;
215+
}
216+
217+
void EventPipeProvider::SetDeleteDeferred()
218+
{
219+
LIMITED_METHOD_CONTRACT;
220+
m_deleteDeferred = true;
221+
}
222+
211223
void EventPipeProvider::RefreshAllEvents()
212224
{
213225
CONTRACTL

src/vm/eventpipeprovider.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ typedef void (*EventPipeCallback)(
2626
class EventPipeProvider
2727
{
2828
// Declare friends.
29+
friend class EventPipe;
2930
friend class EventPipeConfiguration;
3031
friend class SampleProfiler;
3132

@@ -55,9 +56,15 @@ class EventPipeProvider
5556
// The configuration object.
5657
EventPipeConfiguration *m_pConfig;
5758

58-
public:
59+
// True if the provider has been deleted, but that deletion
60+
// has been deferred until tracing is stopped.
61+
bool m_deleteDeferred;
5962

63+
// Private constructor because all providers are created through EventPipe::CreateProvider.
6064
EventPipeProvider(const GUID &providerID, EventPipeCallback pCallbackFunction = NULL, void *pCallbackData = NULL);
65+
66+
public:
67+
6168
~EventPipeProvider();
6269

6370
// Get the provider ID.
@@ -96,6 +103,13 @@ class EventPipeProvider
96103

97104
// Invoke the provider callback.
98105
void InvokeCallback();
106+
107+
// Specifies whether or not the provider was deleted, but that deletion
108+
// was deferred until after tracing is stopped.
109+
bool GetDeleteDeferred() const;
110+
111+
// Defer deletion of the provider.
112+
void SetDeleteDeferred();
99113
};
100114

101115
#endif // FEATURE_PERFTRACING

src/vm/sampleprofiler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ void SampleProfiler::Enable()
3434

3535
if(s_pEventPipeProvider == NULL)
3636
{
37-
s_pEventPipeProvider = new EventPipeProvider(s_providerID);
37+
s_pEventPipeProvider = EventPipe::CreateProvider(s_providerID);
3838
s_pThreadTimeEvent = s_pEventPipeProvider->AddEvent(
3939
0, /* eventID */
4040
0, /* keywords */

0 commit comments

Comments
 (0)