Mapbox-gl-native: [Qt] "database is locked" when opening the same db in different threads

Created on 25 May 2017  路  10Comments  路  Source: mapbox/mapbox-gl-native

Got this on CircleCI with parallel execution:

[ RUN      ] OfflineDatabase.ConcurrentUse
[WARNING] {memcheck-amd64-}[Database]: Removing existing incompatible offline database
terminate called after throwing an instance of 'mapbox::sqlite::Exception'
  what():  database is locked Unable to fetch row
Qt bug offline

All 10 comments

/cc @tmpsantos

We are not sharing the DefaultFileSource on Qt. We should do that by default, unless the user defines a path for the cache that is different from the default path, otherwise it would break the QtLocation plugin API.

That test is wrong, not sure how it is working to be honest. The sqlite API is not thread safe unless we use SQLITE_OPEN_FULLMUTEX which we should not use.

The test is correct. We need sqlite in at least "multi-thread" mode, where multiple threads with independent connections are safe; that's what the test is testing.

If the current Qt setup is operating in "single-thread" mode, then that needs to be fixed.

We do not depend on "serialized" mode, but there's no harm if the sqlite implementation is in that mode.

https://sqlite.org/threadsafe.html

The log message "Removing existing incompatible offline database" (OfflineDatabase::removeExisting()) may be the key here. I don't think that should be happening with this test.

@jfirebaugh thanks a lot for the new insight on this issue. I'm suspecting that QSqlDatabase can only do single-thread to keep compatibility across multiple platforms it supports. I will investigate the Qt source code further to reach a more solid conclusion.

Qt Sqlite plugin for QSqlDatabase does not allow setting e.g. SQLITE_OPEN_FULLMUTEX when opening the connection: https://doc.qt.io/qt-5/qsqldatabase.html#setConnectOptions

I think I finally found the issue. The busy timeout we set in mapboxgl is overflowing in Qt (signed -> unsigned) and for some reason Qt silently ignores the error, leaving the default timeout that is very low.

Was this page helpful?
0 / 5 - 0 ratings