/ Check-in [7c102c7b]
Login

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

Overview
Comment:Fix for race condition in WAL locking code.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | mistake
Files: files | file ages | folders
SHA1: 7c102c7b5f90717f55d95e3d38f33684118784d6
User & Date: dan 2010-06-09 11:02:13
References
2010-06-09
11:28
Simpler fix for the race condition also fixed by [7c102c7b5f] check-in: 3c2de820 user: dan tags: trunk
Context
2010-06-09
11:02
Fix for race condition in WAL locking code. Closed-Leaf check-in: 7c102c7b user: dan tags: mistake
2010-06-08
15:50
Close database opened by tester.tcl when it is sourced in all.test. Because test scripts are now run in slave interpreters, this connection was not being closed by the first script run as it was previously. check-in: b072e9f6 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/wal.c.

  1788   1788     if( mxI==0 ){
  1789   1789       /* If we get here, it means that all of the aReadMark[] entries between
  1790   1790       ** 1 and WAL_NREADER-1 are zero.  Try to initialize aReadMark[1] to
  1791   1791       ** be mxFrame, then retry.
  1792   1792       */
  1793   1793       rc = walLockExclusive(pWal, WAL_READ_LOCK(1), 1);
  1794   1794       if( rc==SQLITE_OK ){
  1795         -      pInfo->aReadMark[1] = pWal->hdr.mxFrame+1;
         1795  +      sqlite3OsShmBarrier(pWal->pDbFd);
         1796  +      if( 0==memcmp((void *)pHdr, &pWal->hdr, sizeof(WalIndexHdr)) ){
         1797  +        pInfo->aReadMark[1] = pWal->hdr.mxFrame+1;
         1798  +      }
  1796   1799         walUnlockExclusive(pWal, WAL_READ_LOCK(1), 1);
  1797   1800         rc = WAL_RETRY;
  1798   1801       }else if( rc==SQLITE_BUSY ){
  1799   1802         rc = WAL_RETRY;
  1800   1803       }
  1801   1804       return rc;
  1802   1805     }else{
  1803         -    if( mxReadMark < pWal->hdr.mxFrame ){
         1806  +    if( mxReadMark<=pWal->hdr.mxFrame ){
  1804   1807         for(i=1; i<WAL_NREADER; i++){
  1805   1808           rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
  1806   1809           if( rc==SQLITE_OK ){
  1807         -          mxReadMark = pInfo->aReadMark[i] = pWal->hdr.mxFrame+1;
  1808         -          mxI = i;
         1810  +          sqlite3OsShmBarrier(pWal->pDbFd);
         1811  +          if( 0==memcmp((void *)pHdr, &pWal->hdr, sizeof(WalIndexHdr)) ){
         1812  +            mxReadMark = pInfo->aReadMark[i] = pWal->hdr.mxFrame+1;
         1813  +            mxI = i;
         1814  +          }
  1809   1815             walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
  1810   1816             break;
  1811   1817           }else if( rc!=SQLITE_BUSY ){
  1812   1818             return rc;
  1813   1819           }
  1814   1820         }
  1815   1821       }
................................................................................
  1841   1847       sqlite3OsShmBarrier(pWal->pDbFd);
  1842   1848       if( pInfo->aReadMark[mxI]!=mxReadMark
  1843   1849        || memcmp((void *)pHdr, &pWal->hdr, sizeof(WalIndexHdr))
  1844   1850       ){
  1845   1851         walUnlockShared(pWal, WAL_READ_LOCK(mxI));
  1846   1852         return WAL_RETRY;
  1847   1853       }else{
         1854  +      assert( mxReadMark<=(pWal->hdr.mxFrame+1) );
  1848   1855         pWal->readLock = mxI;
  1849   1856       }
  1850   1857     }
  1851   1858     return rc;
  1852   1859   }
  1853   1860   
  1854   1861   /*

Changes to test/wal2.test.

    49     49     set ints [set_tvfs_hdr $file]
    50     50     set v [lindex $ints $idx]
    51     51     incr v $incrval
    52     52     lset ints $idx $v
    53     53     set_tvfs_hdr $file $ints
    54     54   }
    55     55   
           56  +proc clear_tvfs_readmarks {file} {
           57  +
           58  +  set blob [tvfs shm $file]
           59  +  binary scan $blob i21 ints
           60  +  lappend ints 0 0 0 0 0 
           61  +
           62  +  binary scan $blob a104a* dummy tail
           63  +  set blob [binary format i26a* $ints $tail]
           64  +  tvfs shm $file $blob
           65  +
           66  +}
           67  +
    56     68   
    57     69   #-------------------------------------------------------------------------
    58     70   # Test case wal2-1.*:
    59     71   #
    60     72   # Set up a small database containing a single table. The database is not
    61     73   # checkpointed during the test - all content resides in the log file.
    62     74   #
................................................................................
   163    175   # After this, the header is corrupted again and the reader is allowed
   164    176   # to run recovery. This time, it sees an up-to-date snapshot of the
   165    177   # database file.
   166    178   #
   167    179   set WRITER [list 0 1 lock exclusive]
   168    180   set LOCKS  [list \
   169    181     {0 1 lock exclusive} {0 1 unlock exclusive} \
          182  +  {4 1 lock exclusive} {4 1 unlock exclusive} \
   170    183     {4 1 lock shared}    {4 1 unlock shared}    \
   171    184   ]
   172    185   do_test wal2-2.0 {
   173    186   
   174    187     testvfs tvfs
   175    188     tvfs script tvfs_cb
   176    189     proc tvfs_cb {method args} {
................................................................................
   224    237           }
   225    238         }
   226    239         if {$method == "xShmLock"} {
   227    240           set lock [lindex $args 2]
   228    241           lappend ::locks $lock
   229    242           if {$lock == $::WRITER} {
   230    243             set_tvfs_hdr $::shm_file $::oldhdr
          244  +          clear_tvfs_readmarks $::shm_file
   231    245           }
   232    246         }
   233    247         return SQLITE_OK
   234    248       }
   235    249   
   236    250       execsql { SELECT count(a), sum(a) FROM t1 } db2
   237    251     } $res0
................................................................................
   889    903     5  $wih(2)                $wih(1)                {Barton Deakin Watson}   \
   890    904     6  $wih(2)                $wih(2)                {Barton Deakin Watson}   \
   891    905     7  $wih(1)                $wih(1)                {Barton Deakin}          \
   892    906     8  {0 0 0 0 0 0 0 0 0 0} {0 0 0 0 0 0 0 0 0 0}   {Barton Deakin Watson}   \
   893    907   ] {
   894    908     do_test wal2-9.$tn {
   895    909       set_tvfs_hdr $::filename $hdr1 $hdr2
          910  +    clear_tvfs_readmarks $::shm_file
   896    911       execsql { SELECT * FROM x } db2
   897    912     } $res
   898    913   }
   899    914   
   900    915   db2 close
   901    916   db close
   902    917   
   903    918   finish_test