mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-07 19:57:07 +02:00
Fix for Crash due to System.AccessViolationException when calling OleDBSearch from multiple threads. (#6052)
* Removing non thread safe member variables, as well as the check to ensure that they have been disposed. * Removing 'ExecuteQuery_ShouldDisposeAllConnections_AfterFunctionCall'. This call previously required the use of member variables that were not thread safe. There is no reason to share this state across threads. Arguably this test verifies an internal implementation detail and is not suitable for a unit test anyway.
This commit is contained in:
committed by
GitHub
parent
64106cba82
commit
2390368d03
@@ -8,13 +8,8 @@ using System.Data.OleDb;
|
||||
|
||||
namespace Microsoft.Plugin.Indexer.SearchHelper
|
||||
{
|
||||
public class OleDBSearch : ISearch, IDisposable
|
||||
public class OleDBSearch : ISearch
|
||||
{
|
||||
private OleDbCommand command;
|
||||
private OleDbConnection conn;
|
||||
private OleDbDataReader wDSResults;
|
||||
private bool disposedValue;
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage(
|
||||
"Security",
|
||||
"CA2100:Review SQL queries for security vulnerabilities",
|
||||
@@ -22,101 +17,34 @@ namespace Microsoft.Plugin.Indexer.SearchHelper
|
||||
public List<OleDBResult> Query(string connectionString, string sqlQuery)
|
||||
{
|
||||
List<OleDBResult> result = new List<OleDBResult>();
|
||||
|
||||
using (conn = new OleDbConnection(connectionString))
|
||||
using (var conn = new OleDbConnection(connectionString))
|
||||
{
|
||||
// open the connection
|
||||
conn.Open();
|
||||
|
||||
try
|
||||
// now create an OleDB command object with the query we built above and the connection we just opened.
|
||||
using (var command = new OleDbCommand(sqlQuery, conn))
|
||||
{
|
||||
// now create an OleDB command object with the query we built above and the connection we just opened.
|
||||
using (command = new OleDbCommand(sqlQuery, conn))
|
||||
using (var wDSResults = command.ExecuteReader())
|
||||
{
|
||||
using (wDSResults = command.ExecuteReader())
|
||||
if (!wDSResults.IsClosed && wDSResults.HasRows)
|
||||
{
|
||||
if (!wDSResults.IsClosed && wDSResults.HasRows)
|
||||
while (wDSResults.IsClosed && wDSResults.Read())
|
||||
{
|
||||
while (!wDSResults.IsClosed && wDSResults.Read())
|
||||
List<object> fieldData = new List<object>(wDSResults.FieldCount);
|
||||
for (int i = 0; i < wDSResults.FieldCount; i++)
|
||||
{
|
||||
List<object> fieldData = new List<object>(wDSResults.FieldCount);
|
||||
for (int i = 0; i < wDSResults.FieldCount; i++)
|
||||
{
|
||||
fieldData.Add(wDSResults.GetValue(i));
|
||||
}
|
||||
|
||||
result.Add(new OleDBResult(fieldData));
|
||||
fieldData.Add(wDSResults.GetValue(i));
|
||||
}
|
||||
|
||||
result.Add(new OleDBResult(fieldData));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AccessViolationException can occur if another query is made before the current query completes. Since the old query would be cancelled we can ignore the exception
|
||||
catch (System.AccessViolationException)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Checks if all the variables related to database connection have been properly disposed
|
||||
public bool HaveAllDisposableItemsBeenDisposed()
|
||||
{
|
||||
bool commandDisposed = false;
|
||||
bool connDisposed = false;
|
||||
bool resultDisposed = false;
|
||||
|
||||
try
|
||||
{
|
||||
command.ExecuteReader();
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
commandDisposed = true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
wDSResults.Read();
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
resultDisposed = true;
|
||||
}
|
||||
|
||||
if (conn.State == System.Data.ConnectionState.Closed)
|
||||
{
|
||||
connDisposed = true;
|
||||
}
|
||||
|
||||
return commandDisposed && resultDisposed && connDisposed;
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
command?.Dispose();
|
||||
conn?.Dispose();
|
||||
wDSResults?.Dispose();
|
||||
}
|
||||
|
||||
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
|
||||
// TODO: set large fields to null
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user