Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot reuse Unix Domain Socket on Windows #71291

Open
sakno opened this issue Jun 25, 2022 · 2 comments
Open

Cannot reuse Unix Domain Socket on Windows #71291

sakno opened this issue Jun 25, 2022 · 2 comments

Comments

@sakno
Copy link
Contributor

sakno commented Jun 25, 2022

Description

On Linux, Socket.DisconnectAsync works fine and allows to reuse Socket object to connect again. On Windows, DisconnectAsync completes successfully. However, subsequent call of ConnectAsync fails with SocketException and SocketError.IsConnected error. At the same time, Socket.Connected property returns false.

Reproduction Steps

[Fact]
        public static async Task CannotReuseSocketRepro()
        {
            var path = new UnixDomainSocketEndPoint(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()));

            // server
            using var serverCts = new CancellationTokenSource();
            var server = RunServer(path, serverCts.Token);

            // client
            using (var clientSocket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified))
            {
                var buffer = new byte[512];
                await clientSocket.ConnectAsync(path);
                var count = await clientSocket.ReceiveAsync(buffer, SocketFlags.None);
                Equal("Hello", Encoding.UTF8.GetString(buffer, 0, count));
                await clientSocket.DisconnectAsync(reuseSocket: true);

                // on Linux the connection is successful here, on Windows - failure
                await clientSocket.ConnectAsync(path);
                count = await clientSocket.ReceiveAsync(buffer, SocketFlags.None);
                Equal("Hello", Encoding.UTF8.GetString(buffer, 0, count));
                await clientSocket.DisconnectAsync(reuseSocket: true);
            }

            serverCts.Cancel();
            await server;
        }

        private static async Task RunServer(UnixDomainSocketEndPoint endPoint, CancellationToken token)
        {
            using var serverSocket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
            serverSocket.Bind(endPoint);
            serverSocket.Listen();

            while (!token.IsCancellationRequested)
            {
                using var acceptedSocket = await serverSocket.AcceptAsync(token);
                await acceptedSocket.SendAsync(Encoding.UTF8.GetBytes("Hello"), SocketFlags.None, token);
                await acceptedSocket.DisconnectAsync(reuseSocket: false, token);
            }
        }

Expected behavior

Behavior on Linux and Windows must be identical.

Actual behavior

On Windows, it is not possible to call ConnectAsync on disconnected socket.

Regression?

No

Known Workarounds

Recreate socket on client side by the cost of allocation.

Configuration

.NET 6.0.301
Windows 10 Enterprise 20H2 (Build 1904.1706)

Other information

No response

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Jun 25, 2022
@ghost
Copy link

ghost commented Jun 25, 2022

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

On Linux, Socket.DisconnectAsync works fine and allows to reuse Socket object to connect again. On Windows, DisconnectAsync completes successfully. However, subsequent call of ConnectAsync fails with SocketException and SocketError.IsConnected error. At the same time, Socket.Connected property returns false.

Reproduction Steps

[Fact]
        public static async Task CannotReuseSocketRepro()
        {
            var path = new UnixDomainSocketEndPoint(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()));

            // server
            using var serverCts = new CancellationTokenSource();
            var server = RunServer(path, serverCts.Token);

            // client
            using (var clientSocket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified))
            {
                var buffer = new byte[512];
                await clientSocket.ConnectAsync(path);
                var count = await clientSocket.ReceiveAsync(buffer, SocketFlags.None);
                Equal("Hello", Encoding.UTF8.GetString(buffer, 0, count));
                await clientSocket.DisconnectAsync(reuseSocket: true);

                // on Linux the connection is successful here, on Windows - failure
                await clientSocket.ConnectAsync(path);
                count = await clientSocket.ReceiveAsync(buffer, SocketFlags.None);
                Equal("Hello", Encoding.UTF8.GetString(buffer, 0, count));
                await clientSocket.DisconnectAsync(reuseSocket: true);
            }

            serverCts.Cancel();
            await server;
        }

        private static async Task RunServer(UnixDomainSocketEndPoint endPoint, CancellationToken token)
        {
            using var serverSocket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
            serverSocket.Bind(endPoint);
            serverSocket.Listen();

            while (!token.IsCancellationRequested)
            {
                using var acceptedSocket = await serverSocket.AcceptAsync(token);
                await acceptedSocket.SendAsync(Encoding.UTF8.GetBytes("Hello"), SocketFlags.None, token);
                await acceptedSocket.DisconnectAsync(reuseSocket: false, token);
            }
        }

Expected behavior

Behavior on Linux and Windows must be identical.

Actual behavior

On Windows, it is not possible to call ConnectAsync on disconnected socket.

Regression?

No

Known Workarounds

Recreate socket on client side by the cost of allocation.

Configuration

.NET 6.0.301
Windows 10 Enterprise 20H2 (Build 1904.1706)

Other information

No response

Author: sakno
Assignees: -
Labels:

area-System.Net.Sockets

Milestone: -

@karelz karelz added bug and removed untriaged New issue has not been triaged by the area owner labels Jun 28, 2022
@karelz karelz added this to the Future milestone Jun 28, 2022
@karelz
Copy link
Member

karelz commented Jun 28, 2022

Triage: Would be nice to understand it and route it to appropriate team (us or Windows). Not high pri -> Future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants