/ Check-in [71a799b0]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a race condition in OP_ParseSchema.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:71a799b02a3b3cf2e12758dea29fd2465bbec3e1
User & Date: dan 2011-04-02 09:44:43
Context
2011-04-02
17:00
Avoid returning SQLITE_NOTFOUND when the unix xSetSystemCall interface is invoked with NULL passed as the second argument, even if all the default system calls are already installed. check-in: 3b91eaaa user: dan tags: trunk
16:28
Begin a series of changes designed to reduce the scope and frequency of invalidating schemas. Design goals are that the internal schema should never be deleted out from under a prepared statement that is running and that all prepared statements should be expired if the schema is invalidated. At the same time, minimize the number of schema invalidations. This change merely revises the sqlite3ResetInternalSchema() function to use -1 as the wildcard for "all" rather than 0, so that we can reset the main schema independently of all the others. check-in: 6a8ad6e3 user: drh tags: schema-parse-refactor
09:44
Fix a race condition in OP_ParseSchema. check-in: 71a799b0 user: dan tags: trunk
09:25
Do not attempt to run tests that use the 'wholenumber' virtual table if the build does not support virtual tables. check-in: 20afd81a user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640






4641
4642

4643
4644
4645
4646
4647
4648
4649
4650
4651
  const char *zMaster;
  char *zSql;
  InitData initData;

  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );

  /* Although the mutex on the BtShared object that corresponds to
  ** database iDb (the database containing the sqlite_master table
  ** read by this instruction) is currently held, it is necessary to
  ** obtain the mutexes on all attached databases before checking if
  ** the schema of iDb is loaded. This is because, at the start of
  ** the sqlite3_exec() call below, SQLite will invoke 
  ** sqlite3BtreeEnterAll(). If all mutexes are not already held, the
  ** iDb mutex may be temporarily released to avoid deadlock. If 
  ** this happens, then some other thread may delete the in-memory 
  ** schema of database iDb before the SQL statement runs. The schema
  ** will not be reloaded becuase the db->init.busy flag is set. This
  ** can result in a "no such table: sqlite_master" or "malformed
  ** database schema" error being returned to the user.






  */
  assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );

  sqlite3BtreeEnterAll(db);
  if( ALWAYS(DbHasProperty(db, iDb, DB_SchemaLoaded)) ){
    zMaster = SCHEMA_TABLE(iDb);
    initData.db = db;
    initData.iDb = pOp->p1;
    initData.pzErrMsg = &p->zErrMsg;
    zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[iDb].zName, zMaster, pOp->p4.z);







|
|
<
<
<
|
|
|
|
|
|
<
|
>
>
>
>
>
>


>

|







4621
4622
4623
4624
4625
4626
4627
4628
4629



4630
4631
4632
4633
4634
4635

4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
  const char *zMaster;
  char *zSql;
  InitData initData;

  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );

  /* When this opcode is invoked, it is guaranteed that the b-tree mutex
  ** is held and the schema is loaded for database iDb. However, at the 



  ** start of the sqlite3_exec() call below, SQLite will invoke 
  ** sqlite3BtreeEnterAll(). If all mutexes are not already held, the iDb 
  ** mutex may be temporarily released to avoid deadlock. If this happens, 
  ** then some other thread may delete the in-memory schema of database iDb 
  ** before the SQL statement runs. The schema will not be reloaded because 
  ** the db->init.busy flag is set. This can result in a "no such table: 

  ** sqlite_master" or "malformed database schema" error being returned to 
  ** the user. 
  **
  ** To avoid this, obtain all mutexes and check that no other thread has
  ** deleted the schema before calling sqlite3_exec(). If we find that the
  ** another thread has deleted the schema, there is no need to update it.
  ** The updated schema will be loaded from disk when it is next required.
  */
  assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
  sqlite3BtreeEnterAll(db);
  if( DbHasProperty(db, iDb, DB_SchemaLoaded) ){
    zMaster = SCHEMA_TABLE(iDb);
    initData.db = db;
    initData.iDb = pOp->p1;
    initData.pzErrMsg = &p->zErrMsg;
    zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[iDb].zName, zMaster, pOp->p4.z);