views:

225

answers:

2

Is the sqlite3 Ruby gem thread safe? I can't find any documentation to say that it is.

In my experiments, accessing a database from multiple Ruby threads eventually leads to the following error:

/Library/Ruby/Gems/1.8/gems/sqlite3-ruby-1.2.5/lib/sqlite3/driver/native/driver.rb:84: [BUG] Bus Error

Is there anything I'm missing? If not, is there another package I can use that is thread safe?

Edit: using SQLite3.4 on Mac OS 10.5.

+1  A: 

It's most likely dependent on the sqlite3 library you're using. It can be compiled with thread safety on or off. The sqlite3_threadsafe() function will tell you, although I suspect that API is not exposed in the Ruby bindings.

The following C program would test it for you

#include <sqlite3.h>

int main()
{
    printf("Threadsafe: %d\n", sqlite3_threadsafe());
}

Compile it with

gcc -o test test.c -lsqlite3

If it prints a non-zero number, then it should be threadsafe.

Rudedog
Thanks for that, I didn't think of testing the c lib directly.
Justicle
Hmm interesting the source compiles, but doesn't link to that function (although gcc does find the library). I smell library install shenanigans.
Justicle
A: 

After some investigation, I found that the issue has nothing to do with sqlite3.

In the function that is performing the threaded access to the DB, an exception is occurring. As Thread.abort_on_exception defaults to false, the exception is masked, but manifests as a bus error (see above) as soon as the DL function is evoked by driver.rb

Fixing the exception (a silly string/integer comparison) results in expected working behaviour - and using the test above did indicate that the sqlite lib was built with -DTHREADSAFE=1

Note I still have mutexes around the SQL queries as recommended by documents (see http://www.sqlite.org/cvstrac/wiki?p=MultiThreading ), but this may not be necessary with Ruby 1.8's "green" threads.

Justicle