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

Code before:
		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

	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;
	bool connect_success = true;
	uint32_t poll_attempts = 0;

	dn_vector_custom_alloc_params_t params = {0, };
	params.capacity = _ds_default_poll_handle_array_size;

	dn_vector_t ipc_poll_handles;
	ep_raise_error_if_nok (dn_vector_custom_init_t (&ipc_poll_handles, &params, DiagnosticsIpcPollHandle));

	while (!stream) {
		connect_success = true;
		DN_VECTOR_PTR_FOREACH_BEGIN (DiagnosticsPort *, port, _ds_port_array) {
			DiagnosticsIpcPollHandle ipc_poll_handle;
			if (ds_port_get_ipc_poll_handle_vcall (port, &ipc_poll_handle, callback))
				ep_raise_error_if_nok (dn_vector_push_back (&ipc_poll_handles, ipc_poll_handle));
			else
				connect_success = false;
		} DN_VECTOR_PTR_FOREACH_END;

		poll_timeout_ms = connect_success ?
			IPC_TIMEOUT_INFINITE :
			ipc_stream_factory_get_next_timeout (poll_timeout_ms);


Review comment (bug):
The mmap return value should be checked for MAP_FAILED before calling close. According to POSIX, mmap returns MAP_FAILED on error, and without this check, the file descriptor could be leaked if mmap fails. This pattern is consistently followed throughout the codebase (see src/native/corehost/hostmisc/pal.unix.cpp:99, src/native/minipal/memorybarrierprocesswide.c:119, and src/native/libs/System.Native/pal_io.c:1010). The check ensures the file descriptor is only closed when the mapping succeeds, or alternatively ensures proper cleanup when it fails.
```suggestion
			void *mapping = mmap (NULL, 1, PROT_NONE, MAP_PRIVATE, fd, 0);
			if (mapping == MAP_FAILED) {
				close (fd);
			} else {
				close (fd);
			}
```

Code after:

	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;
	bool connect_success = true;