public async Task ConnectGetsCanceledByDispose(string addressString, bool useDns) { IPAddress address = IPAddress.Parse(addressString); // We try this a couple of times to deal with a timing race: if the Dispose happens // before the operation is started, we won't see a SocketException. int msDelay = 100; await RetryHelper.ExecuteAsync(async() => { var client = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); if (address.IsIPv4MappedToIPv6) { client.DualMode = true; } Task connectTask = ConnectAsync(client, useDns ? new DnsEndPoint("one.one.one.one", 23) : new IPEndPoint(address, 23)); // Wait a little so the operation is started. await Task.Delay(Math.Min(msDelay, 1000)); msDelay *= 2; Task disposeTask = Task.Run(() => client.Dispose()); await Task.WhenAny(disposeTask, connectTask).WaitAsync(TimeSpan.FromSeconds(30)); await disposeTask; SocketError?localSocketError = null; bool disposedException = false; try { await connectTask; } catch (SocketException se) { // On connection timeout, retry. Assert.NotEqual(SocketError.TimedOut, se.SocketErrorCode); localSocketError = se.SocketErrorCode; } catch (ObjectDisposedException) { disposedException = true; } if (UsesApm) { Assert.Null(localSocketError); Assert.True(disposedException); } else if (UsesSync) { Assert.True(disposedException || localSocketError == SocketError.NotSocket, $"{disposedException} {localSocketError}"); } else { Assert.Equal(SocketError.OperationAborted, localSocketError); } }, maxAttempts : 10, retryWhen : e => e is XunitException); }
[PlatformSpecific(~(TestPlatforms.OSX | TestPlatforms.FreeBSD))] // Not supported on BSD like OSes. public async Task ConnectGetsCanceledByDispose() { bool usesApm = UsesApm || (this is ConnectTask); // .NET Core ConnectAsync Task API is implemented using Apm // We try this a couple of times to deal with a timing race: if the Dispose happens // before the operation is started, we won't see a SocketException. int msDelay = 100; await RetryHelper.ExecuteAsync(async() => { var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Task connectTask = ConnectAsync(client, new IPEndPoint(IPAddress.Parse("1.1.1.1"), 23)); // Wait a little so the operation is started. await Task.Delay(msDelay); msDelay *= 2; Task disposeTask = Task.Run(() => client.Dispose()); var cts = new CancellationTokenSource(); Task timeoutTask = Task.Delay(30000, cts.Token); Assert.NotSame(timeoutTask, await Task.WhenAny(disposeTask, connectTask, timeoutTask)); cts.Cancel(); await disposeTask; SocketError?localSocketError = null; bool disposedException = false; try { await connectTask; } catch (SocketException se) { // On connection timeout, retry. Assert.NotEqual(SocketError.TimedOut, se.SocketErrorCode); localSocketError = se.SocketErrorCode; } catch (ObjectDisposedException) { disposedException = true; } if (usesApm) { Assert.Null(localSocketError); Assert.True(disposedException); } else if (UsesSync) { Assert.Equal(SocketError.NotSocket, localSocketError); } else { Assert.Equal(SocketError.OperationAborted, localSocketError); } }, maxAttempts : 10); }
public async Task ClosedDuringOperation_Throws_ObjectDisposedExceptionOrSocketException(bool closeOrDispose) { if (UsesSync && PlatformDetection.IsOSX) { // [ActiveIssue("https://github.com/dotnet/runtime/issues/47342")] // On Mac, Close/Dispose hangs when invoked concurrently with a blocking UDP receive. return; } int msDelay = 100; if (UsesSync) { // In sync case Dispose may happen before the operation is started, // in that case we would see an ObjectDisposedException instead of a SocketException. // We may need to try the run a couple of times to deal with the timing race. await RetryHelper.ExecuteAsync(() => RunTestAsync(), maxAttempts : 10, retryWhen : e => e is XunitException); } else { await RunTestAsync(); } async Task RunTestAsync() { using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); socket.BindToAnonymousPort(IPAddress.Any); Task receiveTask = ReceiveMessageFromAsync(socket, new byte[1], GetGetDummyTestEndpoint()); await Task.Delay(msDelay); msDelay *= 2; if (closeOrDispose) { socket.Close(); } else { socket.Dispose(); } if (DisposeDuringOperationResultsInDisposedException) { await Assert.ThrowsAsync <ObjectDisposedException>(() => receiveTask) .TimeoutAfter(CancellationTestTimeout); } else { SocketException ex = await Assert.ThrowsAsync <SocketException>(() => receiveTask) .TimeoutAfter(CancellationTestTimeout); SocketError expectedError = UsesSync ? SocketError.Interrupted : SocketError.OperationAborted; Assert.Equal(expectedError, ex.SocketErrorCode); } } }
public async Task AcceptGetsCanceledByDispose() { // We try this a couple of times to deal with a timing race: if the Dispose happens // before the operation is started, we won't see a SocketException. int msDelay = 100; await RetryHelper.ExecuteAsync(async() => { var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listener.Bind(new IPEndPoint(IPAddress.Loopback, 0)); listener.Listen(1); Task acceptTask = AcceptAsync(listener); // Wait a little so the operation is started. await Task.Delay(msDelay); msDelay *= 2; Task disposeTask = Task.Run(() => listener.Dispose()); var cts = new CancellationTokenSource(); Task timeoutTask = Task.Delay(30000, cts.Token); Assert.NotSame(timeoutTask, await Task.WhenAny(disposeTask, acceptTask, timeoutTask)); cts.Cancel(); await disposeTask; SocketError?localSocketError = null; bool disposedException = false; try { await acceptTask; } catch (SocketException se) { localSocketError = se.SocketErrorCode; } catch (ObjectDisposedException) { disposedException = true; } if (UsesApm) { Assert.Null(localSocketError); Assert.True(disposedException); } else if (UsesSync) { Assert.Equal(SocketError.Interrupted, localSocketError); } else { Assert.Equal(SocketError.OperationAborted, localSocketError); } }, maxAttempts : 10); }
public async Task AcceptGetsCanceledByDispose(IPAddress loopback) { // We try this a couple of times to deal with a timing race: if the Dispose happens // before the operation is started, we won't see a SocketException. int msDelay = 100; await RetryHelper.ExecuteAsync(async() => { var listener = new Socket(loopback.AddressFamily, SocketType.Stream, ProtocolType.Tcp); if (loopback.IsIPv4MappedToIPv6) { listener.DualMode = true; } listener.Bind(new IPEndPoint(loopback, 0)); listener.Listen(1); Task acceptTask = AcceptAsync(listener); // Wait a little so the operation is started. await Task.Delay(msDelay); msDelay *= 2; Task disposeTask = Task.Run(() => listener.Dispose()); await Task.WhenAny(disposeTask, acceptTask).TimeoutAfter(30000); await disposeTask; SocketError?localSocketError = null; bool disposedException = false; try { await acceptTask; } catch (SocketException se) { localSocketError = se.SocketErrorCode; } catch (ObjectDisposedException) { disposedException = true; } if (UsesApm) { Assert.Null(localSocketError); Assert.True(disposedException); } else if (UsesSync) { Assert.Equal(SocketError.Interrupted, localSocketError); } else { Assert.Equal(SocketError.OperationAborted, localSocketError); } }, maxAttempts : 10, retryWhen : e => e is XunitException); }
public async Task NonDisposedSocket_SafeHandlesCollected(bool clientAsync) { TimeSpan timeout = TimeSpan.FromMilliseconds(TestSettings.PassingTestTimeout); List <WeakReference> handles = await CreateHandlesAsync(clientAsync).WaitAsync(timeout); await RetryHelper.ExecuteAsync(() => Task.Run(() => { GC.Collect(); GC.WaitForPendingFinalizers(); Assert.Equal(0, handles.Count(h => h.IsAlive)); })).WaitAsync(timeout); }