예제 #1
0
        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);
        }
예제 #2
0
        [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);
        }
예제 #3
0
        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);
                }
            }
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }