Changeset 189526 in webkit


Ignore:
Timestamp:
Sep 8, 2015 6:38:32 PM (9 years ago)
Author:
Michael Catanzaro
Message:

Crash when WebCore::SQLiteFileSystem::openDatabase is called from multiple threads
https://bugs.webkit.org/show_bug.cgi?id=143245

Reviewed by Darin Adler.

sqlite3_initialize is documented to be thread-safe, and to be called automatically by the
library when needed, so applications should never need to call it directly. The problem is,
it's not thread-safe: we have documented instances of GNOME Builder, Devhelp, Epiphany, and
cinnamon-screensaver crashing when sqlite3_initialize is called simultaneously in separate
threads (usually inside sqlite3_open). So call it manually, guarded using std::call_once, to
make sure that the library is fully initialized before the first call to sqlite3_open. It's
a good idea to do this regardless, because the documentation says it could be required in
a future release of SQLite. (Though the use of std::call_once should not be needed, and is
only used to attempt to work around the crashes.)

This is a workaround for an SQLite bug that might have been fixed upstream, but the SQLite
developers are not really confident in the thread-safety of this function, and have advised
that we carry the workaround. Seems like a good idea.

  • platform/sql/SQLiteDatabase.cpp:

(WebCore::SQLiteDatabase::SQLiteDatabase):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r189525 r189526  
     12015-09-08  Michael Catanzaro  <mcatanzaro@igalia.com>
     2
     3        Crash when WebCore::SQLiteFileSystem::openDatabase is called from multiple threads
     4        https://bugs.webkit.org/show_bug.cgi?id=143245
     5
     6        Reviewed by Darin Adler.
     7
     8        sqlite3_initialize is documented to be thread-safe, and to be called automatically by the
     9        library when needed, so applications should never need to call it directly. The problem is,
     10        it's not thread-safe: we have documented instances of GNOME Builder, Devhelp, Epiphany, and
     11        cinnamon-screensaver crashing when sqlite3_initialize is called simultaneously in separate
     12        threads (usually inside sqlite3_open). So call it manually, guarded using std::call_once, to
     13        make sure that the library is fully initialized before the first call to sqlite3_open. It's
     14        a good idea to do this regardless, because the documentation says it could be required in
     15        a future release of SQLite. (Though the use of std::call_once should not be needed, and is
     16        only used to attempt to work around the crashes.)
     17
     18        This is a workaround for an SQLite bug that might have been fixed upstream, but the SQLite
     19        developers are not really confident in the thread-safety of this function, and have advised
     20        that we carry the workaround. Seems like a good idea.
     21
     22        * platform/sql/SQLiteDatabase.cpp:
     23        (WebCore::SQLiteDatabase::SQLiteDatabase):
     24
    1252015-09-08  Yusuke Suzuki  <utatane.tea@gmail.com>
    226
  • trunk/Source/WebCore/platform/sql/SQLiteDatabase.cpp

    r188594 r189526  
    3232#include "SQLiteFileSystem.h"
    3333#include "SQLiteStatement.h"
     34#include <mutex>
     35#include <sqlite3.h>
    3436#include <thread>
    3537#include <wtf/Threading.h>
     
    5860    , m_lastChangesCount(0)
    5961{
     62    static std::once_flag flag;
     63    std::call_once(flag, [] {
     64        // It should be safe to call this outside of std::call_once, since it is documented to be
     65        // completely threadsafe. But in the past it was not safe, and the SQLite developers still
     66        // aren't confident that it really is, and we still support ancient versions of SQLite. So
     67        // std::call_once is used to stay on the safe side. See bug #143245.
     68        int ret = sqlite3_initialize();
     69        if (ret != SQLITE_OK) {
     70#if SQLITE_VERSION_NUMBER >= 3007015
     71            WTFLogAlways("Failed to initialize SQLite: %s", sqlite3_errstr(ret));
     72#else
     73            WTFLogAlways("Failed to initialize SQLite");
     74#endif
     75            CRASH();
     76        }
     77    });
    6078}
    6179
Note: See TracChangeset for help on using the changeset viewer.