diff --git a/src/MongoDB.Driver/Core/Connections/TcpStreamFactory.cs b/src/MongoDB.Driver/Core/Connections/TcpStreamFactory.cs index ae2c1fb69b4..3e435d3fd12 100644 --- a/src/MongoDB.Driver/Core/Connections/TcpStreamFactory.cs +++ b/src/MongoDB.Driver/Core/Connections/TcpStreamFactory.cs @@ -164,7 +164,11 @@ private async Task ConnectAsync(Socket socket, EndPoint endPoint, CancellationTo if (!connectTask.IsCompleted) { - try { socket.Dispose(); } catch { } + try + { + connectTask.IgnoreExceptions(); + socket.Dispose(); + } catch { } cancellationToken.ThrowIfCancellationRequested(); throw new TimeoutException($"Timed out connecting to {endPoint}. Timeout was {_settings.ConnectTimeout}."); diff --git a/tests/MongoDB.Driver.Tests/Core/Connections/TcpStreamFactoryTests.cs b/tests/MongoDB.Driver.Tests/Core/Connections/TcpStreamFactoryTests.cs index 014f1b6a523..d1cc67d23ca 100644 --- a/tests/MongoDB.Driver.Tests/Core/Connections/TcpStreamFactoryTests.cs +++ b/tests/MongoDB.Driver.Tests/Core/Connections/TcpStreamFactoryTests.cs @@ -185,6 +185,43 @@ public void CreateStream_should_connect_to_a_running_server_and_return_a_non_nul stream.Should().NotBeNull(); } + [Fact] + public async Task CreateStream_should_not_produce_unobserved_exceptions_on_timeout() + { + // The purpose of this test is to attempt a connection that will reliably be rejected and throw exception the connection. + // By specifying a very short timeout, we expect a TimeoutException to occur before the connection exception. + // This test ensures that the connection exception is observed. + var subject = new TcpStreamFactory(new TcpStreamSettings(connectTimeout: TimeSpan.FromMilliseconds(1))); + var endpoint = new IPEndPoint(IPAddress.Parse("1.1.1.1"), 23456); + + GC.Collect(); + GC.WaitForPendingFinalizers(); + var unobservedTaskExceptionRaised = false; + + EventHandler eventHandler = (s, args) => + { + unobservedTaskExceptionRaised = true; + }; + + TaskScheduler.UnobservedTaskException += eventHandler; + + try + { + var exception = await Record.ExceptionAsync(() => subject.CreateStreamAsync(endpoint, CancellationToken.None)); + exception.Should().BeOfType(); + + Thread.Sleep(100); + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + finally + { + TaskScheduler.UnobservedTaskException -= eventHandler; + } + + unobservedTaskExceptionRaised.Should().BeFalse(); + } + [Theory] [ParameterAttributeData] public void SocketConfigurator_can_be_used_to_set_keepAlive(