Hi,
We are experiencing an issue on Linux, building with publish -r linux-x64.
It looks like TcpListener.Stop() hangs when we try to orderly shutdown the server.
The socket is waiting for an Accept, then other thread does TcpListener.Stop().
The same code works fine on Windows (.NET Core) and also on Linux/Mono.
Here the sequence is:
- We start the server.
- We try to stop it.
- It takes forever to finish.
- Attaching the debugger (from Visual Studio on Windows, which is awesome :P) we see the process is stopped in TcpListener.Stop and never leaves.
Attached a repro case, but the code is super simple:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace tcplistenertest
{
class Program
{
static void Main(string[] args)
{
Thread listenerThread = StartBackgroundThread(new ThreadStart(ThreadProc));
while(Console.ReadLine() != string.Empty)
{
}
mListener.Stop();
listenerThread.Join();
}
static void ThreadProc()
{
try
{
mListener = StartListening();
AcceptLoop(mListener);
}
catch(Exception e)
{
Console.WriteLine($"ThreadProc error: {e.Message}");
Console.WriteLine($"Stack trace:{Environment.NewLine}{e.StackTrace}");
}
}
static Thread StartBackgroundThread(ThreadStart task)
{
Thread thread = new Thread(task);
thread.IsBackground = true;
thread.Start();
return thread;
}
static TcpListener StartListening()
{
TcpListener result = new TcpListener(IPAddress.Any, PORT);
result.Start();
return result;
}
static void AcceptLoop(TcpListener listener)
{
// this is the main loop of the Socket based server
while (true)
{
Socket socket = null;
try
{
Console.WriteLine("Accepting connection...");
socket = AcceptConnection(listener);
Console.WriteLine($"Connection accepted from {socket.RemoteEndPoint}");
}
catch (SocketException e)
{
Console.WriteLine($"Socket error accepting connection: {e.Message}");
Console.WriteLine($"Stack trace:{Environment.NewLine}{e.StackTrace}");
break;
}
catch (Exception e)
{
Console.WriteLine($"Generic error accepting connection: {e.Message}");
Console.WriteLine($"Stack trace:{Environment.NewLine}{e.StackTrace}");
break;
}
try
{
socket.Close();
}
catch (Exception e)
{
Console.WriteLine($"Error closing socket: {e.Message}");
Console.WriteLine($"Stack trace:{Environment.NewLine}{e.StackTrace}");
break;
}
}
Console.WriteLine("Accept loop thread stopping");
}
static Socket AcceptConnection(TcpListener listener)
{
Socket socket = listener.AcceptSocket();
try
{
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.Debug, 1);
LingerOption optionValue = new LingerOption(true, 3);
socket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.Linger, optionValue);
return socket;
}
catch (Exception)
{
socket.Close();
throw;
}
}
static TcpListener mListener;
const int PORT = 55000;
}
}
tcplistenertest-1.zip
Thanks!
pablo
[EDIT] Add C# syntax highlighting by @karelz
Hi,
We are experiencing an issue on Linux, building with publish -r linux-x64.
It looks like TcpListener.Stop() hangs when we try to orderly shutdown the server.
The socket is waiting for an Accept, then other thread does TcpListener.Stop().
The same code works fine on Windows (.NET Core) and also on Linux/Mono.
Here the sequence is:
Attached a repro case, but the code is super simple:
tcplistenertest-1.zip
Thanks!
pablo
[EDIT] Add C# syntax highlighting by @karelz