diff --git a/src/native/eventpipe/ep-buffer-manager.c b/src/native/eventpipe/ep-buffer-manager.c index bda775b00250dc..c1cb584a5d89cd 100644 --- a/src/native/eventpipe/ep-buffer-manager.c +++ b/src/native/eventpipe/ep-buffer-manager.c @@ -791,6 +791,7 @@ buffer_manager_try_convert_buffer_to_read_only ( EventPipeThread *thread = ep_buffer_get_writer_thread (new_read_buffer); EP_SPIN_LOCK_ENTER (ep_thread_get_rt_lock_ref (thread), section1); EventPipeThreadSessionState *thread_session_state = ep_thread_get_session_state (thread, buffer_manager->session); + EP_ASSERT(thread_session_state != NULL); if (ep_thread_session_state_get_write_buffer (thread_session_state) == new_read_buffer) { ep_thread_session_state_set_write_buffer (thread_session_state, NULL); EP_ASSERT (ep_buffer_get_volatile_state (new_read_buffer) == EP_BUFFER_STATE_READ_ONLY); @@ -1091,6 +1092,7 @@ ep_buffer_manager_suspend_write_event ( EventPipeThread *thread = ep_rt_thread_array_iterator_value (&thread_array_iterator); EP_SPIN_LOCK_ENTER (ep_thread_get_rt_lock_ref (thread), section2) EventPipeThreadSessionState *thread_session_state = ep_thread_get_session_state (thread, buffer_manager->session); + EP_ASSERT(thread_session_state != NULL); ep_thread_session_state_set_write_buffer (thread_session_state, NULL); EP_SPIN_LOCK_EXIT (ep_thread_get_rt_lock_ref (thread), section2) ep_rt_thread_array_iterator_next (&thread_array_iterator); diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 2dc9f624b6cc15..9a8c43b9834163 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -26,6 +26,10 @@ static void session_create_streaming_thread (EventPipeSession *session); +static +void +ep_session_remove_dangling_session_states (EventPipeSession *session); + /* * EventPipeSession. */ @@ -216,6 +220,46 @@ ep_session_alloc ( ep_exit_error_handler (); } +void +ep_session_remove_dangling_session_states (EventPipeSession *session) +{ + ep_return_void_if_nok (session != NULL); + + EP_RT_DECLARE_LOCAL_THREAD_ARRAY (threads); + ep_rt_thread_array_init (&threads); + + ep_thread_get_threads (&threads); + + ep_rt_thread_array_iterator_t threads_iterator = ep_rt_thread_array_iterator_begin (&threads); + while (!ep_rt_thread_array_iterator_end (&threads, &threads_iterator)) { + EventPipeThread *thread = ep_rt_thread_array_iterator_value (&threads_iterator); + EP_ASSERT(thread != NULL); + EP_SPIN_LOCK_ENTER (ep_thread_get_rt_lock_ref (thread), section1); + EventPipeThreadSessionState *session_state = ep_thread_get_session_state(thread, session); + if (session_state) { + // If a buffer tries to write event(s) but never gets a buffer because the maximum total buffer size + // has been exceeded, we can leak the EventPipeThreadSessionState* and crash later trying to access + // the session from the thread session state. Whenever we terminate a session we check to make sure + // we haven't leaked any thread session states. + ep_thread_delete_session_state(thread, session); + } + EP_SPIN_LOCK_EXIT (ep_thread_get_rt_lock_ref (thread), section1); + + // ep_thread_get_threads calls ep_thread_addref for every entry, need to release it here + ep_thread_release (thread); + + ep_rt_thread_array_iterator_next (&threads_iterator); + } + + ep_rt_thread_array_fini (&threads); + +ep_on_exit: + return; + +ep_on_error: + ep_exit_error_handler (); +} + void ep_session_free (EventPipeSession *session) { @@ -230,6 +274,8 @@ ep_session_free (EventPipeSession *session) ep_buffer_manager_free (session->buffer_manager); ep_file_free (session->file); + ep_session_remove_dangling_session_states (session); + ep_rt_object_free (session); } diff --git a/src/native/eventpipe/ep-thread.c b/src/native/eventpipe/ep-thread.c index 0f2eac6d78949d..0f8d974a5a7603 100644 --- a/src/native/eventpipe/ep-thread.c +++ b/src/native/eventpipe/ep-thread.c @@ -247,7 +247,6 @@ ep_thread_get_session_state ( ep_thread_requires_lock_held (thread); - EP_ASSERT (thread->session_state [ep_session_get_index (session)] != NULL); return thread->session_state [ep_session_get_index (session)]; }