Skip to content

[EventPipe] End user_events session upon continuation_stream closure #117435

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

mdh1418
Copy link
Member

@mdh1418 mdh1418 commented Jul 8, 2025

User_events-based EventPipe sessions should end when the profiling process disconnects from the Diagnostic Port.

This PR does the following:

  • Adds the poll_func to IpcStream vtables
  • Adds ds_ipc_stream_poll based on ds_ipc_poll
  • Pass the continuation stream to user_events sessions
  • Extends the eventpipe streaming thread for user_events with ep_ipc_continuation_stream_connection_closed to detect disconnects.

Testing

Manual E2E testing with the same C program as #115265, except putting a getchar before closing the socket from the client side.

@mdh1418
Copy link
Member Author

mdh1418 commented Jul 8, 2025

cc: @pavelsavara for websocket poll implementation

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds support for detecting remote disconnections on user_events-based EventPipe sessions by extending IPC streams with polling capabilities and wiring up a continuation stream to session logic.

  • Introduce IpcStreamPollFunc in IPC vtables and implement ds_ipc_stream_poll variants
  • Define IpcContinuationStream and add ep_ipc_continuation_stream_connection_closed for hangup detection
  • Refactor session streaming thread to handle EP_SESSION_TYPE_USEREVENTS and unified ep_session_type_uses_streaming_thread predicate

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/native/eventpipe/ep-types-forward.h Forward-declare IpcContinuationStream
src/native/eventpipe/ep-stream.h Define IpcContinuationStream struct and closure API
src/native/eventpipe/ep-stream.c Add ep_ipc_stream_poll_vcall and continuation-stream check
src/native/eventpipe/ep-session.h Add continuation_stream field and streaming-thread predicate
src/native/eventpipe/ep-session.c Refactor streaming thread to support user events and cleanup
src/native/eventpipe/ep-ipc-stream.h Add IpcStreamPollFunc and ep_ipc_stream_poll_vcall prototype
src/native/eventpipe/ep-ipc-pal-types.h Define EventPipeIpcPollEvents enum and poll timeout constant
src/native/eventpipe/ds-ipc.c Replace DS_IPC_POLL_EVENTS_* with EP_IPC_POLL_EVENTS_*
src/native/eventpipe/ds-ipc-pal.h Declare ds_ipc_stream_poll
src/native/eventpipe/ds-ipc-pal-websocket.c Implement WebSocket poll func and update vtable
src/native/eventpipe/ds-ipc-pal-types.h Remove old DiagnosticsIpcPollEvents enum
src/native/eventpipe/ds-ipc-pal-socket.c Add socket poll func and vtable entry
src/native/eventpipe/ds-ipc-pal-namedpipe.c Stub out named pipe poll func
src/native/eventpipe/ds-eventpipe-protocol.c Always pass ds_ipc_stream_get_stream_ref(stream)

@mdh1418 mdh1418 force-pushed the ep_user_events_close_session_on_stream_close branch from a529a85 to c7fc5e6 Compare July 8, 2025 20:43
@@ -355,5 +355,26 @@ ep_ipc_stream_writer_write (
uint32_t bytes_to_write,
uint32_t *bytes_written);

/*
* IpcContinuationStream
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defining a new struct to wrap IpcStream seems unnecessary. Couldn't we just make the continuation_stream field in the session be type IpcStream*?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, we can. I just wasn't sure if IpcStream was meant to only be a base class that should be derived for different implementations, like how the different PAL implementations of DiagnosticsIpcStream all just derive from IpcStream.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think IpcStream is meant to be a base class for different types of stream implementations, for example socket stream vs named pipe stream vs websocket stream. Its a bit less obvious because even though derived types have different implementations they are all reusing the same 'DiagnosticsIpcStream' type name. At some point in the future we could rename them SocketIpcStream, NamedPipeIpcStream, etc to make the inheritance pattern clearer. Sidestepping the naming, unless we are implementing a new transport I wouldn't expect a new stream derived type is needed.

mdh1418 and others added 2 commits July 10, 2025 19:54
Revert moving IpcPollEvents to ep-ipc-pal-types header
Use IpcStream base type directly in sessions
Omit websocket ipc_stream_poll_func implementation
Change continuation stream poll timeout to infinite
Change returned PollEvent to none upon timeout
ep-stream.h for ep_ipc_stream_writer_alloc that was transitively
included by ep-file.h
ep-ipc-stream.h for ep_ipc_stream_poll_vcall
@@ -71,6 +71,9 @@ struct _EventPipeSession_Internal {
volatile uint32_t ref_count;
// The user_events_data file descriptor to register Tracepoints and write user_events to.
int user_events_data_fd;
// The IPC continuation stream from initializing the session through the diagnostic server
// Currently only initialized for user_events sessions.
IpcStream *stream;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to do it in this PR, but going forward I believe we should do different versions of this struct depending on the type and move specific fields into sub types instead of having a fields in one struct where type dictates what fields is applicable without any further information.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I think we can have a Refactoring PR where we split up the versions of the struct, also migrate the IPC types to its own file, and move the user_events_data fd into the Stream structure

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So IPC namespace, Clarify the IpcStream inheritance naming, this, and the followup work from the main user_events PR (#115265 (comment) ,#115265 (comment), #115265 (comment))

DS_IPC_POLL_EVENTS_HANGUP = 0x02, // connection remotely closed
DS_IPC_POLL_EVENTS_ERR = 0x04, // error
DS_IPC_POLL_EVENTS_UNKNOWN = 0x80 // unknown state
} DiagnosticsIpcPollEvents;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it already have been discussed, but maybe we should just drop EP/DS from this so its "common" meaning IPC_POLL_EVENTS_*, IpcPollEvents, IPC_TIMEOUT_INFINITE and going forward we might put all the low level IPC stuff into its own IPC namespace and share that code cross components.

Remove prefix from IpcPollEvents enums and infinite timeout define
Expand connection closed detection to error case
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants