Skip to content

Commit 776ff7e

Browse files
authored
make Socket useable after cancellation (#99181)
1 parent 95a0265 commit 776ff7e

File tree

2 files changed

+73
-2
lines changed

2 files changed

+73
-2
lines changed

src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3754,7 +3754,7 @@ internal void UpdateStatusAfterSocketError(SocketError errorCode, bool disconnec
37543754

37553755
if (disconnectOnFailure && _isConnected && (_handle.IsInvalid || (errorCode != SocketError.WouldBlock &&
37563756
errorCode != SocketError.IOPending && errorCode != SocketError.NoBufferSpaceAvailable &&
3757-
errorCode != SocketError.TimedOut)))
3757+
errorCode != SocketError.TimedOut && errorCode != SocketError.OperationAborted)))
37583758
{
37593759
// The socket is no longer a valid socket.
37603760
if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, "Invalidating socket.");

src/libraries/System.Net.Sockets/tests/FunctionalTests/NetworkStreamTest.cs

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ private static async Task RunWithConnectedNetworkStreamsAsync(Func<NetworkStream
547547
await Task.WhenAll(remoteTask, clientConnectTask);
548548

549549
using (TcpClient remote = remoteTask.Result)
550-
using (NetworkStream serverStream = new NetworkStream(remote.Client, serverAccess, ownsSocket:true))
550+
using (NetworkStream serverStream = new NetworkStream(remote.Client, serverAccess, ownsSocket: true))
551551
using (NetworkStream clientStream = new NetworkStream(client.Client, clientAccess, ownsSocket: true))
552552
{
553553
await func(serverStream, clientStream);
@@ -560,6 +560,77 @@ private static async Task RunWithConnectedNetworkStreamsAsync(Func<NetworkStream
560560
}
561561
}
562562

563+
[Fact]
564+
public async Task NetworkStream_ReadTimeout_RemainUseable()
565+
{
566+
using StreamPair streams = await CreateConnectedStreamsAsync();
567+
NetworkStream readable = (NetworkStream)streams.Stream1;
568+
569+
Assert.True(readable.Socket.Connected);
570+
readable.Socket.ReceiveTimeout = TestSettings.FailingTestTimeout;
571+
var buffer = new byte[100];
572+
int readBytes;
573+
try
574+
{
575+
readBytes = readable.Read(buffer);
576+
}
577+
catch (IOException ex) when (ex.InnerException is SocketException && ((SocketException)ex.InnerException).SocketErrorCode == SocketError.TimedOut)
578+
{
579+
}
580+
Assert.True(readable.Socket.Connected);
581+
582+
try
583+
{
584+
readBytes = readable.Read(buffer);
585+
}
586+
catch (IOException ex) when (ex.InnerException is SocketException && ((SocketException)ex.InnerException).SocketErrorCode == SocketError.TimedOut)
587+
{
588+
}
589+
Assert.True(readable.Socket.Connected);
590+
591+
streams.Stream2.Write(new byte[] { 65 });
592+
readBytes = readable.Read(buffer);
593+
Assert.Equal(1, readBytes);
594+
Assert.True(readable.Socket.Connected);
595+
}
596+
597+
598+
[Fact]
599+
public async Task NetworkStream_ReadAsyncTimeout_RemainUseable()
600+
{
601+
using StreamPair streams = await CreateConnectedStreamsAsync();
602+
NetworkStream readable = (NetworkStream)streams.Stream1;
603+
604+
Assert.True(readable.Socket.Connected);
605+
606+
CancellationTokenSource cts = new CancellationTokenSource(TestSettings.FailingTestTimeout);
607+
var buffer = new byte[100];
608+
int readBytes;
609+
try
610+
{
611+
readBytes = await readable.ReadAsync(buffer, cts.Token);
612+
}
613+
catch (OperationCanceledException)
614+
{
615+
}
616+
Assert.True(readable.Socket.Connected);
617+
618+
try
619+
{
620+
cts = new CancellationTokenSource(TestSettings.FailingTestTimeout);
621+
readBytes = await readable.ReadAsync(buffer, cts.Token);
622+
}
623+
catch (OperationCanceledException)
624+
{
625+
}
626+
Assert.True(readable.Socket.Connected);
627+
628+
await streams.Stream2.WriteAsync(new byte[] { 65 });
629+
readBytes = await readable.ReadAsync(buffer);
630+
Assert.Equal(1, readBytes);
631+
Assert.True(readable.Socket.Connected);
632+
}
633+
563634
private sealed class DerivedNetworkStream : NetworkStream
564635
{
565636
public DerivedNetworkStream(Socket socket) : base(socket) { }

0 commit comments

Comments
 (0)