Skip to content

Commit 6b9eb50

Browse files
committed
CSHARP-5798: Implement test to track if any UnobservedTaskExceptions were raised while test run
1 parent fe6f12f commit 6b9eb50

File tree

1 file changed

+38
-8
lines changed

1 file changed

+38
-8
lines changed

src/MongoDB.Driver/Core/Connections/TcpStreamFactory.cs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ namespace MongoDB.Driver.Core.Connections
3131
/// </summary>
3232
internal sealed class TcpStreamFactory : IStreamFactory
3333
{
34+
private static readonly byte[] __ensureConnectedBuffer = new byte[1];
35+
3436
// fields
3537
private readonly TcpStreamSettings _settings;
3638

@@ -165,10 +167,18 @@ private void ConfigureConnectedSocket(Socket socket)
165167

166168
private void Connect(Socket socket, EndPoint endPoint, CancellationToken cancellationToken)
167169
{
168-
var isSocketDisposed = false;
170+
var callbackState = new ConnectOperationState(socket);
169171
using var timeoutCancellationTokenSource = new CancellationTokenSource(_settings.ConnectTimeout);
170172
using var combinedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCancellationTokenSource.Token);
171-
using var cancellationSubscription = combinedCancellationTokenSource.Token.Register(DisposeSocket);
173+
using var cancellationSubscription = combinedCancellationTokenSource.Token.Register(state =>
174+
{
175+
var operationState = (ConnectOperationState)state;
176+
if (operationState.IsSucceeded)
177+
{
178+
return;
179+
}
180+
DisposeSocket(operationState.Socket);
181+
}, callbackState);
172182

173183
try
174184
{
@@ -185,13 +195,12 @@ private void Connect(Socket socket, EndPoint endPoint, CancellationToken cancell
185195
#else
186196
socket.Connect(endPoint);
187197
#endif
198+
EnsureConnected(socket);
199+
callbackState.IsSucceeded = true;
188200
}
189201
catch
190202
{
191-
if (!isSocketDisposed)
192-
{
193-
DisposeSocket();
194-
}
203+
DisposeSocket(socket);
195204

196205
cancellationToken.ThrowIfCancellationRequested();
197206
if (timeoutCancellationTokenSource.IsCancellationRequested)
@@ -202,9 +211,8 @@ private void Connect(Socket socket, EndPoint endPoint, CancellationToken cancell
202211
throw;
203212
}
204213

205-
void DisposeSocket()
214+
static void DisposeSocket(Socket socket)
206215
{
207-
isSocketDisposed = true;
208216
try
209217
{
210218
socket.Dispose();
@@ -214,6 +222,23 @@ void DisposeSocket()
214222
// Ignore any exceptions.
215223
}
216224
}
225+
226+
static void EnsureConnected(Socket socket)
227+
{
228+
bool originalBlockingState = socket.Blocking;
229+
socket.Blocking = false;
230+
231+
try
232+
{
233+
// Try to use the socket to ensure it's connected. On MacOS with net6.0 sometimes Connect is completed successfully even after the socket disposal.
234+
socket.Send(__ensureConnectedBuffer, 0, 0);
235+
}
236+
finally
237+
{
238+
// Restore original blocking state
239+
socket.Blocking = originalBlockingState;
240+
}
241+
}
217242
}
218243

219244
private async Task ConnectAsync(Socket socket, EndPoint endPoint, CancellationToken cancellationToken)
@@ -376,5 +401,10 @@ public int Compare(EndPoint x, EndPoint y)
376401
return 0;
377402
}
378403
}
404+
405+
private sealed record ConnectOperationState(Socket Socket)
406+
{
407+
public bool IsSucceeded { get; set; }
408+
}
379409
}
380410
}

0 commit comments

Comments
 (0)