From: dan Date: Sat, 29 Dec 2018 20:42:12 +0000 (+0000) Subject: Fix a problem causing a corrupt pager-cache if an OOM or IO error was X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ff9e9b27d54690d93cd0acb5c95a892882d26139;p=thirdparty%2Fsqlite.git Fix a problem causing a corrupt pager-cache if an OOM or IO error was encountered while committing a concurrent transacation. FossilOrigin-Name: 48ca30f9d7817d87a5e9a069fdc51b1a34e00585f8a35771895dd743c7bfe07c --- diff --git a/manifest b/manifest index 53ad854a7b..37ed02ff19 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index b7d011b3bc..ccaa3c2b9b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -123cbb3312917ad5b3c32556547c5b7e8ba4e2d2def8651ff80f9fc1bdc1875c \ No newline at end of file +48ca30f9d7817d87a5e9a069fdc51b1a34e00585f8a35771895dd743c7bfe07c \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 5d7ef14983..fb7b685106 100644 --- a/src/pager.c +++ b/src/pager.c @@ -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 diff --git a/src/wal.c b/src/wal.c index 89f475d4d1..01cf270f3b 100644 --- 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; diff --git a/src/wal.h b/src/wal.h index 70247f1c2b..9878852c76 100644 --- 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 */ diff --git a/test/concfault.test b/test/concfault.test index 6d409c8d74..8c26d3d486 100644 --- a/test/concfault.test +++ b/test/concfault.test @@ -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