Skip to content

Commit

Permalink
[release/5.0-rc2] Restore exception compatibility in TcpListener.EndA…
Browse files Browse the repository at this point in the history
…ccept*** (#41938)

Backport of #41745 to release/5.0-rc2
  • Loading branch information
github-actions[bot] committed Sep 8, 2020
1 parent 3e44435 commit 944d33e
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,13 @@ public TcpClient AcceptTcpClient()
TaskToApm.Begin(AcceptSocketAsync(), callback, state);

public Socket EndAcceptSocket(IAsyncResult asyncResult) =>
TaskToApm.End<Socket>(asyncResult);
EndAcceptCore<Socket>(asyncResult);

public IAsyncResult BeginAcceptTcpClient(AsyncCallback? callback, object? state) =>
TaskToApm.Begin(AcceptTcpClientAsync(), callback, state);

public TcpClient EndAcceptTcpClient(IAsyncResult asyncResult) =>
TaskToApm.End<TcpClient>(asyncResult);
EndAcceptCore<TcpClient>(asyncResult);

public Task<Socket> AcceptSocketAsync()
{
Expand Down Expand Up @@ -280,5 +280,19 @@ private void CreateNewSocketIfNeeded()
_allowNatTraversal = null; // Reset value to avoid affecting more sockets
}
}

private TResult EndAcceptCore<TResult>(IAsyncResult asyncResult)
{
try
{
return TaskToApm.End<TResult>(asyncResult);
}
catch (SocketException) when (!_active)
{
// Socket.EndAccept(iar) throws ObjectDisposedException when the underlying socket gets closed.
// TcpClient's documented behavior was to propagate that exception, we need to emulate it for compatibility:
throw new ObjectDisposedException(typeof(Socket).FullName);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,36 @@ public void ExclusiveAddressUse_SetStartAndStopListenerThenRead_ReadSuccessfully
Assert.True(listener.ExclusiveAddressUse);
}

[Fact]
public void EndAcceptSocket_WhenStopped_ThrowsObjectDisposedException()
{
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();

IAsyncResult iar = listener.BeginAcceptSocket(callback: null, state: null);

// Give some time for the underlying OS operation to start:
Thread.Sleep(50);
listener.Stop();

Assert.Throws<ObjectDisposedException>(() => listener.EndAcceptSocket(iar));
}

[Fact]
public void EndAcceptTcpClient_WhenStopped_ThrowsObjectDisposedException()
{
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();

IAsyncResult iar = listener.BeginAcceptTcpClient(callback: null, state: null);

// Give some time for the underlying OS operation to start:
Thread.Sleep(50);
listener.Stop();

Assert.Throws<ObjectDisposedException>(() => listener.EndAcceptTcpClient(iar));
}

private sealed class DerivedTcpListener : TcpListener
{
#pragma warning disable 0618
Expand Down

0 comments on commit 944d33e

Please sign in to comment.