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 |
Timelines: | family | ancestors | descendants | both | shared-cache-fixes |
Files: | files | file ages | folders |
SHA1: |
a6f851d0fe01d8c8d44a2fe0b716ff7a |
User & Date: | drh 2013-05-14 23:12:06.185 |
Context
2013-05-14
| ||
23:13 | Merge together the fork in this branch. (check-in: 164e3d4da2 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: a6f851d0fe 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: ea0428f9b6 user: dan tags: shared-cache-fixes) | |
Changes
Changes to src/btree.c.
︙ | ︙ | |||
2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 | page1_init_failed: releasePage(pPage1); pBt->pPage1 = 0; return rc; } /* ** If there are no outstanding cursors and we are not in the middle ** of a transaction but there is a read lock on the database, then ** this routine unrefs the first page of the database file which ** has the effect of releasing the read lock. ** ** If there is a transaction in progress, this routine is a no-op. */ static void unlockBtreeIfUnused(BtShared *pBt){ assert( sqlite3_mutex_held(pBt->mutex) ); | > > > > > > > > > > > > > > > > > > > > > > > | | 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 | page1_init_failed: releasePage(pPage1); pBt->pPage1 = 0; return rc; } #ifndef NDEBUG /* ** Return the number of cursors open on pBt. This is for use ** in assert() expressions, so it is only compiled if NDEBUG is not ** defined. ** ** Only write cursors are counted if wrOnly is true. If wrOnly is ** false then all cursors are counted. ** ** For the purposes of this routine, a cursor is any cursor that ** is capable of reading or writing to the databse. Cursors that ** have been tripped into the CURSOR_FAULT state are not counted. */ static int countValidCursors(BtShared *pBt, int wrOnly){ BtCursor *pCur; int r = 0; for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++; } return r; } #endif /* ** If there are no outstanding cursors and we are not in the middle ** of a transaction but there is a read lock on the database, then ** this routine unrefs the first page of the database file which ** has the effect of releasing the read lock. ** ** If there is a transaction in progress, this routine is a no-op. */ static void unlockBtreeIfUnused(BtShared *pBt){ assert( sqlite3_mutex_held(pBt->mutex) ); assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE ); if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){ assert( pBt->pPage1->aData ); assert( sqlite3PagerRefcount(pBt->pPager)==1 ); assert( pBt->pPage1->aData ); releasePage(pBt->pPage1); pBt->pPage1 = 0; } |
︙ | ︙ | |||
3347 3348 3349 3350 3351 3352 3353 | if( rc==SQLITE_OK ){ rc = sqlite3BtreeCommitPhaseTwo(p, 0); } sqlite3BtreeLeave(p); return rc; } | < < < < < < < < < < < < < < < < < < < < < | 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 | if( rc==SQLITE_OK ){ rc = sqlite3BtreeCommitPhaseTwo(p, 0); } sqlite3BtreeLeave(p); return rc; } /* ** This routine sets the state to CURSOR_FAULT and the error ** code to errCode for every cursor on BtShared that pBtree ** references. ** ** Every cursor is tripped, including cursors that belong ** to other database connections that happen to be sharing |
︙ | ︙ | |||
3447 3448 3449 3450 3451 3452 3453 | int nPage = get4byte(28+(u8*)pPage1->aData); testcase( nPage==0 ); if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); testcase( pBt->nPage!=nPage ); pBt->nPage = nPage; releasePage(pPage1); } | | | 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 | int nPage = get4byte(28+(u8*)pPage1->aData); testcase( nPage==0 ); if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage); testcase( pBt->nPage!=nPage ); pBt->nPage = nPage; releasePage(pPage1); } assert( countValidCursors(pBt, 1)==0 ); pBt->inTransaction = TRANS_READ; } btreeEndTransaction(p); sqlite3BtreeLeave(p); return rc; } |
︙ | ︙ |
Changes to test/misuse.test.
︙ | ︙ | |||
166 167 168 169 170 171 172 | do_test misuse-4.3 { set v [catch { db eval {SELECT * FROM t1} {} { set r [sqlite3_close $::DB] } } msg] lappend v $msg $r | | | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | do_test misuse-4.3 { set v [catch { db eval {SELECT * FROM t1} {} { set r [sqlite3_close $::DB] } } msg] lappend v $msg $r } {1 {callback requested query abort} SQLITE_BUSY} do_test misuse-4.4 { # Flush the TCL statement cache here, otherwise the sqlite3_close() will # fail because there are still un-finalized() VDBEs. db cache flush sqlite3_close $::DB catchsql2 {SELECT * FROM t1} } {1 {library routine called out of sequence}} |
︙ | ︙ |