Repository: dotnet/runtime
File: src/native/eventpipe/ds-ipc.c (C)

Code before:
	uint32_t port_suspend = ds_rt_config_value_get_default_port_suspend ();

	DiagnosticsPortBuilder default_port_builder;
	if (ds_port_builder_init (&default_port_builder)) {
		default_port_builder.path = NULL;
		default_port_builder.suspend_mode = port_suspend > 0 ? DS_PORT_SUSPEND_MODE_SUSPEND : DS_PORT_SUSPEND_MODE_NOSUSPEND;
		default_port_builder.type = DS_PORT_TYPE_LISTEN;

		result &= ipc_stream_factory_build_and_add_port (&default_port_builder, callback, true);

		ds_port_builder_fini (&default_port_builder);
	} else {
		result &= false;
	}
#else
	DS_LOG_DEBUG_0 ("ds_ipc_stream_factory_configure - Ignoring default LISTEN port");
#endif

#if HAVE_SYS_MMAN_H && HAVE_MEMFD_CREATE && HAVE_UNISTD_H
	// Create a mapping to signal that the diagnostic server IPC is available.
	// External tools can use this to detect when the runtime is ready to accept diagnostic commands.
	// The mapping's lifetime is tied to the process, so tools that start after the .NET process can still detect it.
	if (ds_ipc_stream_factory_any_listen_ports ()) {
		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);
			close (fd);
		}
	}
#endif

	return result;
}

// Polling timeout semantics
// If client connection is opted in
//   and connection succeeds => set timeout to infinite
//   and connection fails => set timeout to minimum and scale by falloff factor
// else => set timeout to (uint32_t)-1 (infinite)
//
// If an agent closes its socket while we're still connected,
// Poll will return and let us know which connection hung up

DiagnosticsIpcStream *
ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func callback)
{
	DS_LOG_DEBUG_0 ("ds_ipc_stream_factory_get_next_available_stream - ENTER");

	DiagnosticsIpcStream *stream = NULL;

	uint32_t poll_timeout_ms = IPC_TIMEOUT_INFINITE;

Review comment (bug):
The return value of mmap should be checked for MAP_FAILED before using or closing the file descriptor. According to POSIX standards and existing code patterns in the repository (e.g., src/native/corehost/hostmisc/pal.unix.cpp:99 and src/native/minipal/memorybarrierprocesswide.c:119), mmap returns MAP_FAILED (typically (void*)-1) on failure rather than NULL. Without this check, a failed mmap call could leave the mapping in an undefined state and the close operation would still proceed on the file descriptor.
```suggestion
			void *mapping = mmap (NULL, 1, PROT_EXEC | PROT_READ, MAP_PRIVATE, fd, 0);
			if (mapping == MAP_FAILED) {
				// Mapping failed; the diagnostic IPC created signal will not be available.
			}
```

Code after:
	uint32_t port_suspend = ds_rt_config_value_get_default_port_suspend ();

	DiagnosticsPortBuilder default_port_builder;
	if (ds_port_builder_init (&default_port_builder)) {
		default_port_builder.path = NULL;
		default_port_builder.suspend_mode = port_suspend > 0 ? DS_PORT_SUSPEND_MODE_SUSPEND : DS_PORT_SUSPEND_MODE_NOSUSPEND;
		default_port_builder.type = DS_PORT_TYPE_LISTEN;

		result &= ipc_stream_factory_build_and_add_port (&default_port_builder, callback, true);

		ds_port_builder_fini (&default_port_builder);
	} else {
		result &= false;
	}
#else
	DS_LOG_DEBUG_0 ("ds_ipc_stream_factory_configure - Ignoring default LISTEN port");
#endif

#if HAVE_SYS_MMAN_H && HAVE_MEMFD_CREATE && HAVE_UNISTD_H
	// Create a mapping to signal that the diagnostic server IPC is available.
	// External tools can use this to detect when the runtime is ready to accept diagnostic commands.
	// The mapping's lifetime is tied to the process, so tools that start after the .NET process can still detect it.
	if (ds_ipc_stream_factory_any_listen_ports ()) {
		int fd = (int)syscall (__NR_memfd_create, "dotnet_ipc_created", (unsigned int)MFD_CLOEXEC);
		if (fd >= 0) {
			mmap (NULL, 1, PROT_NONE, MAP_PRIVATE, fd, 0);
			close (fd);
		}
	}
#endif

	return result;
}

// Polling timeout semantics
// If client connection is opted in
//   and connection succeeds => set timeout to infinite
//   and connection fails => set timeout to minimum and scale by falloff factor
// else => set timeout to (uint32_t)-1 (infinite)
//
// If an agent closes its socket while we're still connected,
// Poll will return and let us know which connection hung up

DiagnosticsIpcStream *
ds_ipc_stream_factory_get_next_available_stream (ds_ipc_error_callback_func callback)
{
	DS_LOG_DEBUG_0 ("ds_ipc_stream_factory_get_next_available_stream - ENTER");

	DiagnosticsIpcStream *stream = NULL;

	uint32_t poll_timeout_ms = IPC_TIMEOUT_INFINITE;