runtime: Disposing Socket then rebinding fails with SocketError.AddressAlreadyInUse on Unix

.NET Core 2.0.0 runtime macOS 10.12.6 Seirra and Ubuntu 16.04.2 LTS (Xenial Xerus)

using System;
using System.Net;
using System.Net.Sockets;

namespace SocketRebind
{
    class Program
    {
        static void Main(string[] args)
        {
            for (var i = 0;; i++)
            {
                Console.WriteLine("Iteration #{0}", i);

                var serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                serverSocket.Bind(new IPEndPoint(IPAddress.Loopback, 5000));
                serverSocket.Listen(512);

                var clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                clientSocket.Connect(IPAddress.Loopback, 5000);

                var acceptSocket = serverSocket.Accept();

                acceptSocket.Dispose();
                clientSocket.Dispose();
                serverSocket.Dispose();
            }
        }
    }
}

Expected behavior:

Program should iterate indefinitely. This is what happens on Windows.

Actual behavior:

After the first iteration, Socket.Bind throws “SocketException: Address already in use”

Output (identical on macOS and Ubuntu):

$ dotnet run
Iteration #0
Iteration dotnet/corefx#1

Unhandled Exception: System.Net.Sockets.SocketException: Address already in use
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at SocketRebind.Program.Main(String[] args) in /Users/shalter/source/halter73/SocketRebind/Program.cs:line 16
$
$
$ dotnet run
Iteration #0

Unhandled Exception: System.Net.Sockets.SocketException: Address already in use
   at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
   at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Bind(EndPoint localEP)
   at SocketRebind.Program.Main(String[] args) in /Users/shalter/source/halter73/SocketRebind/Program.cs:line 16

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 51 (40 by maintainers)

Commits related to this issue

Most upvoted comments

Ended up just grabbing the 2.1.302 tarball and manually installing it, and I’m happy to say it fixed the HttpListener socket issue. Thanks!

@doyouevensunbro I noticed that the debian/ubuntu repository is missing the latest SDK version yesterday. I adapted the debian dockerfile to work on Ubuntu Xenial.

# Install .NET CLI dependencies
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        libc6 \
        libgcc1 \
        libgssapi-krb5-2 \
        libicu55 \
        liblttng-ust0 \
        libssl1.0.2 \
        libstdc++6 \
        zlib1g \
    && rm -rf /var/lib/apt/lists/*

# Install .NET Core SDK
ENV DOTNET_SDK_VERSION 2.1.302

RUN curl -SL --output dotnet.tar.gz https://dotnetcli.blob.core.windows.net/dotnet/Sdk/$DOTNET_SDK_VERSION/dotnet-sdk-$DOTNET_SDK_VERSION-linux-x64.tar.gz \
    && dotnet_sha512='2166986e360f1c3456a33723edb80349e6ede115be04a6331bfbfd0f412494684d174a0cfb21d2feb00d509ce342030160a4b5b445e393ad83bedb613a64bc66' \
    && sha512sum dotnet.tar.gz \
    && echo "$dotnet_sha512 dotnet.tar.gz" | sha512sum -c - \
    && mkdir -p /usr/share/dotnet \
    && tar -zxf dotnet.tar.gz -C /usr/share/dotnet \
    && rm dotnet.tar.gz \
    && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet

# Configure Kestrel web server to bind to port 80 when present
ENV ASPNETCORE_URLS=http://+:80 \
    # Enable detection of running in a container
    DOTNET_RUNNING_IN_CONTAINER=true \
    # Enable correct mode for dotnet watch (only mode supported in a container)
    DOTNET_USE_POLLING_FILE_WATCHER=true \
    # Skip extraction of XML docs - generally not useful within an image/container - helps perfomance
    NUGET_XMLDOC_MODE=skip

# Trigger first run experience by running arbitrary cmd to populate local package cache
RUN dotnet help

Sorry about that, we are using <TargetFramework>netcoreapp2.0</TargetFramework> and I’m guessing that should be <TargetFramework>netcoreapp2.1</TargetFramework>?

@joshgarnett This should be fixed with .NET Core 2.1. If you need a workaround for now, it’s pretty ugly, but here it is. Just call EnableRebinding(socket) prior to socket.Bind(...).

@Mga-Denmark port stealing is still possible by setting ReuseAddress.