From 84d03851529c9f4164f776b44dfd73b286f9776f Mon Sep 17 00:00:00 2001 From: Franz Reiter Date: Fri, 14 Oct 2022 14:00:51 +0200 Subject: [PATCH] Fixed potential deadlock in FbConnectionPoolManager --- .../FirebirdClient/FbConnectionPoolManager.cs | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/FirebirdSql.Data.FirebirdClient/FirebirdClient/FbConnectionPoolManager.cs b/src/FirebirdSql.Data.FirebirdClient/FirebirdClient/FbConnectionPoolManager.cs index 59924b46..5d156000 100644 --- a/src/FirebirdSql.Data.FirebirdClient/FirebirdClient/FbConnectionPoolManager.cs +++ b/src/FirebirdSql.Data.FirebirdClient/FirebirdClient/FbConnectionPoolManager.cs @@ -65,13 +65,19 @@ public Pool(ConnectionString connectionString) public void Dispose() { + Item[] items; + lock (_syncRoot) { if (_disposed) return; _disposed = true; - CleanConnectionsImpl(); + + items = _available.ToArray(); + _available.Clear(); } + + CleanConnectionsImpl(items); } public FbConnectionInternal GetConnection(out bool createdNew) @@ -103,6 +109,8 @@ public void ReleaseConnection(FbConnectionInternal connection, bool returnToAvai public void PrunePool() { + List release; + lock (_syncRoot) { CheckDisposedImpl(); @@ -117,26 +125,33 @@ public void PrunePool() { keep = keep.Concat(available.Except(keep).OrderByDescending(x => x.Created).Take(_connectionString.MinPoolSize - keepCount)).ToList(); } - var release = available.Except(keep).ToList(); - Parallel.ForEach(release, x => x.Release()); + release = available.Except(keep).ToList(); _available = new Stack(keep); } + + // Call Release() outside the lock to avoid potential deadlocks + Parallel.ForEach(release, x => x.Release()); } public void ClearPool() { + Item[] items; + lock (_syncRoot) { CheckDisposedImpl(); - CleanConnectionsImpl(); + items = _available.ToArray(); _available.Clear(); } + + // Call Release() outside the lock to avoid potential deadlocks + CleanConnectionsImpl(items); } - void CleanConnectionsImpl() + void CleanConnectionsImpl(Item[] items) { - Parallel.ForEach(_available, x => x.Release()); + Parallel.ForEach(items, x => x.Release()); } [MethodImpl(MethodImplOptions.AggressiveInlining)]