Skip to content

Commit e67e4da

Browse files
authored
Move away from exposing internal EventPipe wait handle to EventPipeEventDispatcher. (#68320)
* Move away from exposing internal EventPipe wait handle to EventPipeEventDispatcher. Fix for issue, #68032. EventPipe exposed and internal wait handle to EventPipeEventDispatcher. The wait handle is not a managed WaitableObject, but maps to runtime specific event types: CLREventStatic * on CoreCLR mono_w32event_create on Mono Overtime it appears that the underlying WaitHandle changed on none Windows platforms, so calls like: EventWaitHandle.Set Assumes that IntPtr used is a WaitableObject and on Mono this will cause a crash, but on CoreCLR, it will just be casted over to a WaitableObject and use it, so based on memory layout this could cause issue, but looking at the implementation, it appears it will always assume EventWaitHandle is signaled so won't touch any of the memory (but not signal the event). There have been an ambition in DispatchEventsToEventListeners to move this abstraction down into native code, get away from using a handle returned from EventPipeInternal.GetWaitHandle as a EventWaitHandle. This PR eliminate EventPipeInternal.GetWaitHandle and adds a SignalSession and WaitForSessionSignal icall's (Mono), qcall's (CoreCLR) and fix the issue caused by exposing the handle to managed code.
1 parent cfa18c9 commit e67e4da

File tree

14 files changed

+162
-38
lines changed

14 files changed

+162
-38
lines changed

src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.CoreCLR.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,13 @@ private static unsafe partial ulong Enable(
5757
[return: MarshalAs(UnmanagedType.Bool)]
5858
internal static unsafe partial bool GetNextEvent(ulong sessionID, EventPipeEventInstanceData* pInstance);
5959

60-
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "EventPipeInternal_GetWaitHandle")]
61-
internal static unsafe partial IntPtr GetWaitHandle(ulong sessionID);
60+
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "EventPipeInternal_SignalSession")]
61+
[return: MarshalAs(UnmanagedType.Bool)]
62+
internal static unsafe partial bool SignalSession(ulong sessionID);
63+
64+
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "EventPipeInternal_WaitForSessionSignal")]
65+
[return: MarshalAs(UnmanagedType.Bool)]
66+
internal static unsafe partial bool WaitForSessionSignal(ulong sessionID, int timeoutMs);
6267
}
6368
}
6469

src/coreclr/vm/eventpipeadapter.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,26 @@ class EventPipeAdapter final
261261
return ep_get_session(id);
262262
}
263263

264-
static inline HANDLE GetWaitHandle(EventPipeSessionID id)
264+
static inline bool SignalSession(EventPipeSessionID id)
265265
{
266266
STATIC_CONTRACT_NOTHROW;
267-
return reinterpret_cast<HANDLE>(ep_get_wait_handle(id));
267+
268+
EventPipeSession *const session = ep_get_session (id);
269+
if (!session)
270+
return false;
271+
272+
return ep_rt_wait_event_set (ep_session_get_wait_event (session));
273+
}
274+
275+
static inline bool WaitForSessionSignal(EventPipeSessionID id, INT32 timeoutMs)
276+
{
277+
STATIC_CONTRACT_NOTHROW;
278+
279+
EventPipeSession *const session = ep_get_session (id);
280+
if (!session)
281+
return false;
282+
283+
return !ep_rt_wait_event_wait (ep_session_get_wait_event (session), (uint32_t)timeoutMs, false) ? true : false;
268284
}
269285

270286
static inline FILETIME GetSessionStartTime(EventPipeSession *session)

src/coreclr/vm/eventpipeinternal.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,17 +255,30 @@ extern "C" bool QCALLTYPE EventPipeInternal_GetNextEvent(UINT64 sessionID, Event
255255
return pNextInstance != NULL;
256256
}
257257

258-
extern "C" HANDLE QCALLTYPE EventPipeInternal_GetWaitHandle(UINT64 sessionID)
258+
extern "C" bool QCALLTYPE EventPipeInternal_SignalSession(UINT64 sessionID)
259259
{
260260
QCALL_CONTRACT;
261261

262-
HANDLE waitHandle = NULL;
262+
bool result = false;
263263
BEGIN_QCALL;
264264

265-
waitHandle = EventPipeAdapter::GetWaitHandle(sessionID);
265+
result = EventPipeAdapter::SignalSession(sessionID);
266266

267267
END_QCALL;
268-
return waitHandle;
268+
return result;
269+
}
270+
271+
extern "C" bool QCALLTYPE EventPipeInternal_WaitForSessionSignal(UINT64 sessionID, INT32 timeoutMs)
272+
{
273+
QCALL_CONTRACT;
274+
275+
bool result = false;
276+
BEGIN_QCALL;
277+
278+
result = EventPipeAdapter::WaitForSessionSignal(sessionID, timeoutMs);
279+
280+
END_QCALL;
281+
return result;
269282
}
270283

271284
#endif // FEATURE_PERFTRACING

src/coreclr/vm/eventpipeinternal.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ extern "C" void QCALLTYPE EventPipeInternal_DeleteProvider(
7373
INT_PTR provHandle);
7474

7575
extern "C" int QCALLTYPE EventPipeInternal_EventActivityIdControl(
76-
uint32_t controlCode,
76+
UINT32 controlCode,
7777
GUID *pActivityId);
7878

7979
extern "C" void QCALLTYPE EventPipeInternal_WriteEventData(
@@ -86,9 +86,13 @@ extern "C" bool QCALLTYPE EventPipeInternal_GetNextEvent(
8686
UINT64 sessionID,
8787
EventPipeEventInstanceData *pInstance);
8888

89-
extern "C" HANDLE QCALLTYPE EventPipeInternal_GetWaitHandle(
89+
extern "C" bool QCALLTYPE EventPipeInternal_SignalSession(
9090
UINT64 sessionID);
9191

92+
extern "C" bool QCALLTYPE EventPipeInternal_WaitForSessionSignal(
93+
UINT64 sessionID,
94+
INT32 timeoutMs);
95+
9296
#endif // FEATURE_PERFTRACING
9397

9498
#endif // __EVENTPIPEINTERNAL_H__

src/coreclr/vm/qcallentrypoints.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,8 @@ static const Entry s_QCall[] =
291291
DllImportEntry(EventPipeInternal_GetProvider)
292292
DllImportEntry(EventPipeInternal_WriteEventData)
293293
DllImportEntry(EventPipeInternal_GetNextEvent)
294-
DllImportEntry(EventPipeInternal_GetWaitHandle)
294+
DllImportEntry(EventPipeInternal_SignalSession)
295+
DllImportEntry(EventPipeInternal_WaitForSessionSignal)
295296
#endif
296297
#if defined(TARGET_UNIX)
297298
DllImportEntry(CloseHandle)

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

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ internal EventListenerSubscription(EventKeywords matchAnyKeywords, EventLevel le
3232
private long m_timeQPCFrequency;
3333

3434
private bool m_stopDispatchTask;
35-
private readonly EventPipeWaitHandle m_dispatchTaskWaitHandle = new EventPipeWaitHandle();
3635
private Task? m_dispatchTask;
3736
private readonly object m_dispatchControlLock = new object();
3837
private readonly Dictionary<EventListener, EventListenerSubscription> m_subscriptions = new Dictionary<EventListener, EventListenerSubscription>();
@@ -43,7 +42,6 @@ private EventPipeEventDispatcher()
4342
{
4443
// Get the ID of the runtime provider so that it can be used as a filter when processing events.
4544
m_RuntimeProviderID = EventPipeInternal.GetProvider(NativeRuntimeEventSource.EventSourceName);
46-
m_dispatchTaskWaitHandle.SafeWaitHandle = new SafeWaitHandle(IntPtr.Zero, false);
4745
}
4846

4947
internal void SendCommand(EventListener eventListener, EventCommand command, bool enable, EventLevel level, EventKeywords matchAnyKeywords)
@@ -139,9 +137,6 @@ private void StartDispatchTask()
139137
if (m_dispatchTask == null)
140138
{
141139
m_stopDispatchTask = false;
142-
// Create a SafeWaitHandle that won't release the handle when done
143-
m_dispatchTaskWaitHandle.SafeWaitHandle = new SafeWaitHandle(EventPipeInternal.GetWaitHandle(m_sessionID), false);
144-
145140
m_dispatchTask = Task.Factory.StartNew(DispatchEventsToEventListeners, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
146141
}
147142
}
@@ -153,8 +148,7 @@ private void StopDispatchTask()
153148
if (m_dispatchTask != null)
154149
{
155150
m_stopDispatchTask = true;
156-
Debug.Assert(!m_dispatchTaskWaitHandle.SafeWaitHandle.IsInvalid);
157-
EventWaitHandle.Set(m_dispatchTaskWaitHandle.SafeWaitHandle);
151+
EventPipeInternal.SignalSession(m_sessionID);
158152
m_dispatchTask.Wait();
159153
m_dispatchTask = null;
160154
}
@@ -188,9 +182,7 @@ private unsafe void DispatchEventsToEventListeners()
188182
{
189183
if (!eventsReceived)
190184
{
191-
// Future TODO: this would make more sense to handle in EventPipeSession/EventPipe native code.
192-
Debug.Assert(!m_dispatchTaskWaitHandle.SafeWaitHandle.IsInvalid);
193-
m_dispatchTaskWaitHandle.WaitOne();
185+
EventPipeInternal.WaitForSessionSignal(m_sessionID, Timeout.Infinite);
194186
}
195187

196188
Thread.Sleep(10);

src/mono/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipe.Mono.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ internal static unsafe IntPtr GetProvider(string providerName)
5757
internal static extern unsafe bool GetNextEvent(ulong sessionID, EventPipeEventInstanceData* pInstance);
5858

5959
[MethodImplAttribute(MethodImplOptions.InternalCall)]
60-
internal static extern unsafe IntPtr GetWaitHandle(ulong sessionID);
60+
internal static extern unsafe bool SignalSession(ulong sessionID);
61+
62+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
63+
internal static extern unsafe bool WaitForSessionSignal(ulong sessionID, int timeoutMs);
6164
#endif // FEATURE_PERFTRACING
6265

6366
//

src/mono/mono/component/event_pipe-stub.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ event_pipe_stub_write_event_threadpool_io_pack (
177177
intptr_t overlapped,
178178
uint16_t clr_instance_id);
179179

180+
static bool
181+
event_pipe_stub_signal_session (EventPipeSessionID session_id);
182+
183+
static bool
184+
event_pipe_stub_wait_for_session_signal (
185+
EventPipeSessionID session_id,
186+
uint32_t timeout);
187+
180188
MonoComponentEventPipe *
181189
component_event_pipe_stub_init (void);
182190

@@ -210,7 +218,9 @@ static MonoComponentEventPipe fn_table = {
210218
&event_pipe_stub_write_event_threadpool_io_enqueue,
211219
&event_pipe_stub_write_event_threadpool_io_dequeue,
212220
&event_pipe_stub_write_event_threadpool_working_thread_count,
213-
&event_pipe_stub_write_event_threadpool_io_pack
221+
&event_pipe_stub_write_event_threadpool_io_pack,
222+
&event_pipe_stub_signal_session,
223+
&event_pipe_stub_wait_for_session_signal
214224
};
215225

216226
static bool
@@ -459,6 +469,20 @@ event_pipe_stub_write_event_threadpool_io_pack (
459469
return true;
460470
}
461471

472+
static bool
473+
event_pipe_stub_signal_session (EventPipeSessionID session_id)
474+
{
475+
return true;
476+
}
477+
478+
static bool
479+
event_pipe_stub_wait_for_session_signal (
480+
EventPipeSessionID session_id,
481+
uint32_t timeout)
482+
{
483+
return true;
484+
}
485+
462486
MonoComponentEventPipe *
463487
component_event_pipe_stub_init (void)
464488
{

src/mono/mono/component/event_pipe.c

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ event_pipe_thread_ctrl_activity_id(
8484
uint8_t *activity_id,
8585
uint32_t activity_id_len);
8686

87+
static bool
88+
event_pipe_signal_session (EventPipeSessionID session_id);
89+
90+
static bool
91+
event_pipe_wait_for_session_signal (
92+
EventPipeSessionID session_id,
93+
uint32_t timeout);
94+
8795
static MonoComponentEventPipe fn_table = {
8896
{ MONO_COMPONENT_ITF_VERSION, &event_pipe_available },
8997
&ep_init,
@@ -114,7 +122,9 @@ static MonoComponentEventPipe fn_table = {
114122
&ep_rt_write_event_threadpool_io_enqueue,
115123
&ep_rt_write_event_threadpool_io_dequeue,
116124
&ep_rt_write_event_threadpool_working_thread_count,
117-
&ep_rt_write_event_threadpool_io_pack
125+
&ep_rt_write_event_threadpool_io_pack,
126+
&event_pipe_signal_session,
127+
&event_pipe_wait_for_session_signal
118128
};
119129

120130
static bool
@@ -161,7 +171,7 @@ event_pipe_enable (
161171
rundown_requested,
162172
stream,
163173
sync_callback,
164-
NULL);
174+
NULL);
165175

166176
if (config_providers) {
167177
for (int i = 0; i < providers_len; ++i) {
@@ -285,6 +295,28 @@ event_pipe_thread_ctrl_activity_id (
285295
return result;
286296
}
287297

298+
static bool
299+
event_pipe_signal_session (EventPipeSessionID session_id)
300+
{
301+
EventPipeSession *const session = ep_get_session (session_id);
302+
if (!session)
303+
return false;
304+
305+
return ep_rt_wait_event_set (ep_session_get_wait_event (session));
306+
}
307+
308+
static bool
309+
event_pipe_wait_for_session_signal (
310+
EventPipeSessionID session_id,
311+
uint32_t timeout)
312+
{
313+
EventPipeSession *const session = ep_get_session (session_id);
314+
if (!session)
315+
return false;
316+
317+
return !ep_rt_wait_event_wait (ep_session_get_wait_event (session), timeout, false) ? true : false;
318+
}
319+
288320
MonoComponentEventPipe *
289321
mono_component_event_pipe_init (void)
290322
{

src/mono/mono/component/event_pipe.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ typedef bool
8585
typedef ep_timestamp_t
8686
(*event_pipe_component_convert_100ns_ticks_to_timestamp_t_func) (int64_t ticks_100ns);
8787

88+
typedef bool
89+
(*event_pipe_component_signal_session) (EventPipeSessionID session_id);
90+
91+
typedef bool
92+
(*event_pipe_component_wait_for_session_signal) (
93+
EventPipeSessionID session_id,
94+
uint32_t timeout);
95+
8896
/*
8997
* EventPipeProvider.
9098
*/
@@ -242,6 +250,8 @@ typedef struct _MonoComponentEventPipe {
242250
event_pipe_component_write_event_threadpool_io_dequeue_func write_event_threadpool_io_dequeue;
243251
event_pipe_component_write_event_threadpool_working_thread_count_func write_event_threadpool_working_thread_count;
244252
event_pipe_component_write_event_threadpool_io_pack_func write_event_threadpool_io_pack;
253+
event_pipe_component_signal_session signal_session;
254+
event_pipe_component_wait_for_session_signal wait_for_session_signal;
245255
} MonoComponentEventPipe;
246256

247257
MONO_COMPONENT_EXPORT_ENTRYPOINT

0 commit comments

Comments
 (0)