Skip to content

Commit

Permalink
SQLite: Don't modify collection while enumerating inside ReclaimLeake…
Browse files Browse the repository at this point in the history
…dConnections

Fixes dotnet#27168
  • Loading branch information
bricelam committed Feb 10, 2022
1 parent 9d51382 commit 2455206
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 8 deletions.
17 changes: 9 additions & 8 deletions src/Microsoft.Data.Sqlite.Core/SqliteConnectionPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;

namespace Microsoft.Data.Sqlite
Expand Down Expand Up @@ -157,17 +158,17 @@ private bool ReclaimLeakedConnections()
{
var leakedConnectionsFound = false;

List<SqliteConnectionInternal> leakedConnections;
lock (_connections)
{
foreach (var connection in _connections)
{
if (connection.Leaked)
{
Return(connection);
leakedConnections = _connections.Where(c => c.Leaked).ToList();
}

leakedConnectionsFound = true;
}
}
foreach (var connection in leakedConnections)
{
leakedConnectionsFound = true;

Return(connection);
}

return leakedConnectionsFound;
Expand Down
21 changes: 21 additions & 0 deletions test/Microsoft.Data.Sqlite.Tests/SqliteConnectionFactoryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Data;
using System.IO;
using System.Runtime.CompilerServices;
using SQLitePCL;
using Xunit;

Expand Down Expand Up @@ -218,6 +219,26 @@ public void EnableExtensions_doesnt_bleed_across_connections()
Assert.Equal(disabledMessage, ex.Message);
}

[Fact]
public void Clear_works_when_connection_leaked()
{
using var connection = new SqliteConnection(ConnectionString);
connection.Open();

LeakConnection();
GC.Collect();

SqliteConnection.ClearPool(connection);

[MethodImpl(MethodImplOptions.NoInlining)]
static void LeakConnection()
{
// Don't add using!
var connection = new SqliteConnection(ConnectionString);
connection.Open();
}
}

public void Dispose()
{
SqliteConnection.ClearAllPools();
Expand Down

0 comments on commit 2455206

Please sign in to comment.