diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index 3a8139b4b2963..a3e8501348375 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -586,6 +586,56 @@ public async Task ReceiveFrom_EndPoints_Correct(bool useAsync) } } + [ConditionalFact(typeof(Socket), nameof(Socket.OSSupportsUnixDomainSockets))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/52124", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] + public async Task UnixDomainSocket_Receive_GetsCanceledByDispose() + { + string path = GetRandomNonExistingFilePath(); + var endPoint = new UnixDomainSocketEndPoint(path); + + using (var server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) + using (var client = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) + { + server.Bind(endPoint); + server.Listen(1); + + client.Connect(endPoint); + int msDelay = 100; + bool readFailed = false; + byte[] buffer = new byte[100]; + using (Socket accepted = server.Accept()) + { + while (msDelay < 10_000) + { + Task disposeTask = Task.Run(() => + { + Thread.Sleep(msDelay); + client.Dispose(); + }); + + try + { + client.Receive(buffer); + } + catch (SocketException) + { + await disposeTask; + readFailed = true; + break; + } + catch (ObjectDisposedException) + { + await disposeTask; + // Dispose happened before the operation, retry. + msDelay *= 2; + continue; + } + } + } + Assert.True(readFailed); + } + } + private static string GetRandomNonExistingFilePath() { string result; diff --git a/src/native/libs/System.Native/pal_networking.c b/src/native/libs/System.Native/pal_networking.c index 113ef377294f2..9856236627faf 100644 --- a/src/native/libs/System.Native/pal_networking.c +++ b/src/native/libs/System.Native/pal_networking.c @@ -3143,6 +3143,11 @@ int32_t SystemNative_Disconnect(intptr_t socket) #elif HAVE_DISCONNECTX // disconnectx causes a FIN close on OSX. It's the best we can do. err = disconnectx(fd, SAE_ASSOCID_ANY, SAE_CONNID_ANY); + if (err != 0) + { + // This happens on Unix Domain Sockets as disconnectx is only supported on AF_INET and AF_INET6 + err = shutdown(fd, SHUT_RDWR); + } #else // best-effort, this may cause a FIN close. err = shutdown(fd, SHUT_RDWR);