Skip to content

Conversation

@mdh1418
Copy link
Member

@mdh1418 mdh1418 commented Jan 29, 2026

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

mihw@CPC-mihw-6KMZDM:~/repo/runtime$ ./artifacts/tests/coreclr/linux.x64.Release/tracing/userevents/basic/basic/basic.sh
BEGIN EXECUTION
/home/mihw/repo/runtime/src/tests/Common/scripts/nativeaottest.sh /home/mihw/repo/runtime/artifacts/tests/coreclr/linux.x64.Release/tracing/userevents/basic/basic/ basic.dll ''
traceeAssemblyPath:
Starting record-trace: sudo -n /home/mihw/repo/runtime/artifacts/tests/coreclr/linux.x64.Release/tracing/userevents/common/userevents_common/record-trace --script-file /home/mihw/repo/runtime/artifacts/tests/coreclr/linux.x64.Release/tracing/userevents/basic/basic/native/../basic.script --out /tmp/tmpBoli5K.nettrace --log-mode console --log-filter error,one_collect::helpers::dotnet::os::linux=debug
record-trace started with PID: 1543079
[record-trace] 2026-01-29T22:55:19.967428Z DEBUG one_collect::helpers::dotnet::os::linux: Registered .NET tracepoint: name=OC_DotNet_Microsoft_Windows_DotNETRuntime_1543081_All, callstacks=false, use_names=true
Starting tracee process: /home/mihw/repo/runtime/artifacts/tests/coreclr/linux.x64.Release/tracing/userevents/basic/basic/native/basic tracee
Tracee process started with PID: 1543083
Waiting for tracee process to exit...
[record-trace] 2026-01-29T22:55:20.093460Z DEBUG one_collect::helpers::dotnet::os::linux: Opened diagnostic socket: pid=1543063, nspid=1543063
[record-trace] 2026-01-29T22:55:20.093476Z DEBUG one_collect::helpers::dotnet::os::linux: Opened diagnostic socket: pid=1543063, nspid=1543063
[record-trace] 2026-01-29T22:55:20.094446Z DEBUG one_collect::helpers::dotnet::os::linux: Opened diagnostic socket: pid=1543063, nspid=1543063
[record-trace] Recording started.  Press CTRL+C to stop.
[record-trace] 2026-01-29T22:55:20.097795Z  INFO one_collect::helpers::dotnet::os::linux: Enabled .NET events for process: pid=1543063
[record-trace] 2026-01-29T22:55:20.098955Z DEBUG one_collect::helpers::dotnet::os::linux: Opened diagnostic socket: pid=1543083, nspid=1543083
[record-trace] 2026-01-29T22:55:20.099085Z DEBUG one_collect::helpers::dotnet::os::linux: Opened diagnostic socket: pid=1543083, nspid=1543083
[record-trace] 2026-01-29T22:55:20.100017Z DEBUG one_collect::helpers::dotnet::os::linux: Opened diagnostic socket: pid=1543083, nspid=1543083
[record-trace] 2026-01-29T22:55:20.104842Z  INFO one_collect::helpers::dotnet::os::linux: Enabled .NET events for process: pid=1543083
Stopping record-trace with SIGINT.
Waiting for record-trace to exit...
[record-trace] Recording stopped.
[record-trace] Resolving symbols.
[record-trace] Finished recording trace.
[record-trace] Trace written to /tmp/tmpBoli5K.nettrace
Expected: 100
Actual: 100
END EXECUTION - PASSED

@mdh1418 mdh1418 requested a review from jkotas January 29, 2026 22:57
@mdh1418 mdh1418 self-assigned this Jan 29, 2026
Copilot AI review requested due to automatic review settings January 29, 2026 22:57
Copy link
Contributor

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 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.h header and memfd_create syscall 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

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);
Copy link

Copilot AI Jan 29, 2026

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).

Suggested change
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.
}

Copilot uses AI. Check for mistakes.
Copy link
Member Author

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?

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);
Copy link

Copilot AI Jan 29, 2026

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.

Suggested change
mmap (NULL, 1, PROT_EXEC | PROT_READ, MAP_PRIVATE, fd, 0);
mmap (NULL, 1, PROT_NONE, MAP_PRIVATE, fd, 0);

Copilot uses AI. Check for mistakes.
Copy link
Member Author

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.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

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?

Copy link
Member

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.

Copy link
Member Author

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)

Copy link
Member

@lateralusX lateralusX Jan 30, 2026

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.

Copilot AI review requested due to automatic review settings January 30, 2026 17:38
Copy link
Contributor

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

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

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