SQLite3.SetDirectory call exposes System.AccessViolationException on Windows 8.1 (WinRT)

In my Windows 8.1 (WinRT) application, I am using SQLite v 3.8.9 with SQLite-net as my database and SemaphoreSlim as my sync tool. It usually works, but sometimes it crashes in SQLite C ++ code when I try to delete a record in a table.

Exception from first chance in (code) in (project name): Microsoft C ++ exception: _com_error in memory location (location).

Delete a record in a table

private static SemaphoreSlim _mutex = new SemaphoreSlim(1,5);
public void DeleteItem(Item item)
{
    _mutex.Wait();
    using (var connection = new SQLiteConnection(Path))
    {
         connection.Delete(item);
    }
    _mutex.Release();
}

      

SQLite.cs

public SQLiteConnection (string databasePath, SQLiteOpenFlags openFlags, bool storeDateTimeAsTicks = false)
{
    ...
#if NETFX_CORE
        SQLite3.SetDirectory(/*temp directory type*/2, Windows.Storage.ApplicationData.Current.TemporaryFolder.Path);
#endif
    ...
}

      

Failure occurs when called SQLite3.SetDirectory

.

An exception:

System.AccessViolationException

Message:

An attempt was made to read or write protected memory. This is often an indication that other memory is damaged.

StackTrace:

at SQLite.SQLite3.SetDirectory (UInt32 directoryType, String directoryPath)

at SQLite.SQLiteConnection..ctor (String databasePath, SQLiteOpenFlags openFlags, Boolean storeDateTimeAsTicks)

at SQLite.SQLiteConnection..ctor (String databasePath, Boolean storeDateTimeAsTicks)

Question

I guess it must be a Threading issue because it usually works and has intermittent crashes; but I can't find anything.

What could be causing the exception and what can I do to fix it?

I don't think this is corrupted memory, possibly protected, but I'm pretty sure that only one of my threads is accessing it.

+3


source to share


1 answer


In the end, even though I was sure that only one thread was accessing the SQLite db at a time, it turned out that I had a little bit of code that I didn't expect to be called at the same time; it causedAccessViolationException

To ensure that this problem does not occur in the future, I did the following:

  • Moved all SQLite code to another project trying to isolate it.
  • Implemented semi-factory pattern in the project to ensure that only one thread is used (this also improved the code)

Factory Database Class

public class DataBaseConnection: SQLite.SQLiteConnection
{
   private const string _path = "MySQlitePath";
   private static SemaphoreSlim _contextMutex = new SemaphoreSlim(1, 5);
   private DataBaseConnection() : base(_path)
   {
   }

   public static DataBaseConnection CreateDataBaseConnection()
   {
       _contextMutex.Wait();
       return new DataBaseConnection();
   }

   private bool disposed = false;
   protected override void Dispose(bool disposing)
   {
       if (disposed)
          return;
       if(disposing)
       {

       }
       disposed = true;
       base.Dispose(disposing);
       _contextMutex.Release();
    }
}

      

Using a factory

using (var connection = DataBaseConnection.CreateDataBaseConnection())
{
     connection.Delete(item);
}

      



Since then I have never seen AccessViolationException

again.


Using multiple DB connections

If you are using multiple connections (i.e. different DB paths), for example:

  • MySQlitePath_1
  • MySQlitePath_2
  • ...
  • MySQlitePath_N

You have to use the same synchronization mechanism (in my case SemaphoreSlim

) to ensure that only one SQLite connection is open at any given time; even if they refer to different files.

+1


source







All Articles