]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a problem causing a corrupt pager-cache if an OOM or IO error was
authordan <dan@noemail.net>
Sat, 29 Dec 2018 20:42:12 +0000 (20:42 +0000)
committerdan <dan@noemail.net>
Sat, 29 Dec 2018 20:42:12 +0000 (20:42 +0000)
encountered while committing a concurrent transacation.

FossilOrigin-Name: 48ca30f9d7817d87a5e9a069fdc51b1a34e00585f8a35771895dd743c7bfe07c

manifest
manifest.uuid
src/pager.c
src/wal.c
src/wal.h
test/concfault.test

index 53ad854a7bc519a732321b861268d610845c233e..37ed02ff1964737842817f777fa56ecc5c231cae 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Merge\slatest\strunk\schanges\sinto\sthis\sbranch.
-D 2018-12-18T17:20:01.245
+C Fix\sa\sproblem\scausing\sa\scorrupt\spager-cache\sif\san\sOOM\sor\sIO\serror\swas\nencountered\swhile\scommitting\sa\sconcurrent\stransacation.
+D 2018-12-29T20:42:12.966
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in d8b254f8bb81bab43c340d70d17dc3babab40fcc8a348c8255881f780a45fee6
@@ -498,7 +498,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
 F src/os_unix.c 86eca42c3d955bebea0082450f978e5633448235f03f86b27a02538bb26e7fff
 F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
-F src/pager.c 79b8ced46a3c32be19ab4b00d8836292e460411d283a333cb008923c69fbca6a
+F src/pager.c 94e8c52c0f91fbf7059ffbbd3be7939ee5122221e0e63855df7ba83100733580
 F src/pager.h 389ba8f526d13026aa7081dc581aa742eb7207e3277e7106c522c5b65ad92590
 F src/parse.y 8206217fe7fa96652aa1b8a797246e23b30a9d4c1a5175d9c12b13750f51dc2f
 F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee
@@ -593,8 +593,8 @@ F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7
 F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
 F src/vtab.c 70188a745dc4e57d26e942681ff4b2912b7c8249ad5de3f60f0677b4337bcfaa
 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c 6675d84d7bc5d04879e487d79248fb79d9bdad46811cc5ed5ef6233bdf1b70a1
-F src/wal.h f325a5856b669f5ba449157485915816103857c8574efc746ac55eba3335c5e0
+F src/wal.c 2d5771a64354e7a7ef926a38fec8c06193a50fda40cee027c5385c3330abb791
+F src/wal.h ac2100eeda406a4492b8c183154507532d23ab9d5a8e32e208adfe4f9ea554f9
 F src/walker.c fb94aadc9099ff9c6506d0a8b88d51266005bcaa265403f3d7caf732a562eb66
 F src/where.c 3818e8a736a05d2cb194e64399af707e367fbcc5c251d785804d02eaf121288e
 F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f
@@ -730,7 +730,7 @@ F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
 F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
 F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
 F test/colname.test fb28b3687e03625425bc216edf8b186ce974aa71008e2aa1f426a7dcb75a601d
-F test/concfault.test 500f17c3fcfe7705114422bcc6ddd3c740001a43
+F test/concfault.test e5370cd686f601a01909377cac3bbf13dac56d39dd4ad6b04ccbec9eeeaccb18
 F test/concurrent.test 86661967a680670127a62a819e60dc93c2d3d49043ac95b26dfa70d3e60dbde5
 F test/concurrent2.test 9dfbeb0a323733fe1d13443371734bb94a674dbf777f464365475903873111f8
 F test/concurrent3.test 530671ac706f6a1d0f4992dbdd33a86408330d03cd90fb9e82ecb1b27f5fd081
@@ -1800,7 +1800,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 1e13aaa29fb6324b60b3758bdab0491fdef9727e0de603d3da3e1885b52c5caa d64f248da3ce7762fe2c17fbc83f7bea9ffca73723bb3ad0982a85320839da90
-R 25be479282f6f39e20e5b15b242014de
+P 123cbb3312917ad5b3c32556547c5b7e8ba4e2d2def8651ff80f9fc1bdc1875c
+R 512dc15e0eb54608feb82659e89c990b
 U dan
-Z 3d11aa975cce853c61989d953b5773cd
+Z 01d5996e76265f2df93e10aa0e859282
index b7d011b3bcbab0569c381d394bdfd8eae7c20ae7..ccaa3c2b9b1e59b5a543ca5d2d1c6cc4c3a4a3eb 100644 (file)
@@ -1 +1 @@
-123cbb3312917ad5b3c32556547c5b7e8ba4e2d2def8651ff80f9fc1bdc1875c
\ No newline at end of file
+48ca30f9d7817d87a5e9a069fdc51b1a34e00585f8a35771895dd743c7bfe07c
\ No newline at end of file
index 5d7ef14983aeba8c6db9fe95a0328eb4db6bbc94..fb7b685106b18c2af9abf239a21a64c084411c62 100644 (file)
@@ -3213,7 +3213,13 @@ static int pagerRollbackWal(Pager *pPager){
   **   + Reload page content from the database (if refcount>0).
   */
   pPager->dbSize = pPager->dbOrigSize;
-  rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager);
+  rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager, 
+#ifdef SQLITE_OMIT_CONCURRENT
+      0
+#else
+      pPager->pAllRead!=0
+#endif
+  );
   pList = sqlite3PcacheDirtyList(pPager->pPCache);
 
 #ifndef SQLITE_OMIT_CONCURRENT
index 89f475d4d1263a57561fbd1e57b461bda66d90e7..01cf270f3bc3b634f0c0cdfc5826fdbb5fb11cb9 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -3256,7 +3256,12 @@ int sqlite3WalEndWriteTransaction(Wal *pWal){
 ** Otherwise, if the callback function does not return an error, this
 ** function returns SQLITE_OK.
 */
-int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
+int sqlite3WalUndo(
+  Wal *pWal, 
+  int (*xUndo)(void *, Pgno), 
+  void *pUndoCtx,
+  int bConcurrent                 /* True if this is a CONCURRENT transaction */
+){
   int rc = SQLITE_OK;
   if( pWal->writeLock ){
     Pgno iMax = pWal->hdr.mxFrame;
@@ -3266,6 +3271,13 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
     ** was in before the client began writing to the database. 
     */
     memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr));
+#ifndef SQLITE_OMIT_CONCURRENT
+    if( bConcurrent ){
+      pWal->hdr.aCksum[0]++;
+    }
+#else
+    UNUSED_PARAMETER(bConcurrent);
+#endif
 
     for(iFrame=pWal->hdr.mxFrame+1; 
         ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; 
index 70247f1c2b43cf0a3c54cc2d57eafea811b16b51..9878852c763cb6ba0019ed7d996305c6a2773582 100644 (file)
--- a/src/wal.h
+++ b/src/wal.h
@@ -34,7 +34,7 @@
 # define sqlite3WalDbsize(y)                     0
 # define sqlite3WalBeginWriteTransaction(y)      0
 # define sqlite3WalEndWriteTransaction(x)        0
-# define sqlite3WalUndo(x,y,z)                   0
+# define sqlite3WalUndo(w,x,y,z)                 0
 # define sqlite3WalSavepoint(y,z)
 # define sqlite3WalSavepointUndo(y,z)            0
 # define sqlite3WalFrames(u,v,w,x,y,z)           0
@@ -83,7 +83,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal);
 int sqlite3WalEndWriteTransaction(Wal *pWal);
 
 /* Undo any frames written (but not committed) to the log */
-int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx);
+int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx, int);
 
 /* Return an integer that records the current (uncommitted) write
 ** position in the WAL */
index 6d409c8d74f2f11ac7e0a51b1f219b1dbce755c1..8c26d3d48656a8653a2146dcebc86dfa992ed601 100644 (file)
@@ -82,5 +82,46 @@ do_faultsim_test 1.3 -prep {
   faultsim_integrity_check
 }
 
+
+#-------------------------------------------------------------------------
+reset_db
+
+do_execsql_test 2.0 {
+  PRAGMA auto_vacuum = 0;
+  PRAGMA journal_mode = wal;
+  CREATE TABLE t1(a PRIMARY KEY, b);
+  CREATE TABLE t2(a PRIMARY KEY, b);
+  INSERT INTO t1 VALUES(randomblob(1000), randomblob(100));
+  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
+  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
+  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
+  INSERT INTO t1 SELECT randomblob(1000), randomblob(1000) FROM t1;
+  DELETE FROM t1 WHERE rowid%2;
+} {wal}
+
+faultsim_save_and_close
+do_faultsim_test 1 -prep {
+  faultsim_restore_and_reopen
+  execsql {
+    SELECT * FROM t1;
+    BEGIN CONCURRENT;
+      INSERT INTO t2 VALUES(1, 2);
+  }
+  sqlite3 db2 test.db
+  execsql {
+    PRAGMA journal_size_limit = 10000;
+    INSERT INTO t1 VALUES(randomblob(1000), randomblob(1000));
+  } db2
+  db2 close
+} -body {
+  execsql { COMMIT }
+} -test {
+  faultsim_test_result {0 {}} 
+  catchsql { ROLLBACK }
+  set res [catchsql { SELECT count(*) FROM t1 }]
+  if {$res!="0 9"} { error "expected {0 9} got {$res}" }
+  faultsim_integrity_check
+}
+
 finish_test