-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[EventPipe] Add dotnet_ipc_created mapping #123779
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this 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 a dotnet_ipc_created memory mapping to signal when a .NET process's diagnostic port is ready to receive IPC commands. This provides external tracing tools with a low-overhead mechanism to detect when the runtime is ready, instead of having to poll temporary file directories. The implementation uses Linux's memfd_create syscall to create a named memory mapping that can be detected by tools like one-collect.
Changes:
- Added CMake configuration checks for
sys/mman.hheader andmemfd_createsyscall availability - Created a memory mapping named "dotnet_ipc_created" when the default diagnostic listen port is successfully initialized
- The mapping serves as a signal mechanism for external tools to detect IPC readiness
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/native/eventpipe/configure.cmake | Added CMake checks for sys/syscall.h, sys/mman.h, and __NR_memfd_create symbol |
| src/native/eventpipe/ep-shared-config.h.in | Added CMake define declarations for HAVE_SYS_MMAN_H and HAVE_MEMFD_CREATE |
| src/native/eventpipe/ds-ipc.c | Implemented the dotnet_ipc_created mapping creation using memfd_create and mmap when the default listen port is successfully created |
src/native/eventpipe/ds-ipc.c
Outdated
| if (default_listen_port_ready) { | ||
| int fd = (int)syscall (__NR_memfd_create, "dotnet_ipc_created", (unsigned int)MFD_CLOEXEC); | ||
| if (fd >= 0) { | ||
| mmap (NULL, 1, PROT_EXEC | PROT_READ, MAP_PRIVATE, fd, 0); |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value of mmap should be checked for MAP_FAILED. The mmap call can fail for various reasons (e.g., insufficient memory, invalid permissions), and ignoring this failure could lead to resource leaks or unexpected behavior. Other instances of mmap in the codebase consistently check for MAP_FAILED (see src/native/libs/System.Native/pal_io.c:1010, src/native/corehost/hostmisc/pal.unix.cpp:99, and src/native/minipal/memorybarrierprocesswide.c:119).
| mmap (NULL, 1, PROT_EXEC | PROT_READ, MAP_PRIVATE, fd, 0); | |
| void *map = mmap (NULL, 1, PROT_EXEC | PROT_READ, MAP_PRIVATE, fd, 0); | |
| if (map == MAP_FAILED) { | |
| // Mapping failed; external tools will not see the readiness signal. | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we fail to create the mapping for some reason, should we even try again and if so, how many times?
src/native/eventpipe/ds-ipc.c
Outdated
| if (default_listen_port_ready) { | ||
| int fd = (int)syscall (__NR_memfd_create, "dotnet_ipc_created", (unsigned int)MFD_CLOEXEC); | ||
| if (fd >= 0) { | ||
| mmap (NULL, 1, PROT_EXEC | PROT_READ, MAP_PRIVATE, fd, 0); |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PROT_EXEC flag allows pages to be executed, which is a security concern. Since this mapping is only intended as a signal mechanism (the mapped memory is never accessed), PROT_EXEC is unnecessary and violates the principle of least privilege. The mapping should use minimal permissions required for its purpose. Consider using PROT_READ only, or even PROT_NONE if the mere existence of the mapping is sufficient for detection by external tools.
| mmap (NULL, 1, PROT_EXEC | PROT_READ, MAP_PRIVATE, fd, 0); | |
| mmap (NULL, 1, PROT_NONE, MAP_PRIVATE, fd, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried just using PROT_READ (also suggested by Copilot CLI), but when running the userevents tests, it was insufficient for record-trace to discover the mapping.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
record-trace skips non executable mmaps.
https://github.com/microsoft/one-collect/blob/ebdb5acfbf5b767d0d648a74bc302e0807e50000/one_collect/src/helpers/dotnet/os/linux.rs#L1291-L1294
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can it be at least just PROT_READ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
record-trace skips non executable mmaps.
Can it be changed? That code will need to be modified to check for this mapping instead anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Asked in the record-trace PR microsoft/one-collect#229 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we have this memory map indicating that we have a diagnostic server up and running, I believe that is a much better indicator than the doublemapper they used in the past, so maybe they should steer away from that and only use this instead to find dotnet processes that support tracing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
External tools interested in connecting to the runtime's diagnostic ports benefit from a low-overhead IO signal that a .NET process is ready to receive IPC commands, instead of trying to IO over all known temp file directories looking for diagnostic ports for each process.
Following the discussion in microsoft/one-collect#226, this PR adds a new mapping,
dotnet_ipc_created, that is created once a .NET process' singular listen port is successfully created.Testing
userevents runtime tests now work on NativeAOT with the record-trace change microsoft/one-collect#229