/ Check-in [a6f851d0]
Login

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

Overview
Comment:Fix an assert() in unlockBtreeIfUnused() so that it checks for the existance of an untripped cursor, not for the existance of any cursor at all.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | shared-cache-fixes
Files: files | file ages | folders
SHA1: a6f851d0fe01d8c8d44a2fe0b716ff7a5194c63b
User & Date: drh 2013-05-14 23:12:06
Context
2013-05-14
23:13
Merge together the fork in this branch. check-in: 164e3d4d user: drh tags: shared-cache-fixes
23:12
Fix an assert() in unlockBtreeIfUnused() so that it checks for the existance of an untripped cursor, not for the existance of any cursor at all. check-in: a6f851d0 user: drh tags: shared-cache-fixes
2013-05-13
18:23
Candidate fixes for problems revealed by notify2.test. Notify2.test is still failing at this point. check-in: ea0428f9 user: dan tags: shared-cache-fixes
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  2513   2513   
  2514   2514   page1_init_failed:
  2515   2515     releasePage(pPage1);
  2516   2516     pBt->pPage1 = 0;
  2517   2517     return rc;
  2518   2518   }
  2519   2519   
         2520  +#ifndef NDEBUG
         2521  +/*
         2522  +** Return the number of cursors open on pBt. This is for use
         2523  +** in assert() expressions, so it is only compiled if NDEBUG is not
         2524  +** defined.
         2525  +**
         2526  +** Only write cursors are counted if wrOnly is true.  If wrOnly is
         2527  +** false then all cursors are counted.
         2528  +**
         2529  +** For the purposes of this routine, a cursor is any cursor that
         2530  +** is capable of reading or writing to the databse.  Cursors that
         2531  +** have been tripped into the CURSOR_FAULT state are not counted.
         2532  +*/
         2533  +static int countValidCursors(BtShared *pBt, int wrOnly){
         2534  +  BtCursor *pCur;
         2535  +  int r = 0;
         2536  +  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
         2537  +    if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++; 
         2538  +  }
         2539  +  return r;
         2540  +}
         2541  +#endif
         2542  +
  2520   2543   /*
  2521   2544   ** If there are no outstanding cursors and we are not in the middle
  2522   2545   ** of a transaction but there is a read lock on the database, then
  2523   2546   ** this routine unrefs the first page of the database file which 
  2524   2547   ** has the effect of releasing the read lock.
  2525   2548   **
  2526   2549   ** If there is a transaction in progress, this routine is a no-op.
  2527   2550   */
  2528   2551   static void unlockBtreeIfUnused(BtShared *pBt){
  2529   2552     assert( sqlite3_mutex_held(pBt->mutex) );
  2530         -  assert( pBt->pCursor==0 || pBt->inTransaction>TRANS_NONE );
         2553  +  assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE );
  2531   2554     if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){
  2532   2555       assert( pBt->pPage1->aData );
  2533   2556       assert( sqlite3PagerRefcount(pBt->pPager)==1 );
  2534   2557       assert( pBt->pPage1->aData );
  2535   2558       releasePage(pBt->pPage1);
  2536   2559       pBt->pPage1 = 0;
  2537   2560     }
................................................................................
  3347   3370     if( rc==SQLITE_OK ){
  3348   3371       rc = sqlite3BtreeCommitPhaseTwo(p, 0);
  3349   3372     }
  3350   3373     sqlite3BtreeLeave(p);
  3351   3374     return rc;
  3352   3375   }
  3353   3376   
  3354         -#ifndef NDEBUG
  3355         -/*
  3356         -** Return the number of write-cursors open on this handle. This is for use
  3357         -** in assert() expressions, so it is only compiled if NDEBUG is not
  3358         -** defined.
  3359         -**
  3360         -** For the purposes of this routine, a write-cursor is any cursor that
  3361         -** is capable of writing to the databse.  That means the cursor was
  3362         -** originally opened for writing and the cursor has not be disabled
  3363         -** by having its state changed to CURSOR_FAULT.
  3364         -*/
  3365         -static int countWriteCursors(BtShared *pBt){
  3366         -  BtCursor *pCur;
  3367         -  int r = 0;
  3368         -  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
  3369         -    if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++; 
  3370         -  }
  3371         -  return r;
  3372         -}
  3373         -#endif
  3374         -
  3375   3377   /*
  3376   3378   ** This routine sets the state to CURSOR_FAULT and the error
  3377   3379   ** code to errCode for every cursor on BtShared that pBtree
  3378   3380   ** references.
  3379   3381   **
  3380   3382   ** Every cursor is tripped, including cursors that belong
  3381   3383   ** to other database connections that happen to be sharing
................................................................................
  3447   3449         int nPage = get4byte(28+(u8*)pPage1->aData);
  3448   3450         testcase( nPage==0 );
  3449   3451         if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
  3450   3452         testcase( pBt->nPage!=nPage );
  3451   3453         pBt->nPage = nPage;
  3452   3454         releasePage(pPage1);
  3453   3455       }
  3454         -    assert( countWriteCursors(pBt)==0 );
         3456  +    assert( countValidCursors(pBt, 1)==0 );
  3455   3457       pBt->inTransaction = TRANS_READ;
  3456   3458     }
  3457   3459   
  3458   3460     btreeEndTransaction(p);
  3459   3461     sqlite3BtreeLeave(p);
  3460   3462     return rc;
  3461   3463   }

Changes to test/misuse.test.

   166    166   do_test misuse-4.3 {
   167    167     set v [catch {
   168    168       db eval {SELECT * FROM t1} {} {
   169    169         set r [sqlite3_close $::DB]
   170    170       }
   171    171     } msg]
   172    172     lappend v $msg $r
   173         -} {0 {} SQLITE_BUSY}
          173  +} {1 {callback requested query abort} SQLITE_BUSY}
   174    174   do_test misuse-4.4 {
   175    175     # Flush the TCL statement cache here, otherwise the sqlite3_close() will
   176    176     # fail because there are still un-finalized() VDBEs.
   177    177     db cache flush
   178    178     sqlite3_close $::DB
   179    179     catchsql2 {SELECT * FROM t1}
   180    180   } {1 {library routine called out of sequence}}