3

With the release of iOS 5 we are getting more and more errors when setting the serialized option for the sqlite database (so its save to be used for multithreading). We are getting SQLITE_MISUSE error code on sqlite3_config. Has someone noticed this odd behavior? And does someone know how I can fix this? It works perfectly fine on previous iOS versions.

here is the code:

- (sqlite3 *)getNewDBConnection {
    NSLog(@"sqlite3 lib version: %s", sqlite3_libversion());

    //sqlite3_config() has to be called before any sqlite3_open calls.

    if (sqlite3_threadsafe() > 0) {
        int retCode = sqlite3_config(SQLITE_CONFIG_SERIALIZED);
        if (retCode == SQLITE_OK) {
            NSLog(@"Can now use sqlite on multiple threads, using the same connection");
        } else {
            NSLog(@"setting sqlite thread safe mode to serialized failed!!! return code: %d", retCode);
        }
    } else {
        NSLog(@"Your SQLite database is not compiled to be threadsafe.");
    }

    sqlite3 *newDBconnection;

    // Open the database
    if (sqlite3_open([[self getDatabaseFilePath] UTF8String], &newDBconnection) == SQLITE_OK) {
        NSLog(@"Database Successfully Opened :)");
    } else {
        sqlite3_close(newDBconnection);
        NSLog(@"Error in opening database :(");
    }

    return newDBconnection; 
}

and this is the output:

sqlite3 lib version: 3.7.7
setting sqlite thread safe mode to serialized failed!!! return code: 21
Database Successfully Opened :)
Buju
  • 1,546
  • 3
  • 16
  • 27
  • I'm experiencing the same issue, and calling sqlite3_initialize() after sqlite3_config() does not resolve the issue. The call to config() still returns SQLITE_MISUSE (code 21). Anyone was able to figure this out? –  Oct 28 '11 at 20:47

2 Answers2

12

I struggled long and hard with this as well and finally got the solution.

As @enobufs said, sqlite3_config() needs to be called before sqlite3_initialize(). However, the OS might initialize SQLite for us so I also do a sqlite3_shutdown() before the sqlite3_config().

  1. sqlite3_shutdown()
  2. sqlite3_config()
  3. sqlite3_initialize().

Then its also necessary to use the same connection for every query as it is the access to the database connection that gets serialized. As described here http://www.sqlite.org/capi3ref.html#sqliteconfigserialized

So I create a connection as soon as the app starts up and the pass that connection to every class that needs it.

patridge
  • 26,385
  • 18
  • 89
  • 135
naudecruywagen
  • 378
  • 3
  • 8
  • thanks for the tipp. it seems to work now but this needs further testing if it really fixes our problem and it will not have any side effects. – Buju Apr 17 '12 at 18:14
  • @naudec at what point in the application do you call the 3 methods? is it in the `appdeleage.cs`? and what parameters do you pass into `sqlite3_config()` – JKennedy Nov 04 '19 at 15:38
  • Apologies @user1 I don't have access to this codebase anymore and it's too long ago for me to remember – naudecruywagen Nov 13 '19 at 07:36
1

Is the sqlite3_config() called before sqlite3_initialize()? The function returns SQLITE_MISUSE if called after sqlite3_initialize() and before sqlite3_shutdown(). See http://www.sqlite.org/c3ref/config.html for more details.

patridge
  • 26,385
  • 18
  • 89
  • 135
enobufs
  • 860
  • 1
  • 7
  • 12
  • I'm not calling any of these methods. It works fine in previous versions. – Buju Oct 18 '11 at 08:17
  • 1
    I wasn't calling *_initialize()/*_shutdown() functions with earlier versions of ios either and working fine. But multithread operations failed with ios 5. Apparently, sqlite3_initialize() is called automatically if the library is compiled without SQLITE_OMIT_AUTOINIT. To resolve my problem with ios, I explicitly called sqlite3_initialize() after sqlite3_config() before any other sqlite3 function calls. Now my sqlite3_config() returns SQLITE_OK and multithreaded access working properly on ios 5. I agree something has changed with ios5. Good luck! – enobufs Oct 18 '11 at 22:34