]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When trying to read the index header, accept either of the two headers that more-aggressive-wal-recovery
authordrh <drh@noemail.net>
Sat, 25 Jul 2020 20:16:35 +0000 (20:16 +0000)
committerdrh <drh@noemail.net>
Sat, 25 Jul 2020 20:16:35 +0000 (20:16 +0000)
have a valid checksum after 15 attempts to get exactly matching headers
fail.

FossilOrigin-Name: 3549faefea1bbfba9e1df3e979b648ceff21c830877354afb0bfde24137267a0

manifest
manifest.uuid
src/wal.c

index 80b02e2e4b1d2a586d3e5a52ef4348694e43bbc3..ea4e27a6629082f3495693fb3b044344ccf31931 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Remove\sa\ssurplus\sspace\sfrom\sa\scomment
-D 2020-07-24T11:01:29.118
+C When\strying\sto\sread\sthe\sindex\sheader,\saccept\seither\sof\sthe\stwo\sheaders\sthat\nhave\sa\svalid\schecksum\safter\s15\sattempts\sto\sget\sexactly\smatching\sheaders\nfail.
+D 2020-07-25T20:16:35.579
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -619,7 +619,7 @@ F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143
 F src/vdbevtab.c ee5b4c902fdda2230f9503ac7b84c6d614c91e8f6f4dc1633e2e8dfef8ffb144
 F src/vtab.c 5f5fc793092f53bbdfde296c50f563fb7bda58cf48e9cf6a8bdfbc5abd409845
 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c 231044ecf7d5d78bc705af9dcec6c10ec59e891366362b6be54bb6a0bc7c17db
+F src/wal.c 701b03c19b721d67f2b9e2e091716a450abeec3eb7ab9d09e2ff3dc8bd6db6ed
 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
 F src/walker.c 3df26a33dc4f54e8771600fb7fdebe1ece0896c2ad68c30ab40b017aa4395049
 F src/where.c 2ea911238674e9baaeddf105dddabed92692a01996073c4d4983f9a7efe481f9
@@ -1878,7 +1878,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 270ac1a0f232d75537be40abae559004e950b992cb2c7e94cd6de66e96ae17bd
-R 0212ebf857b7a36fab6e1708725a20d6
+P 73fecc688ab5c459245c9bb89432139a083ef378404b4dae3397a7f4e253f72a
+R 8b78d8957ed058ded3a7dbd973cc6886
+T *branch * more-aggressive-wal-recovery
+T *sym-more-aggressive-wal-recovery *
+T -sym-trunk *
 U drh
-Z 7c8911d20a18c22808c4eb3363f6ff12
+Z 3aeeeda48c6b870c6fcde25fed7c5eb2
index ef6483f2d60cc1f1587b013bc23ec10d9e47eb1b..1c0fdc3f034bc3e0dd93a027826a50b039dfd57a 100644 (file)
@@ -1 +1 @@
-73fecc688ab5c459245c9bb89432139a083ef378404b4dae3397a7f4e253f72a
\ No newline at end of file
+3549faefea1bbfba9e1df3e979b648ceff21c830877354afb0bfde24137267a0
\ No newline at end of file
index c6d4476e7b3b5d65765a816060139b69bd5e4b5c..b2ff475b41b237021ce99b980a94bbc6671804d7 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -2137,6 +2137,19 @@ int sqlite3WalClose(
   return rc;
 }
 
+/*
+** Return true if the wal-index header seems valid based on the
+** checksum.
+*/
+static int walIndexHdrValid(WalIndexHdr *p){
+  u32 aCksum[2];
+  if( p->isInit==0 ) return 0;
+  walChecksumBytes(1, (u8*)p, sizeof(*p)-sizeof(p->aCksum), 0, aCksum);
+  if( aCksum[0]!=p->aCksum[0] ) return 0;
+  if( aCksum[1]!=p->aCksum[1] ) return 0;
+  return 1;
+}
+
 /*
 ** Try to read the wal-index header.  Return 0 on success and 1 if
 ** there is a problem.
@@ -2154,7 +2167,7 @@ int sqlite3WalClose(
 ** If the checksum cannot be verified return non-zero. If the header
 ** is read successfully and the checksum verified, return zero.
 */
-static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
+static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged, int cnt){
   u32 aCksum[2];                  /* Checksum on the header content */
   WalIndexHdr h1, h2;             /* Two copies of the header content */
   WalIndexHdr volatile *aHdr;     /* Header in shared memory */
@@ -2179,20 +2192,17 @@ static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
   ** reliably in that environment.
   */
   aHdr = walIndexHdr(pWal);
-  memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); /* Possible TSAN false-positive */
+  memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
   walShmBarrier(pWal);
   memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
 
   if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
-    return 1;   /* Dirty read */
-  }  
-  if( h1.isInit==0 ){
-    return 1;   /* Malformed header - probably all zeros */
-  }
-  walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum);
-  if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){
-    return 1;   /* Checksum does not match */
+    if( cnt<15 ) return 1;
+    if( !walIndexHdrValid(&h1) ){
+      memcpy(&h1, &h2, sizeof(h1));
+    }
   }
+  if( !walIndexHdrValid(&h1) ) return 1;
 
   if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
     *pChanged = 1;
@@ -2224,7 +2234,7 @@ static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
 ** If the wal-index header is successfully read, return SQLITE_OK. 
 ** Otherwise an SQLite error code.
 */
-static int walIndexReadHdr(Wal *pWal, int *pChanged){
+static int walIndexReadHdr(Wal *pWal, int *pChanged, int cnt){
   int rc;                         /* Return code */
   int badHdr;                     /* True if a header read failed */
   volatile u32 *page0;            /* Chunk of wal-index containing header */
@@ -2264,7 +2274,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
   ** works, but may fail if the wal-index header is corrupt or currently 
   ** being modified by another thread or process.
   */
-  badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
+  badHdr = (page0 ? walIndexTryHdr(pWal, pChanged, 0) : 1);
 
   /* If the first attempt failed, it might have been due to a race
   ** with a writer.  So get a WRITE lock and try again.
@@ -2280,7 +2290,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
       if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){
         pWal->writeLock = 1;
         if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
-          badHdr = walIndexTryHdr(pWal, pChanged);
+          badHdr = walIndexTryHdr(pWal, pChanged, cnt);
           if( badHdr ){
             /* If the wal-index header is still malformed even while holding
             ** a WRITE lock, it can only mean that the header is corrupted and
@@ -2586,7 +2596,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
   if( !useWal ){
     assert( rc==SQLITE_OK );
     if( pWal->bShmUnreliable==0 ){
-      rc = walIndexReadHdr(pWal, pChanged);
+      rc = walIndexReadHdr(pWal, pChanged, cnt);
     }
     if( rc==SQLITE_BUSY ){
       /* If there is not a recovery running in another thread or process
@@ -3745,7 +3755,7 @@ int sqlite3WalCheckpoint(
   /* Read the wal-index header. */
   if( rc==SQLITE_OK ){
     walDisableBlocking(pWal);
-    rc = walIndexReadHdr(pWal, &isChanged);
+    rc = walIndexReadHdr(pWal, &isChanged, 0);
     (void)walEnableBlocking(pWal);
     if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
       sqlite3OsUnfetch(pWal->pDbFd, 0, 0);