From f76b26970d4a9b3d8cce7f57ae11a674a192d892 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Fri, 30 Apr 2021 13:57:07 +0200 Subject: [PATCH 01/11] Socket: delete unix local endpoint filename on Close --- .../NamedPipeTest.UnixDomainSockets.cs | 3 +-- .../src/System/Net/Sockets/Socket.cs | 10 ++++++++++ .../Net/Sockets/UnixDomainSocketEndPoint.cs | 3 +++ .../tests/FunctionalTests/UnixDomainSocketTest.cs | 15 +++++++++++++++ 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.UnixDomainSockets.cs b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.UnixDomainSockets.cs index 7bab6b302d4dec..ff7fa1509fe020 100644 --- a/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.UnixDomainSockets.cs +++ b/src/libraries/System.IO.Pipes/tests/NamedPipeTests/NamedPipeTest.UnixDomainSockets.cs @@ -49,8 +49,7 @@ public async Task NamedPipeClient_Connects_With_UnixDomainSocketEndPointServer() } } - Assert.True(File.Exists(pipeName)); - try { File.Delete(pipeName); } catch { } + Assert.False(File.Exists(pipeName)); } } } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs index 2671112ffa139d..c2197213ee8498 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs @@ -3380,6 +3380,16 @@ protected virtual void Dispose(bool disposing) { } } + if (_rightEndPoint is UnixDomainSocketEndPoint unixEndPoint && + unixEndPoint.FileName is not null) + { + try + { + File.Delete(unixEndPoint.FileName); + } + catch + { } + } } // Clean up any cached data diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs index 8ce031120f0499..a612a0b741a1ee 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs @@ -120,6 +120,9 @@ public override string ToString() } } + internal string? FileName + => IsAbstract(_path) ? null : _path + private static bool IsAbstract(string path) => path.Length > 0 && path[0] == '\0'; private static bool IsAbstract(byte[] encodedPath) => encodedPath.Length > 0 && encodedPath[0] == 0; diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index 45bbdc29389fa6..d3b76991945bc9 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -73,6 +73,8 @@ public async Task Socket_ConnectAsyncUnixDomainSocketEndPoint_Success() Assert.Equal(SocketError.Success, args.SocketError); Assert.Null(args.ConnectByNameError); } + + Assert.False(File.Exists(path)); } finally { @@ -109,6 +111,8 @@ public async Task Socket_ConnectAsyncUnixDomainSocketEndPoint_NotServer() RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? SocketError.ConnectionRefused : SocketError.AddressNotAvailable, args.SocketError); } + + Assert.False(File.Exists(path)); } finally { @@ -146,6 +150,8 @@ public void Socket_SendReceive_Success() } } } + + Assert.False(File.Exists(path)); } finally { @@ -196,6 +202,8 @@ public void Socket_SendReceive_Clone_Success() } } } + + Assert.False(File.Exists(path)); } finally { @@ -233,6 +241,8 @@ public async Task Socket_SendReceiveAsync_Success() } } } + + Assert.False(File.Exists(path)); } finally { @@ -296,6 +306,8 @@ public async Task Socket_SendReceiveAsync_PropagateToStream_Success(int iteratio Assert.Equal(writeBuffer.Length, readData.Length); Assert.Equal(writeBuffer, readData.ToArray()); + + Assert.False(File.Exists(path)); } finally { @@ -448,6 +460,9 @@ public void UnixDomainSocketEndPoint_RemoteEndPointEqualsBindAddress(bool abstra } } } + + Assert.False(File.Exists(serverAddress)); + Assert.False(File.Exists(clientAddress)); } finally { From befd2a9eaf985557349244860768e4ad659e42d3 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Fri, 30 Apr 2021 15:49:25 +0200 Subject: [PATCH 02/11] Handle delete of relative UnixDomainSocketEndPoint path --- .../src/System/Net/Sockets/Socket.cs | 8 +++++ .../Net/Sockets/UnixDomainSocketEndPoint.cs | 2 +- .../FunctionalTests/UnixDomainSocketTest.cs | 36 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs index c2197213ee8498..e6f3db5e2c000d 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs @@ -809,6 +809,14 @@ private void DoBind(EndPoint endPointSnapshot, Internals.SocketAddress socketAdd { // Save a copy of the EndPoint so we can use it for Create(). _rightEndPoint = endPointSnapshot; + + // Capture the absolute path for UnixDomainSocketEndPoint. + if (endPointSnapshot is UnixDomainSocketEndPoint unixEndPoint && + unixEndPoint.FileName is not null && + !Path.IsPathRooted(unixEndPoint.FileName)) + { + _rightEndPoint = new UnixDomainSocketEndPoint(Path.Combine(Directory.GetCurrentDirectory(), unixEndPoint.Filename)); + } } } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs index a612a0b741a1ee..eaf90821366dbb 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs @@ -121,7 +121,7 @@ public override string ToString() } internal string? FileName - => IsAbstract(_path) ? null : _path + => IsAbstract(_path) ? null : _path; private static bool IsAbstract(string path) => path.Length > 0 && path[0] == '\0'; diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index d3b76991945bc9..7259e12deff74d 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; using Xunit; using Xunit.Abstractions; @@ -506,6 +507,41 @@ public void Socket_CreateUnixDomainSocket_Throws_OnWindows() Assert.Throws(() => new UnixDomainSocketEndPoint("hello")); } +// [ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))] + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void UnixDomainSocketEndPoint_RelativePathDeletesFile() + { + RemoteExecutor.Invoke(() => + { + using (Socket socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) + { + // Bind to a relative path. + string path = GetRandomNonExistingFilePath(); + string wd = Path.GetDirectoryName(path); + Directory.SetCurrentDirectory(wd); + socket.Bind(new UnixDomainSocketEndPoint(Path.GetFileName(path))); + Assert.True(File.Exists(path)); + + string otherDir = GetRandomNonExistingFilePath(); + Directory.CreateDirectory(otherDir); + try + { + // Change to another directory. + Directory.SetCurrentDirectory(Path.GetDirectoryName(path)); + + // Dispose deletes file from original path. + socket.Dispose(); + Assert.False(File.Exists(path)); + } + finally + { + Directory.SetCurrentDirectory(wd); + Directory.Delete(otherDir); + } + } + }).Dispose(); + } + private static string GetRandomNonExistingFilePath() { string result; From 8ba084917374a761b5bdd26ee7fe467c3382f818 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Mon, 3 May 2021 14:51:14 +0200 Subject: [PATCH 03/11] Cleanup tests --- .../FunctionalTests/UnixDomainSocketTest.cs | 292 +++++++----------- 1 file changed, 118 insertions(+), 174 deletions(-) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index 7259e12deff74d..0746348dfb33dc 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -80,9 +80,6 @@ public async Task Socket_ConnectAsyncUnixDomainSocketEndPoint_Success() finally { server.Dispose(); - - try { File.Delete(path); } - catch { } } } @@ -91,35 +88,27 @@ public async Task Socket_ConnectAsyncUnixDomainSocketEndPoint_NotServer() { string path = GetRandomNonExistingFilePath(); var endPoint = new UnixDomainSocketEndPoint(path); - try - { - SocketAsyncEventArgs args = new SocketAsyncEventArgs(); - args.RemoteEndPoint = endPoint; - args.Completed += (s, e) => ((TaskCompletionSource)e.UserToken).SetResult(); + SocketAsyncEventArgs args = new SocketAsyncEventArgs(); + args.RemoteEndPoint = endPoint; + args.Completed += (s, e) => ((TaskCompletionSource)e.UserToken).SetResult(); - var complete = new TaskCompletionSource(); - args.UserToken = complete; + var complete = new TaskCompletionSource(); + args.UserToken = complete; - using (Socket sock = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) + using (Socket sock = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) + { + bool willRaiseEvent = sock.ConnectAsync(args); + if (willRaiseEvent) { - bool willRaiseEvent = sock.ConnectAsync(args); - if (willRaiseEvent) - { - await complete.Task; - } - - Assert.Equal( - RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? SocketError.ConnectionRefused : SocketError.AddressNotAvailable, - args.SocketError); + await complete.Task; } - Assert.False(File.Exists(path)); - } - finally - { - try { File.Delete(path); } - catch { } + Assert.Equal( + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? SocketError.ConnectionRefused : SocketError.AddressNotAvailable, + args.SocketError); } + + Assert.False(File.Exists(path)); } [ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))] @@ -127,38 +116,30 @@ public void Socket_SendReceive_Success() { string path = GetRandomNonExistingFilePath(); var endPoint = new UnixDomainSocketEndPoint(path); - try + using (var server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) + using (var client = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) { - 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); + server.Bind(endPoint); + server.Listen(1); - client.Connect(endPoint); - using (Socket accepted = server.Accept()) + client.Connect(endPoint); + using (Socket accepted = server.Accept()) + { + var data = new byte[1]; + for (int i = 0; i < 10; i++) { - var data = new byte[1]; - for (int i = 0; i < 10; i++) - { - data[0] = (byte)i; + data[0] = (byte)i; - accepted.Send(data); - data[0] = 0; + accepted.Send(data); + data[0] = 0; - Assert.Equal(1, client.Receive(data)); - Assert.Equal(i, data[0]); - } + Assert.Equal(1, client.Receive(data)); + Assert.Equal(i, data[0]); } } - - Assert.False(File.Exists(path)); - } - finally - { - try { File.Delete(path); } - catch { } } + + Assert.False(File.Exists(path)); } [ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))] @@ -166,51 +147,43 @@ public void Socket_SendReceive_Clone_Success() { string path = GetRandomNonExistingFilePath(); var endPoint = new UnixDomainSocketEndPoint(path); - try + using var server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); + using var client = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); { - 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); + server.Bind(endPoint); + server.Listen(1); + client.Connect(endPoint); - using (Socket accepted = server.Accept()) - { - using var clientClone = new Socket(client.SafeHandle); - using var acceptedClone = new Socket(accepted.SafeHandle); + using (Socket accepted = server.Accept()) + { + using var clientClone = new Socket(client.SafeHandle); + using var acceptedClone = new Socket(accepted.SafeHandle); - _log.WriteLine($"accepted: LocalEndPoint={accepted.LocalEndPoint} RemoteEndPoint={accepted.RemoteEndPoint}"); - _log.WriteLine($"acceptedClone: LocalEndPoint={acceptedClone.LocalEndPoint} RemoteEndPoint={acceptedClone.RemoteEndPoint}"); + _log.WriteLine($"accepted: LocalEndPoint={accepted.LocalEndPoint} RemoteEndPoint={accepted.RemoteEndPoint}"); + _log.WriteLine($"acceptedClone: LocalEndPoint={acceptedClone.LocalEndPoint} RemoteEndPoint={acceptedClone.RemoteEndPoint}"); - Assert.True(clientClone.Connected); - Assert.True(acceptedClone.Connected); - Assert.Equal(client.LocalEndPoint.ToString(), clientClone.LocalEndPoint.ToString()); - Assert.Equal(client.RemoteEndPoint.ToString(), clientClone.RemoteEndPoint.ToString()); - Assert.Equal(accepted.LocalEndPoint.ToString(), acceptedClone.LocalEndPoint.ToString()); - Assert.Equal(accepted.RemoteEndPoint.ToString(), acceptedClone.RemoteEndPoint.ToString()); + Assert.True(clientClone.Connected); + Assert.True(acceptedClone.Connected); + Assert.Equal(client.LocalEndPoint.ToString(), clientClone.LocalEndPoint.ToString()); + Assert.Equal(client.RemoteEndPoint.ToString(), clientClone.RemoteEndPoint.ToString()); + Assert.Equal(accepted.LocalEndPoint.ToString(), acceptedClone.LocalEndPoint.ToString()); + Assert.Equal(accepted.RemoteEndPoint.ToString(), acceptedClone.RemoteEndPoint.ToString()); - var data = new byte[1]; - for (int i = 0; i < 10; i++) - { - data[0] = (byte)i; + var data = new byte[1]; + for (int i = 0; i < 10; i++) + { + data[0] = (byte)i; - acceptedClone.Send(data); - data[0] = 0; + acceptedClone.Send(data); + data[0] = 0; - Assert.Equal(1, clientClone.Receive(data)); - Assert.Equal(i, data[0]); - } + Assert.Equal(1, clientClone.Receive(data)); + Assert.Equal(i, data[0]); } } - - Assert.False(File.Exists(path)); - } - finally - { - try { File.Delete(path); } - catch { } } + + Assert.False(File.Exists(path)); } [ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))] @@ -218,38 +191,30 @@ public async Task Socket_SendReceiveAsync_Success() { string path = GetRandomNonExistingFilePath(); var endPoint = new UnixDomainSocketEndPoint(path); - try + using (var server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) + using (var client = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) { - 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); + server.Bind(endPoint); + server.Listen(1); - await client.ConnectAsync(endPoint); - using (Socket accepted = await server.AcceptAsync()) + await client.ConnectAsync(endPoint); + using (Socket accepted = await server.AcceptAsync()) + { + var data = new byte[1]; + for (int i = 0; i < 10; i++) { - var data = new byte[1]; - for (int i = 0; i < 10; i++) - { - data[0] = (byte)i; + data[0] = (byte)i; - await accepted.SendAsync(new ArraySegment(data), SocketFlags.None); - data[0] = 0; + await accepted.SendAsync(new ArraySegment(data), SocketFlags.None); + data[0] = 0; - Assert.Equal(1, await client.ReceiveAsync(new ArraySegment(data), SocketFlags.None)); - Assert.Equal(i, data[0]); - } + Assert.Equal(1, await client.ReceiveAsync(new ArraySegment(data), SocketFlags.None)); + Assert.Equal(i, data[0]); } } - - Assert.False(File.Exists(path)); - } - finally - { - try { File.Delete(path); } - catch { } } + + Assert.False(File.Exists(path)); } [ActiveIssue("https://github.com/dotnet/runtime/issues/26189", TestPlatforms.Windows)] @@ -266,55 +231,47 @@ public async Task Socket_SendReceiveAsync_PropagateToStream_Success(int iteratio string path = GetRandomNonExistingFilePath(); var endPoint = new UnixDomainSocketEndPoint(path); - try + using (var server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) + using (var client = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) { - 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); + server.Bind(endPoint); + server.Listen(1); - Task serverAccept = server.AcceptAsync(); - await Task.WhenAll(serverAccept, client.ConnectAsync(endPoint)); + Task serverAccept = server.AcceptAsync(); + await Task.WhenAll(serverAccept, client.ConnectAsync(endPoint)); - Task clientReceives = Task.Run(async () => + Task clientReceives = Task.Run(async () => + { + byte[] buffer = new byte[readBufferSize]; + while (true) { - byte[] buffer = new byte[readBufferSize]; - while (true) + int bytesRead = await client.ReceiveAsync(new Memory(buffer), SocketFlags.None); + if (bytesRead == 0) { - int bytesRead = await client.ReceiveAsync(new Memory(buffer), SocketFlags.None); - if (bytesRead == 0) - { - break; - } - Assert.InRange(bytesRead, 1, writeBuffer.Length - readData.Length); - readData.Write(buffer, 0, bytesRead); + break; } - }); + Assert.InRange(bytesRead, 1, writeBuffer.Length - readData.Length); + readData.Write(buffer, 0, bytesRead); + } + }); - using (Socket accepted = await serverAccept) + using (Socket accepted = await serverAccept) + { + for (int iter = 0; iter < iterations; iter++) { - for (int iter = 0; iter < iterations; iter++) - { - Task sendTask = accepted.SendAsync(new ArraySegment(writeBuffer, iter * writeBufferSize, writeBufferSize), SocketFlags.None); - await await Task.WhenAny(clientReceives, sendTask); - Assert.Equal(writeBufferSize, await sendTask); - } + Task sendTask = accepted.SendAsync(new ArraySegment(writeBuffer, iter * writeBufferSize, writeBufferSize), SocketFlags.None); + await await Task.WhenAny(clientReceives, sendTask); + Assert.Equal(writeBufferSize, await sendTask); } - - await clientReceives; } - Assert.Equal(writeBuffer.Length, readData.Length); - Assert.Equal(writeBuffer, readData.ToArray()); - - Assert.False(File.Exists(path)); - } - finally - { - try { File.Delete(path); } - catch { } + await clientReceives; } + + Assert.Equal(writeBuffer.Length, readData.Length); + Assert.Equal(writeBuffer, readData.ToArray()); + + Assert.False(File.Exists(path)); } [ConditionalTheory(nameof(PlatformSupportsUnixDomainSockets))] @@ -441,40 +398,27 @@ public void UnixDomainSocketEndPoint_RemoteEndPointEqualsBindAddress(bool abstra expectedClientAddress = clientAddress; } - try + using (Socket server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) { - using (Socket server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) - { - server.Bind(new UnixDomainSocketEndPoint(serverAddress)); - server.Listen(1); + server.Bind(new UnixDomainSocketEndPoint(serverAddress)); + server.Listen(1); - using (Socket client = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) + using (Socket client = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) + { + // Bind the client. + client.Bind(new UnixDomainSocketEndPoint(clientAddress)); + client.Connect(new UnixDomainSocketEndPoint(serverAddress)); + using (Socket acceptedClient = server.Accept()) { - // Bind the client. - client.Bind(new UnixDomainSocketEndPoint(clientAddress)); - client.Connect(new UnixDomainSocketEndPoint(serverAddress)); - using (Socket acceptedClient = server.Accept()) - { - // Verify the client address on the server. - EndPoint clientAddressOnServer = acceptedClient.RemoteEndPoint; - Assert.True(string.CompareOrdinal(expectedClientAddress, clientAddressOnServer.ToString()) == 0); - } + // Verify the client address on the server. + EndPoint clientAddressOnServer = acceptedClient.RemoteEndPoint; + Assert.True(string.CompareOrdinal(expectedClientAddress, clientAddressOnServer.ToString()) == 0); } } - - Assert.False(File.Exists(serverAddress)); - Assert.False(File.Exists(clientAddress)); - } - finally - { - if (!abstractAddress) - { - try { File.Delete(serverAddress); } - catch { } - try { File.Delete(clientAddress); } - catch { } - } } + + Assert.False(File.Exists(serverAddress)); + Assert.False(File.Exists(clientAddress)); } [ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))] From b52142b73d29ba166c68429de8d943d91eef05d9 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Mon, 3 May 2021 17:03:36 +0200 Subject: [PATCH 04/11] Track unix socket file ownership through _rightEndPoint --- .../src/System/Net/Sockets/Socket.cs | 97 +++++++++---------- .../Net/Sockets/UnixDomainSocketEndPoint.cs | 29 +++++- .../FunctionalTests/UnixDomainSocketTest.cs | 4 +- 3 files changed, 77 insertions(+), 53 deletions(-) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs index e6f3db5e2c000d..28e40e9c0c7d2b 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs @@ -24,8 +24,11 @@ public partial class Socket : IDisposable private SafeSocketHandle _handle; - // _rightEndPoint is null if the socket has not been bound. Otherwise, it is any EndPoint of the - // correct type (IPEndPoint, etc). + // _rightEndPoint is null if the socket has not been bound. Otherwise, it is an EndPoint of the + // correct type (IPEndPoint, etc). The Bind operation sets _rightEndPoint. Other operations must only set + // it when the value is still null. + // This enables tracking the file created by UnixDomainSocketEndPoint when the Socket is bound, + // and to delete that file when the Socket gets disposed. internal EndPoint? _rightEndPoint; internal EndPoint? _remoteEndPoint; @@ -293,7 +296,7 @@ public EndPoint? LocalEndPoint { // Update the state if we've become connected after a non-blocking connect. _isConnected = true; - _rightEndPoint = _nonBlockingConnectRightEndPoint; + _rightEndPoint ??= _nonBlockingConnectRightEndPoint; UpdateLocalEndPointOnConnect(); _nonBlockingConnectInProgress = false; } @@ -340,7 +343,7 @@ public EndPoint? RemoteEndPoint { // Update the state if we've become connected after a non-blocking connect. _isConnected = true; - _rightEndPoint = _nonBlockingConnectRightEndPoint; + _rightEndPoint ??= _nonBlockingConnectRightEndPoint; UpdateLocalEndPointOnConnect(); _nonBlockingConnectInProgress = false; } @@ -445,7 +448,7 @@ public bool Connected { // Update the state if we've become connected after a non-blocking connect. _isConnected = true; - _rightEndPoint = _nonBlockingConnectRightEndPoint; + _rightEndPoint ??= _nonBlockingConnectRightEndPoint; UpdateLocalEndPointOnConnect(); _nonBlockingConnectInProgress = false; } @@ -805,19 +808,16 @@ private void DoBind(EndPoint endPointSnapshot, Internals.SocketAddress socketAdd UpdateStatusAfterSocketErrorAndThrowException(errorCode); } - if (_rightEndPoint == null) + if (!IsWildcardEndPoint(_rightEndPoint)) { - // Save a copy of the EndPoint so we can use it for Create(). - _rightEndPoint = endPointSnapshot; - - // Capture the absolute path for UnixDomainSocketEndPoint. - if (endPointSnapshot is UnixDomainSocketEndPoint unixEndPoint && - unixEndPoint.FileName is not null && - !Path.IsPathRooted(unixEndPoint.FileName)) - { - _rightEndPoint = new UnixDomainSocketEndPoint(Path.Combine(Directory.GetCurrentDirectory(), unixEndPoint.Filename)); - } + _localEndPoint = _rightEndPoint; } + + // Save a copy of the EndPoint so we can use it for Create(). + // For UnixDomainSocketEndPoint, track the file to delete on Dispose. + _rightEndPoint = endPointSnapshot is UnixDomainSocketEndPoint unixEndPoint ? + unixEndPoint.CreateBoundEndPoint() : + endPointSnapshot; } // Establishes a connection to a remote system. @@ -1371,11 +1371,8 @@ public int SendTo(byte[] buffer, int offset, int size, SocketFlags socketFlags, if (SocketType == SocketType.Dgram) SocketsTelemetry.Log.DatagramSent(); } - if (_rightEndPoint == null) - { - // Save a copy of the EndPoint so we can use it for Create(). - _rightEndPoint = remoteEP; - } + // Save a copy of the EndPoint so we can use it for Create(). + _rightEndPoint ??= remoteEP; if (NetEventSource.Log.IsEnabled()) NetEventSource.DumpBuffer(this, buffer, offset, size); return bytesTransferred; @@ -1592,11 +1589,8 @@ public int ReceiveMessageFrom(byte[] buffer, int offset, int size, ref SocketFla catch { } - if (_rightEndPoint == null) - { - // Save a copy of the EndPoint so we can use it for Create(). - _rightEndPoint = endPointSnapshot; - } + // Save a copy of the EndPoint so we can use it for Create(). + _rightEndPoint ??= endPointSnapshot; } if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, errorCode); @@ -1686,11 +1680,8 @@ public int ReceiveMessageFrom(Span buffer, ref SocketFlags socketFlags, re catch { } - if (_rightEndPoint == null) - { - // Save a copy of the EndPoint so we can use it for Create(). - _rightEndPoint = endPointSnapshot; - } + // Save a copy of the EndPoint so we can use it for Create(). + _rightEndPoint ??= endPointSnapshot; } if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(this, errorCode); @@ -1749,11 +1740,8 @@ public int ReceiveFrom(byte[] buffer, int offset, int size, SocketFlags socketFl catch { } - if (_rightEndPoint == null) - { - // Save a copy of the EndPoint so we can use it for Create(). - _rightEndPoint = endPointSnapshot; - } + // Save a copy of the EndPoint so we can use it for Create(). + _rightEndPoint ??= endPointSnapshot; } if (socketException != null) @@ -3136,10 +3124,7 @@ private bool SendToAsync(SocketAsyncEventArgs e, CancellationToken cancellationT e.StartOperationCommon(this, SocketAsyncOperation.SendTo); EndPoint? oldEndPoint = _rightEndPoint; - if (_rightEndPoint == null) - { - _rightEndPoint = endPointSnapshot; - } + _rightEndPoint ??= endPointSnapshot; SocketError socketError; try @@ -3148,7 +3133,7 @@ private bool SendToAsync(SocketAsyncEventArgs e, CancellationToken cancellationT } catch { - _rightEndPoint = null; + _rightEndPoint = oldEndPoint; _localEndPoint = null; // Clear in-use flag on event args object. e.Complete(); @@ -3256,11 +3241,8 @@ private void DoConnect(EndPoint endPointSnapshot, Internals.SocketAddress socket if (SocketsTelemetry.Log.IsEnabled()) SocketsTelemetry.Log.AfterConnect(SocketError.Success); - if (_rightEndPoint == null) - { - // Save a copy of the EndPoint so we can use it for Create(). - _rightEndPoint = endPointSnapshot; - } + // Save a copy of the EndPoint so we can use it for Create(). + _rightEndPoint ??= endPointSnapshot; if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"connection to:{endPointSnapshot}"); @@ -3388,12 +3370,14 @@ protected virtual void Dispose(bool disposing) { } } + + // Delete file of bound UnixDomainSocketEndPoint. if (_rightEndPoint is UnixDomainSocketEndPoint unixEndPoint && - unixEndPoint.FileName is not null) + unixEndPoint.BoundFileName is not null) { try { - File.Delete(unixEndPoint.FileName); + File.Delete(unixEndPoint.BoundFileName); } catch { } @@ -3652,9 +3636,24 @@ internal Socket UpdateAcceptSocket(Socket socket, EndPoint remoteEP) socket._addressFamily = _addressFamily; socket._socketType = _socketType; socket._protocolType = _protocolType; - socket._rightEndPoint = _rightEndPoint; socket._remoteEndPoint = remoteEP; + // If the _rightEndpoint tracks a UnixDomainSocketEndPoint to delete, + // create a new EndPoint. + if (_localEndPoint != null) + { + socket._rightEndPoint = _localEndPoint; + } + else if (_rightEndPoint is UnixDomainSocketEndPoint unixEndPoint && + unixEndPoint.BoundFileName is not null) + { + socket._rightEndPoint = unixEndPoint.CreateUnboundEndPoint(); + } + else + { + socket._rightEndPoint = _rightEndPoint; + } + // If the listener socket was bound to a wildcard address, then the `accept` system call // will assign a specific address to the accept socket's local endpoint instead of a // wildcard address. In that case we should not copy listener's wildcard local endpoint. diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs index eaf90821366dbb..f400873433c6e5 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs @@ -3,6 +3,7 @@ using System.Diagnostics; using System.Text; +using System.IO; namespace System.Net.Sockets { @@ -14,13 +15,22 @@ public sealed partial class UnixDomainSocketEndPoint : EndPoint private readonly string _path; private readonly byte[] _encodedPath; + // Tracks the file Socket should delete on Dispose. + internal string? BoundFileName { get; } + public UnixDomainSocketEndPoint(string path) + : this(path, null) + { } + + private UnixDomainSocketEndPoint(string path, string? boundFileName) { if (path == null) { throw new ArgumentNullException(nameof(path)); } + BoundFileName = boundFileName; + // Pathname socket addresses should be null-terminated. // Linux abstract socket addresses start with a zero byte, they must not be null-terminated. bool isAbstract = IsAbstract(path); @@ -120,8 +130,23 @@ public override string ToString() } } - internal string? FileName - => IsAbstract(_path) ? null : _path; + internal UnixDomainSocketEndPoint CreateBoundEndPoint() + { + if (IsAbstract(_path)) + { + return this; + } + return new UnixDomainSocketEndPoint(_path, Path.GetFullPath(_path)); + } + + internal UnixDomainSocketEndPoint CreateUnboundEndPoint() + { + if (IsAbstract(_path) || BoundFileName is null) + { + return this; + } + return new UnixDomainSocketEndPoint(_path, null); + } private static bool IsAbstract(string path) => path.Length > 0 && path[0] == '\0'; diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index 0746348dfb33dc..67114c5ddeebf1 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -74,12 +74,12 @@ public async Task Socket_ConnectAsyncUnixDomainSocketEndPoint_Success() Assert.Equal(SocketError.Success, args.SocketError); Assert.Null(args.ConnectByNameError); } - - Assert.False(File.Exists(path)); } finally { server.Dispose(); + + Assert.False(File.Exists(path)); } } From 4aca3c651630472cb4cae2b1cc46b55f1c30c604 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Tue, 4 May 2021 09:06:25 +0200 Subject: [PATCH 05/11] Fix Socket_SendReceive_Clone_Success test --- .../FunctionalTests/UnixDomainSocketTest.cs | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index 67114c5ddeebf1..99d65b6db39f02 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -148,37 +148,39 @@ public void Socket_SendReceive_Clone_Success() 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); - - using (Socket accepted = server.Accept()) + using var client = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); { - using var clientClone = new Socket(client.SafeHandle); - using var acceptedClone = new Socket(accepted.SafeHandle); + server.Bind(endPoint); + server.Listen(1); + client.Connect(endPoint); - _log.WriteLine($"accepted: LocalEndPoint={accepted.LocalEndPoint} RemoteEndPoint={accepted.RemoteEndPoint}"); - _log.WriteLine($"acceptedClone: LocalEndPoint={acceptedClone.LocalEndPoint} RemoteEndPoint={acceptedClone.RemoteEndPoint}"); + using (Socket accepted = server.Accept()) + { + using var clientClone = new Socket(client.SafeHandle); + using var acceptedClone = new Socket(accepted.SafeHandle); - Assert.True(clientClone.Connected); - Assert.True(acceptedClone.Connected); - Assert.Equal(client.LocalEndPoint.ToString(), clientClone.LocalEndPoint.ToString()); - Assert.Equal(client.RemoteEndPoint.ToString(), clientClone.RemoteEndPoint.ToString()); - Assert.Equal(accepted.LocalEndPoint.ToString(), acceptedClone.LocalEndPoint.ToString()); - Assert.Equal(accepted.RemoteEndPoint.ToString(), acceptedClone.RemoteEndPoint.ToString()); + _log.WriteLine($"accepted: LocalEndPoint={accepted.LocalEndPoint} RemoteEndPoint={accepted.RemoteEndPoint}"); + _log.WriteLine($"acceptedClone: LocalEndPoint={acceptedClone.LocalEndPoint} RemoteEndPoint={acceptedClone.RemoteEndPoint}"); - var data = new byte[1]; - for (int i = 0; i < 10; i++) - { - data[0] = (byte)i; + Assert.True(clientClone.Connected); + Assert.True(acceptedClone.Connected); + Assert.Equal(client.LocalEndPoint.ToString(), clientClone.LocalEndPoint.ToString()); + Assert.Equal(client.RemoteEndPoint.ToString(), clientClone.RemoteEndPoint.ToString()); + Assert.Equal(accepted.LocalEndPoint.ToString(), acceptedClone.LocalEndPoint.ToString()); + Assert.Equal(accepted.RemoteEndPoint.ToString(), acceptedClone.RemoteEndPoint.ToString()); - acceptedClone.Send(data); - data[0] = 0; + var data = new byte[1]; + for (int i = 0; i < 10; i++) + { + data[0] = (byte)i; - Assert.Equal(1, clientClone.Receive(data)); - Assert.Equal(i, data[0]); + acceptedClone.Send(data); + data[0] = 0; + + Assert.Equal(1, clientClone.Receive(data)); + Assert.Equal(i, data[0]); + } } } } From 2dde20f66144749698c1c795ac5979fce5a2d1ba Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Wed, 19 May 2021 11:52:30 +0200 Subject: [PATCH 06/11] Remove code using _localEndPoint --- .../src/System/Net/Sockets/Socket.cs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs index 551221953fc713..d39964c6f60a69 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs @@ -802,11 +802,6 @@ private void DoBind(EndPoint endPointSnapshot, Internals.SocketAddress socketAdd UpdateStatusAfterSocketErrorAndThrowException(errorCode); } - if (!IsWildcardEndPoint(_rightEndPoint)) - { - _localEndPoint = _rightEndPoint; - } - // Save a copy of the EndPoint so we can use it for Create(). // For UnixDomainSocketEndPoint, track the file to delete on Dispose. _rightEndPoint = endPointSnapshot is UnixDomainSocketEndPoint unixEndPoint ? @@ -3615,13 +3610,9 @@ internal Socket UpdateAcceptSocket(Socket socket, EndPoint remoteEP) socket._protocolType = _protocolType; socket._remoteEndPoint = remoteEP; - // If the _rightEndpoint tracks a UnixDomainSocketEndPoint to delete, - // create a new EndPoint. - if (_localEndPoint != null) - { - socket._rightEndPoint = _localEndPoint; - } - else if (_rightEndPoint is UnixDomainSocketEndPoint unixEndPoint && + // If the _rightEndpoint tracks a UnixDomainSocketEndPoint to delete + // then create a new EndPoint. + if (_rightEndPoint is UnixDomainSocketEndPoint unixEndPoint && unixEndPoint.BoundFileName is not null) { socket._rightEndPoint = unixEndPoint.CreateUnboundEndPoint(); From 779f3f70ecb2602a173670c8105bf076d18b55e6 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Wed, 19 May 2021 12:31:41 +0200 Subject: [PATCH 07/11] Fix bad merge with master --- .../tests/FunctionalTests/UnixDomainSocketTest.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index e5b04e1bcdb9df..b3ac720f5ce390 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -102,11 +102,7 @@ public async Task Socket_ConnectAsyncUnixDomainSocketEndPoint_NotServer() bool willRaiseEvent = sock.ConnectAsync(args); if (willRaiseEvent) { - bool willRaiseEvent = sock.ConnectAsync(args); - if (willRaiseEvent) - { - await complete.Task; - } + await complete.Task; Assert.Equal( OperatingSystem.IsWindows() ? SocketError.ConnectionRefused : SocketError.AddressNotAvailable, From 580e4d9c4c4b1381b591cffa2c70d59c83e705de Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Wed, 19 May 2021 12:36:34 +0200 Subject: [PATCH 08/11] Fix Socket_SendReceive_Clone_Success --- .../FunctionalTests/UnixDomainSocketTest.cs | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index b3ac720f5ce390..bd695f94acc9c5 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -155,40 +155,38 @@ public void Socket_SendReceive_Clone_Success() { string path = GetRandomNonExistingFilePath(); var endPoint = new UnixDomainSocketEndPoint(path); - using var server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); + using (var server = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) + using (var client = 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); + server.Bind(endPoint); + server.Listen(1); + client.Connect(endPoint); - using (Socket accepted = server.Accept()) - { - using var clientClone = new Socket(client.SafeHandle); - using var acceptedClone = new Socket(accepted.SafeHandle); + using (Socket accepted = server.Accept()) + { + using var clientClone = new Socket(client.SafeHandle); + using var acceptedClone = new Socket(accepted.SafeHandle); - _log.WriteLine($"accepted: LocalEndPoint={accepted.LocalEndPoint} RemoteEndPoint={accepted.RemoteEndPoint}"); - _log.WriteLine($"acceptedClone: LocalEndPoint={acceptedClone.LocalEndPoint} RemoteEndPoint={acceptedClone.RemoteEndPoint}"); + _log.WriteLine($"accepted: LocalEndPoint={accepted.LocalEndPoint} RemoteEndPoint={accepted.RemoteEndPoint}"); + _log.WriteLine($"acceptedClone: LocalEndPoint={acceptedClone.LocalEndPoint} RemoteEndPoint={acceptedClone.RemoteEndPoint}"); - Assert.True(clientClone.Connected); - Assert.True(acceptedClone.Connected); - Assert.Equal(client.LocalEndPoint.ToString(), clientClone.LocalEndPoint.ToString()); - Assert.Equal(client.RemoteEndPoint.ToString(), clientClone.RemoteEndPoint.ToString()); - Assert.Equal(accepted.LocalEndPoint.ToString(), acceptedClone.LocalEndPoint.ToString()); - Assert.Equal(accepted.RemoteEndPoint.ToString(), acceptedClone.RemoteEndPoint.ToString()); + Assert.True(clientClone.Connected); + Assert.True(acceptedClone.Connected); + Assert.Equal(client.LocalEndPoint.ToString(), clientClone.LocalEndPoint.ToString()); + Assert.Equal(client.RemoteEndPoint.ToString(), clientClone.RemoteEndPoint.ToString()); + Assert.Equal(accepted.LocalEndPoint.ToString(), acceptedClone.LocalEndPoint.ToString()); + Assert.Equal(accepted.RemoteEndPoint.ToString(), acceptedClone.RemoteEndPoint.ToString()); - var data = new byte[1]; - for (int i = 0; i < 10; i++) - { - data[0] = (byte)i; + var data = new byte[1]; + for (int i = 0; i < 10; i++) + { + data[0] = (byte)i; - acceptedClone.Send(data); - data[0] = 0; + acceptedClone.Send(data); + data[0] = 0; - Assert.Equal(1, clientClone.Receive(data)); - Assert.Equal(i, data[0]); - } + Assert.Equal(1, clientClone.Receive(data)); + Assert.Equal(i, data[0]); } } } From 1cba885c48383a31f28b8ffdd5b92835f0e7b654 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 20 May 2021 14:15:22 +0200 Subject: [PATCH 09/11] Socket_ConnectAsyncUnixDomainSocketEndPoint_NotServer: remove Assert that fails on Windows --- .../FunctionalTests/UnixDomainSocketTest.cs | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index bd695f94acc9c5..f6722b65472d12 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -90,31 +90,37 @@ public async Task Socket_ConnectAsyncUnixDomainSocketEndPoint_NotServer() { string path = GetRandomNonExistingFilePath(); var endPoint = new UnixDomainSocketEndPoint(path); - SocketAsyncEventArgs args = new SocketAsyncEventArgs(); - args.RemoteEndPoint = endPoint; - args.Completed += (s, e) => ((TaskCompletionSource)e.UserToken).SetResult(); + try + { + SocketAsyncEventArgs args = new SocketAsyncEventArgs(); + args.RemoteEndPoint = endPoint; + args.Completed += (s, e) => ((TaskCompletionSource)e.UserToken).SetResult(); - var complete = new TaskCompletionSource(); - args.UserToken = complete; + var complete = new TaskCompletionSource(); + args.UserToken = complete; - using (Socket sock = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) - { - bool willRaiseEvent = sock.ConnectAsync(args); - if (willRaiseEvent) + using (Socket sock = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified)) { - await complete.Task; + bool willRaiseEvent = sock.ConnectAsync(args); + if (willRaiseEvent) + { + await complete.Task; + + Assert.Equal( + OperatingSystem.IsWindows() ? SocketError.ConnectionRefused : SocketError.AddressNotAvailable, + args.SocketError); + } Assert.Equal( - OperatingSystem.IsWindows() ? SocketError.ConnectionRefused : SocketError.AddressNotAvailable, + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? SocketError.ConnectionRefused : SocketError.AddressNotAvailable, args.SocketError); } - - Assert.Equal( - RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? SocketError.ConnectionRefused : SocketError.AddressNotAvailable, - args.SocketError); } - - Assert.False(File.Exists(path)); + finally + { + try { File.Delete(path); } + catch { } + } } [ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))] From ae2f7351707dfa229b3fda8c3f64bbc6be21f85d Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Tue, 25 May 2021 12:38:11 +0200 Subject: [PATCH 10/11] UnixDomainSocketEndPoint_RelativePathDeletesFile: add PlatformSupportsUnixDomainSockets condition --- .../tests/FunctionalTests/UnixDomainSocketTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index f6722b65472d12..038b170f871e67 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -471,7 +471,7 @@ public void Socket_CreateUnixDomainSocket_Throws_OnWindows() Assert.Throws(() => new UnixDomainSocketEndPoint("hello")); } -// [ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))] + [ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))] [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void UnixDomainSocketEndPoint_RelativePathDeletesFile() { From f52250ebb958f802886e6753c246cbe9d0ffac24 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Thu, 27 May 2021 14:15:16 +0200 Subject: [PATCH 11/11] UnixDomainSocketEndPoint_RelativePathDeletesFile: fix, can't have two ConditionalFact attributes. --- .../tests/FunctionalTests/UnixDomainSocketTest.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs index 038b170f871e67..9ed4e703f552d3 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs @@ -471,10 +471,13 @@ public void Socket_CreateUnixDomainSocket_Throws_OnWindows() Assert.Throws(() => new UnixDomainSocketEndPoint("hello")); } - [ConditionalFact(nameof(PlatformSupportsUnixDomainSockets))] [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void UnixDomainSocketEndPoint_RelativePathDeletesFile() { + if (!PlatformSupportsUnixDomainSockets) + { + return; + } RemoteExecutor.Invoke(() => { using (Socket socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified))