/ Check-in [c041c6a9]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Clarify the purpose of a test for a race-condition in sqlite3WalBeginReadTransaction().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c041c6a9786bc9ebb82527f7a2c96d255aec927f
User & Date: dan 2010-06-05 18:34:26
Original Comment: Clarify the purpose of a test for a race-condition in walIndexReadHdr().
Context
2010-06-05
19:18
Add further test cases for the logic in sqlite3WalBeginReadTransaction(). check-in: a49713db user: dan tags: trunk
18:34
Clarify the purpose of a test for a race-condition in sqlite3WalBeginReadTransaction(). check-in: c041c6a9 user: dan tags: trunk
18:12
Remove a condition from sqlite3WalRead() that is unreachable as of the changes to clear entries out of the wal-index hash tables on transaction or savepoint rollback. check-in: 39420473 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/wal.c.

  1741   1741     pInfo = (volatile WalCkptInfo*)&pHdr[2];
  1742   1742     assert( pInfo==walCkptInfo(pWal) );
  1743   1743     if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){
  1744   1744       /* The WAL has been completely backfilled (or it is empty).
  1745   1745       ** and can be safely ignored.
  1746   1746       */
  1747   1747       rc = walLockShared(pWal, WAL_READ_LOCK(0));
         1748  +    sqlite3OsShmBarrier(pWal->pDbFd);
  1748   1749       if( rc==SQLITE_OK ){
  1749   1750         if( memcmp(pHdr, &pWal->hdr, sizeof(WalIndexHdr)) ){
  1750   1751           /* It is not safe to allow the reader to continue here if frames
  1751   1752           ** may have been appended to the log before READ_LOCK(0) was obtained.
  1752   1753           ** When holding READ_LOCK(0), the reader ignores the entire log file,
  1753   1754           ** which implies that the database file contains a trustworthy
  1754   1755           ** snapshoT. Since holding READ_LOCK(0) prevents a checkpoint from
................................................................................
  1813   1814         }
  1814   1815       }
  1815   1816   
  1816   1817       rc = walLockShared(pWal, WAL_READ_LOCK(mxI));
  1817   1818       if( rc ){
  1818   1819         return rc==SQLITE_BUSY ? WAL_RETRY : rc;
  1819   1820       }
         1821  +    /* Now that the read-lock has been obtained, check that neither the
         1822  +    ** value in the aReadMark[] array or the contents of the wal-index
         1823  +    ** header have changed.
         1824  +    **
         1825  +    ** It is necessary to check that the wal-index header did not change
         1826  +    ** between the time it was read and when the shared-lock was obtained
         1827  +    ** on WAL_READ_LOCK(mxI) was obtained to account for the possibility
         1828  +    ** that the log file may have been wrapped by a writer, or that frames
         1829  +    ** that occur later in the log than pWal->hdr.mxFrame may have been
         1830  +    ** copied into the database by a checkpointer. If either of these things
         1831  +    ** happened, then reading the database with the current value of
         1832  +    ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
         1833  +    ** instead.
         1834  +    **
         1835  +    ** This does not guarantee that the copy wal-index header is up to
         1836  +    ** date before proceeding. This would not be possible without somehow
         1837  +    ** blocking writers. It only guarantees that a damaging checkpoint or 
         1838  +    ** log-wrap (either of which would require an exclusive lock on
         1839  +    ** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid.
         1840  +    */
         1841  +    sqlite3OsShmBarrier(pWal->pDbFd);
  1820   1842       if( pInfo->aReadMark[mxI]!=mxReadMark
  1821         -     || pHdr[0].mxFrame!=pWal->hdr.mxFrame
  1822         -     || (sqlite3OsShmBarrier(pWal->pDbFd), pHdr[1].mxFrame!=pWal->hdr.mxFrame)
         1843  +     || memcmp(pHdr, &pWal->hdr, sizeof(WalIndexHdr))
  1823   1844       ){
  1824   1845         walUnlockShared(pWal, WAL_READ_LOCK(mxI));
  1825   1846         return WAL_RETRY;
  1826   1847       }else{
  1827   1848         pWal->readLock = mxI;
  1828   1849       }
  1829   1850     }