Sqlite.net + monotouch = SIGSEGV crashes

We use the following:

  • Xamarin 3 (Xamarin forms)
  • Monoouch
  • sqlite.net
  • iOS simulator / hardware

The application synchronizes data with the server in the background thread. There is only one SQLite connection object for the entire application. Foreground requests are executed simultaneously with background synchronization. All this works fine in the version of the Windows 8.1 application (i.e., on the surface of MSFT, etc.). However, as soon as we switched to Xamarin / mono, we started to get constant crashes, as shown below.

Research led to this article: http://www.aaronheise.com/2012/12/monotouch-sqlite-sigsegv/

It uses the use of Mono.Data.SqliteClient, not sqlite.net, like us.

Its solution includes explicit disposition of Command objects to ensure that the GC can keep up, etc. When I tried to wrap Command objects (from sqlite.net) in a using () {} expression, I found that they were not disposable.

I tried inserting delays of 100 ms and stopping crashes, however this is not a viable solution for us.

Is there any hope for sqlite.net here, or should I look for another way to use sqlite?

    mono-rt: Stacktrace:


mono-rt:   at <unknown> <0xffffffff>

mono-rt:   at (wrapper managed-to-native) SQLite.SQLite3.Prepare2 (intptr,string,int,intptr&,intptr) <IL 0x0003c, 0xffffffff>

...

mono-rt: 
Native stacktrace:


mono-rt: 
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
+4
source share
3 answers

, SIGSEGV, sqlite.net , , , : sqlite.net, .

, SQLiteConnection ( ), -, sqlite.net, lock, ..:

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. , , , , , , , Upsert, " ", .

+4

: SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex SQLite. . , SQLite - , , .

0

- iOS, .

Xamarin Forms, Android, iOS. , iOS bundle_green ( Microsoft.data.sqlite) sqlite, iOS, () .

Android bundle_green sqlite Android, Android N . .

ThreadingMode,

var result = SQLitePCL.raw.sqlite3_threadsafe();

string description = "";

switch (result)
{
    case 1:
        // Thread-safe. Lock statements not required.
        description = "Serialized";
        break;
    case 2:
        // Mutexing code is there, but mutexing on database connection and prepared statement objects is disabled.
        // Application is responsible for serializing access to database connections and prepared statements, so must use lock statements.
        description = "Multi-Threaded";
        break;
    default:
        // SQLite was compiled with mutexing code omitted. It is not safe to use SQLite concurrently from more than one thread.
        description = "Mutexing code omitted";
        break;
}

Console.log(description);

, AppDelegate.cs, -

SQLitePCL.Batteries_V2.Init();
raw.sqlite3_shutdown();
raw.sqlite3_config(SQLitePCL.raw.SQLITE_CONFIG_SERIALIZED);
raw.sqlite3_initialize();

What this does is set ThreadMode to Serialized at runtime, and you should stop getting a SIGSEGV error.

0
source

Source: https://habr.com/ru/post/1546314/


All Articles