sqlite.net + monotouch = SIGSEGV crashes sqlite.net + monotouch = SIGSEGV crashes sqlite sqlite

sqlite.net + monotouch = SIGSEGV crashes


I'm pretty sure I was getting meaningful errors instead of SIGSEGV's when I tried hammering the same sqlite.net connection from multiple threads, but if you believe that that's the culprit, the solution is simple: you need to restrict access to any sqlite.net methods which touch the database to one thread at a time.

In the scenario where you're sharing a single SQLiteConnection instance in your app (which is a perfectly valid way of doing things), I recommend creating a simplified proxy class wrapping your sqlite.net connection, exposing only the methods that you want and protecting access to those with lock statements, i.e:

public class DatabaseWrapper : IDisposable{    // Fields.    private readonly SQLiteConnection Connection;    private readonly object Lock = new object();    public DatabaseWrapper(string databasePath)    {        if (string.IsNullOrEmpty(databasePath)) throw new ArgumentException("Database path cannot be null or empty.");        this.Connection = new SQLiteConnection(databasePath);    }    public IEnumerable<T> Entities<T>() where T : new()    {        lock (this.Lock)        {            return this.Connection.Table<T>();        }    }    public IEnumerable<T> Query<T>(string query, params object[] args) where T : new()    {        lock (this.Lock)        {            return this.Connection.Query<T>(query, args);        }    }    public int ExecuteNonQuery(string sql, params object[] args)    {        lock (this.Lock)        {            return this.Connection.Execute(sql, args);        }    }    public T ExecuteScalar<T>(string sql, params object[] args)    {        lock (this.Lock)        {            return this.Connection.ExecuteScalar<T>(sql, args);        }    }    public void Insert<T>(T entity)    {        lock (this.Lock)        {            this.Connection.Insert(entity);        }    }    public void Update<T>(T entity)    {        lock (this.Lock)        {            this.Connection.Update(entity);        }    }    public void Upsert<T>(T entity)    {        lock (this.Lock)        {            var rowCount = this.Connection.Update(entity);            if (rowCount == 0)            {                this.Connection.Insert(entity);            }        }    }    public void Delete<T>(T entity)    {        lock (this.Lock)        {            this.Connection.Delete(entity);        }    }    public void Dispose()    {        this.Connection.Dispose();    }}

P.S. Obviously since you're doing things on multiple threads you need to be very careful not to introduce race conditions, which is why, for example, I included the Upsert method that is guaranteed to perform the two-step "update or insert" operation atomically.


Try adding the flags: SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex to your SQLite connection constructor. Solved our problem. Looks like SQLite still does some background work after transactions, using the internal mutex ensures the base consistency.