I have been trying to track down a crasher in my multi-threaded sqlite 3.2.0 application. I was seeing crashes in highly contentious situations where many threads are opening and closing a database frequently. The crash was consistently in the following bit of code:

src/main.c in sqlite_close starting on line 527

#ifndef SQLITE_OMIT_GLOBALRECOVER
  {
    sqlite3 *pPrev = pDbList;
    sqlite3OsEnterMutex();
    while( pPrev && pPrev->pNext!=db ){
      pPrev = pPrev->pNext;
    }
    if( pPrev ){
      pPrev->pNext = db->pNext;
    }else{
      assert( pDbList==db );
      pDbList = db->pNext;
    }
    sqlite3OsLeaveMutex();
  }
#endif

The problem is that pPrev can be left dangling since the pDbList pointer is saved off before entering the mutex. It is possible that another thread already in the mutex at that time ends up sqliteFree'ing what was the pDbList head, invalidating pPrev for the other thread, causing the crash.

Swapping these two lines fixes the problem:
    sqlite3 *pPrev = pDbList;
    sqlite3OsEnterMutex();

change to:
    sqlite3OsEnterMutex();
    sqlite3 *pPrev = pDbList;

Once I made this change, the crash vanished.
I just looked in the 3.2.1 source and this bit of code is the same.

-Kyle



Reply via email to