Skip to content

Commit 2a324d4

Browse files
committed
Avoid race condition. Fixes #1263
1 parent 0141d9b commit 2a324d4

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

src/MySqlConnector/Core/ConnectionPool.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,22 +246,35 @@ public void Dispose()
246246
/// </summary>
247247
private async Task RecoverLeakedSessionsAsync(IOBehavior ioBehavior)
248248
{
249-
var recoveredSessions = new List<ServerSession>();
249+
var recoveredSessions = new List<(ServerSession Session, MySqlConnection Connection)>();
250250
lock (m_leasedSessions)
251251
{
252252
m_lastRecoveryTime = unchecked((uint) Environment.TickCount);
253253
foreach (var session in m_leasedSessions.Values)
254254
{
255255
if (!session.OwningConnection!.TryGetTarget(out var _))
256-
recoveredSessions.Add(session);
256+
{
257+
// create a dummy MySqlConnection so that any thread running RecoverLeakedSessionsAsync doesn't process this one
258+
var connection = new MySqlConnection();
259+
session.OwningConnection = new(connection);
260+
recoveredSessions.Add((session, connection));
261+
}
257262
}
258263
}
259264
if (recoveredSessions.Count == 0)
260265
Log.Trace("Pool{0} recovered no sessions", m_logArguments);
261266
else
262267
Log.Warn("Pool{0}: RecoveredSessionCount={1}", m_logArguments[0], recoveredSessions.Count);
263-
foreach (var session in recoveredSessions)
268+
269+
foreach (var (session, connection) in recoveredSessions)
270+
{
271+
// bypass MySqlConnection.Dispose(Async), because it's a dummy MySqlConnection that's not set up
272+
// properly, and simply return the session to the pool directly
264273
await session.ReturnToPoolAsync(ioBehavior, null).ConfigureAwait(false);
274+
275+
// be explicit about keeping the associated MySqlConnection alive until the session has been returned
276+
GC.KeepAlive(connection);
277+
}
265278
}
266279

267280
private async Task CleanPoolAsync(IOBehavior ioBehavior, Func<ServerSession, bool> shouldCleanFn, bool respectMinPoolSize, CancellationToken cancellationToken)

0 commit comments

Comments
 (0)