From 8aa22ffe98071496f2f7a5a0d265cc9c267d9b58 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 19 Aug 2021 21:01:15 +0000 Subject: [PATCH 01/15] If SQLITE_USE_SEH is defined, handle structured-exceptions thrown by MSVC builds if the *-shm file mapping is accessed after it becomes invalid for some reason. FossilOrigin-Name: 5c5fa47076c5da25ca92248df3a4c11b90a0225a07f05d7220fa95d9bbb36f43 --- manifest | 20 +- manifest.uuid | 2 +- src/wal.c | 448 +++++++++++++++++++++++++++++---------- test/snapshot_fault.test | 1 + test/walseh1.test | 106 +++++++++ 5 files changed, 451 insertions(+), 126 deletions(-) create mode 100644 test/walseh1.test diff --git a/manifest b/manifest index 6e4b8ae466..aa4b2f1276 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sON\sCONFLICT\sclause\sprocessing\sfor\sNOT\sNULL\sconstraints\sof\sPRIMARY\sKEY\ncolumns\son\sWITHOUT\sROWID\stables.\nTicket\s[f2be158c57aaa8c6] -D 2021-08-18T22:26:51.356 +C If\sSQLITE_USE_SEH\sis\sdefined,\shandle\sstructured-exceptions\sthrown\sby\sMSVC\sbuilds\sif\sthe\s*-shm\sfile\smapping\sis\saccessed\safter\sit\sbecomes\sinvalid\sfor\ssome\sreason. +D 2021-08-19T21:01:15.043 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 2be08331d798237ad5d7ae0b252700ffb2b63189cb18d993496d009a93e2f81c +F src/wal.c dd9ca83fcd91eb237790c18e972f8f2fd30cf86848d6fa9fc09da25e8acf56ae F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1393,7 +1393,7 @@ F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3 F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54 F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322 -F test/snapshot_fault.test f6c5ef7cb93bf92fbb4e864ecc5c87df7d3a250064838822db5b4d3a5563ede4 +F test/snapshot_fault.test 129234ceb9b26a0e1000e8563a16e790f5c1412354e70749cbd78c3d5d07d60a F test/snapshot_up.test a0a29c4cf33475fcef07c3f8e64af795e24ab91b4cc68295863402a393cdd41c F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087 @@ -1739,6 +1739,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 +F test/walseh1.test 970946bdd40bc37d1552811b54ec94dd4a5a4178354b4afa129f2053b99bf09f F test/walsetlk.test 3185bebc90557e0d611442c8d64f7a0cb7b06f8e156eea37a4a7358f722715be F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f @@ -1920,7 +1921,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 b9b0dcd5af072c22f2ce71cf9584b5b572fbcfbce6410a7d703b586adb8938ba -R f57d6ed5153ac1a3784cf20c59f627b9 -U drh -Z 19e6156db8fe8743846e026420e0b856 +P 13abba0941a724eb62455650976b03678e4455b6b3090c84a2ab2f4a7656b4d8 +R f5105d1628b1a51745c8bcb5cc4af959 +T *branch * wal-shm-exceptions +T *sym-wal-shm-exceptions * +T -sym-trunk * +U dan +Z 55cb3a3675f7aa624d05737d0648760c diff --git a/manifest.uuid b/manifest.uuid index e76a74f795..7c3a0bb78c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -13abba0941a724eb62455650976b03678e4455b6b3090c84a2ab2f4a7656b4d8 \ No newline at end of file +5c5fa47076c5da25ca92248df3a4c11b90a0225a07f05d7220fa95d9bbb36f43 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 83929ea467..c8cf4cc1b3 100644 --- a/src/wal.c +++ b/src/wal.c @@ -528,6 +528,13 @@ struct Wal { u32 iReCksum; /* On commit, recalculate checksums from here */ const char *zWalName; /* Name of WAL file */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ +#ifdef SQLITE_USE_SEH +# ifdef SQLITE_DEBUG + int nSehTry; /* Number of nested SEH_TRY{} blocks */ +# endif + u32 lockMask; /* Mask of locks held */ + void *pFree; /* Pointer to sqlite3_free() if exception thrown */ +#endif #ifdef SQLITE_DEBUG u8 lockError; /* True if a locking error has occurred */ #endif @@ -610,6 +617,46 @@ struct WalIterator { sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ ) +#ifdef SQLITE_USE_SEH + +#include + +# define SEH_TRY __try { \ + assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); TESTONLY(pWal->nSehTry++); + +# define SEH_EXCEPT TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); \ + } __except( sehExceptionFilter(pWal, GetExceptionCode()) ) + +# define SEH_INJECT_FAULT sehInjectFault(pWal) + +/* +** The second argument is the return value of GetExceptionCode() for the +** current exception. Return EXCEPTION_EXECUTE_HANDLER if the exception code +** indicates that the exception may have been caused by accessing the *-shm +** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise. +*/ +static int sehExceptionFilter(Wal *pWal, int eCode){ + TESTONLY(pWal->nSehTry--); + if( eCode==EXCEPTION_ACCESS_VIOLATION ){ + return EXCEPTION_EXECUTE_HANDLER; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +static void sehInjectFault(Wal *pWal){ + assert( pWal->nSehTry>0 ); + if( sqlite3FaultSim(650) ){ + RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, NULL); + } +} + +#else +# define SEH_TRY +# define SEH_EXCEPT if(0) +# define SEH_INJECT_FAULT +#endif /* ifdef SQLITE_USE_SEH */ + + /* ** Obtain a pointer to the iPage'th page of the wal-index. The wal-index ** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are @@ -676,6 +723,7 @@ static int walIndexPage( int iPage, /* The page we seek */ volatile u32 **ppPage /* Write the page pointer here */ ){ + SEH_INJECT_FAULT; if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){ return walIndexPageRealloc(pWal, iPage, ppPage); } @@ -687,6 +735,7 @@ static int walIndexPage( */ static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ assert( pWal->nWiData>0 && pWal->apWiData[0] ); + SEH_INJECT_FAULT; return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]); } @@ -695,6 +744,7 @@ static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ */ static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ assert( pWal->nWiData>0 && pWal->apWiData[0] ); + SEH_INJECT_FAULT; return (volatile WalIndexHdr*)pWal->apWiData[0]; } @@ -931,12 +981,18 @@ static int walLockShared(Wal *pWal, int lockIdx){ WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, walLockName(lockIdx), rc ? "failed" : "ok")); VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) +#ifdef SQLITE_USE_SEH + if( rc==SQLITE_OK ) pWal->lockMask |= (1 << lockIdx); +#endif return rc; } static void walUnlockShared(Wal *pWal, int lockIdx){ if( pWal->exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); +#ifdef SQLITE_USE_SEH + pWal->lockMask &= ~(1 << lockIdx); +#endif WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); } static int walLockExclusive(Wal *pWal, int lockIdx, int n){ @@ -947,12 +1003,20 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){ WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, walLockName(lockIdx), n, rc ? "failed" : "ok")); VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) +#ifdef SQLITE_USE_SEH + if( rc==SQLITE_OK ){ + pWal->lockMask |= (((1<exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); +#ifdef SQLITE_USE_SEH + pWal->lockMask &= ~(((1<pFree = aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); if( !aFrame ){ rc = SQLITE_NOMEM_BKPT; goto recovery_error; @@ -1380,6 +1444,7 @@ static int walIndexRecover(Wal *pWal){ } sqlite3_free(aFrame); + pWal->pFree = 0; } finished: @@ -1789,22 +1854,16 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + iLast*sizeof(ht_slot); - p = (WalIterator *)sqlite3_malloc64(nByte); + p = (WalIterator *)sqlite3_malloc64(nByte + + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) + ); if( !p ){ return SQLITE_NOMEM_BKPT; } memset(p, 0, nByte); p->nSegment = nSegment; - - /* Allocate temporary space used by the merge-sort routine. This block - ** of memory will be freed before this function returns. - */ - aTmp = (ht_slot *)sqlite3_malloc64( - sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) - ); - if( !aTmp ){ - rc = SQLITE_NOMEM_BKPT; - } + aTmp = (ht_slot*)&(((u8*)p)[nByte]); + pWal->pFree = p; for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && iaSegment[i].aPgno = (u32 *)sLoc.aPgno; } } - sqlite3_free(aTmp); if( rc!=SQLITE_OK ){ walIteratorFree(p); - p = 0; + pWal->pFree = p = 0; } *pp = p; return rc; @@ -2062,7 +2120,7 @@ static int walCheckpoint( mxSafeFrame = pWal->hdr.mxFrame; mxPage = pWal->hdr.nPage; for(i=1; iaReadMark+i); + u32 y = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; if( mxSafeFrame>y ){ assert( y<=pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); @@ -2089,8 +2147,7 @@ static int walCheckpoint( && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK ){ u32 nBackfill = pInfo->nBackfill; - - pInfo->nBackfillAttempted = mxSafeFrame; + pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT; /* Sync the WAL to disk */ rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); @@ -2172,6 +2229,7 @@ static int walCheckpoint( */ if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ assert( pWal->writeLock ); + SEH_INJECT_FAULT; if( pInfo->nBackfillhdr.mxFrame ){ rc = SQLITE_BUSY; }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ @@ -2203,7 +2261,9 @@ static int walCheckpoint( } walcheckpoint_out: + assert( pWal->pFree==(void*)pIter ); walIteratorFree(pIter); + pWal->pFree = 0; return rc; } @@ -2239,6 +2299,10 @@ int sqlite3WalClose( if( pWal ){ int isDelete = 0; /* True to unlink wal and wal-index files */ +#ifdef SQLITE_USE_SEH + assert( pWal->lockMask==0 ); +#endif + /* If an EXCLUSIVE lock can be obtained on the database file (using the ** ordinary, rollback-mode locking methods, this guarantees that the ** connection associated with this log file is the only connection to @@ -2779,6 +2843,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ assert( pWal->nWiData>0 ); assert( pWal->apWiData[0]!=0 ); pInfo = walCkptInfo(pWal); + SEH_INJECT_FAULT; if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame #ifdef SQLITE_ENABLE_SNAPSHOT && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0) @@ -2828,7 +2893,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ } #endif for(i=1; iaReadMark+i); + u32 thisMark = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; if( mxReadMark<=thisMark && thisMark<=mxFrame ){ assert( thisMark!=READMARK_NOT_USED ); mxReadMark = thisMark; @@ -2894,7 +2959,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** we can guarantee that the checkpointer that set nBackfill could not ** see any pages past pWal->hdr.mxFrame, this problem does not come up. */ - pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; + pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT; walShmBarrier(pWal); if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) @@ -2908,7 +2973,112 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ return rc; } +#ifdef SQLITE_USE_SEH +/* +** This is the "standard" exception handler used in a few places to handle +** an exception thrown by reading from the *-shm mapping after it has become +** invalid in SQLITE_USE_SEH builds. It is used as follows: +** +** SEH_TRY { ... } +** SEH_EXCEPT { rc = walHandleException(pWal); } +** +** This function does three things: +** +** 1) Determines the locks that should be held, based on the contents of +** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other +** held locks are assumed to be transient locks that would have been +** released had the exception not been thrown and are dropped. +** +** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free(). +** +** 3) Returns SQLITE_IOERR. +*/ +static int walHandleException(Wal *pWal){ + if( pWal->exclusiveMode==0 ){ + static const int S = 1; + static const int E = (1<lockMask & ~( + (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) + ); + for(ii=0; iipFree); + pWal->pFree = 0; + return SQLITE_IOERR; +} + +static int walAssertLockmask(Wal *pWal){ + if( pWal->exclusiveMode==0 ){ + static const int S = 1; + static const int E = (1<readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) #ifdef SQLITE_ENABLE_SNAPSHOT + | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0) +#endif + ); + assert( mExpect==pWal->lockMask ); + } + return 1; +} +#endif + +#ifdef SQLITE_ENABLE_SNAPSHOT +/* +** This function does the work of sqlite3WalSnapshotRecover(). +*/ +static int walSnapshotRecover( + Wal *pWal, /* WAL handle */ + void *pBuf1, /* Temp buffer pWal->szPage bytes in size */ + void *pBuf2 /* Temp buffer pWal->szPage bytes in size */ +){ + int szPage = (int)pWal->szPage; + int rc; + i64 szDb; /* Size of db file in bytes */ + + rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); + if( rc==SQLITE_OK ){ + volatile WalCkptInfo *pInfo = walCkptInfo(pWal); + u32 i = pInfo->nBackfillAttempted; + for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ + WalHashLoc sLoc; /* Hash table location */ + u32 pgno; /* Page number in db file */ + i64 iDbOff; /* Offset of db file entry */ + i64 iWalOff; /* Offset of wal file entry */ + + rc = walHashGet(pWal, walFramePage(i), &sLoc); + if( rc!=SQLITE_OK ) break; + pgno = sLoc.aPgno[i-sLoc.iZero]; + iDbOff = (i64)(pgno-1) * szPage; + + if( iDbOff+szPage<=szDb ){ + iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; + rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); + + if( rc==SQLITE_OK ){ + rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); + } + + if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ + break; + } + } + + pInfo->nBackfillAttempted = i-1; + } + } + + return rc; +} + /* ** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted ** variable so that older snapshots can be accessed. To do this, loop @@ -2934,49 +3104,23 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ assert( pWal->readLock>=0 ); rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); if( rc==SQLITE_OK ){ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - int szPage = (int)pWal->szPage; - i64 szDb; /* Size of db file in bytes */ - - rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); - if( rc==SQLITE_OK ){ - void *pBuf1 = sqlite3_malloc(szPage); - void *pBuf2 = sqlite3_malloc(szPage); - if( pBuf1==0 || pBuf2==0 ){ - rc = SQLITE_NOMEM; - }else{ - u32 i = pInfo->nBackfillAttempted; - for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ - WalHashLoc sLoc; /* Hash table location */ - u32 pgno; /* Page number in db file */ - i64 iDbOff; /* Offset of db file entry */ - i64 iWalOff; /* Offset of wal file entry */ - - rc = walHashGet(pWal, walFramePage(i), &sLoc); - if( rc!=SQLITE_OK ) break; - pgno = sLoc.aPgno[i-sLoc.iZero]; - iDbOff = (i64)(pgno-1) * szPage; - - if( iDbOff+szPage<=szDb ){ - iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; - rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); - - if( rc==SQLITE_OK ){ - rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); - } - - if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ - break; - } - } - - pInfo->nBackfillAttempted = i-1; - } + void *pBuf1 = sqlite3_malloc(pWal->szPage); + void *pBuf2 = sqlite3_malloc(pWal->szPage); + if( pBuf1==0 || pBuf2==0 ){ + rc = SQLITE_NOMEM; + }else{ + pWal->ckptLock = 1; + SEH_TRY { + rc = walSnapshotRecover(pWal, pBuf1, pBuf2); } - - sqlite3_free(pBuf1); - sqlite3_free(pBuf2); + SEH_EXCEPT { + rc = SQLITE_IOERR; + } + pWal->ckptLock = 0; } + + sqlite3_free(pBuf1); + sqlite3_free(pBuf2); walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); } @@ -2998,10 +3142,11 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ ** Pager layer will use this to know that its cache is stale and ** needs to be flushed. */ -int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ +static int walBeginReadTransaction(Wal *pWal, int *pChanged){ int rc; /* Return code */ int cnt = 0; /* Number of TryBeginRead attempts */ #ifdef SQLITE_ENABLE_SNAPSHOT + int ckptLock = 0; int bChanged = 0; WalIndexHdr *pSnapshot = pWal->pSnapshot; #endif @@ -3029,7 +3174,7 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ if( rc!=SQLITE_OK ){ return rc; } - pWal->ckptLock = 1; + ckptLock = 1; } #endif @@ -3093,15 +3238,25 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ } /* Release the shared CKPT lock obtained above. */ - if( pWal->ckptLock ){ + if( ckptLock ){ assert( pSnapshot ); walUnlockShared(pWal, WAL_CKPT_LOCK); - pWal->ckptLock = 0; } #endif return rc; } +int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ + int rc; + SEH_TRY { + rc = walBeginReadTransaction(pWal, pChanged); + } + SEH_EXCEPT { + rc = walHandleException(pWal); + } + return rc; +} + /* ** Finish with a read transaction. All this does is release the ** read-lock. @@ -3122,7 +3277,7 @@ void sqlite3WalEndReadTransaction(Wal *pWal){ ** Return SQLITE_OK if successful, or an error code if an error occurs. If an ** error does occur, the final value of *piRead is undefined. */ -int sqlite3WalFindFrame( +static int walFindFrame( Wal *pWal, /* WAL handle */ Pgno pgno, /* Database page number to read data for */ u32 *piRead /* OUT: Frame number (or zero) */ @@ -3185,6 +3340,7 @@ int sqlite3WalFindFrame( } nCollide = HASHTABLE_NSLOT; iKey = walHash(pgno); + SEH_INJECT_FAULT; while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){ u32 iFrame = iH + sLoc.iZero; if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){ @@ -3221,6 +3377,19 @@ int sqlite3WalFindFrame( return SQLITE_OK; } +int sqlite3WalFindFrame( + Wal *pWal, /* WAL handle */ + Pgno pgno, /* Database page number to read data for */ + u32 *piRead /* OUT: Frame number (or zero) */ +){ + int rc; + SEH_TRY { + rc = walFindFrame(pWal, pgno, piRead); + } + SEH_EXCEPT { rc = SQLITE_IOERR; } + return rc; +} + /* ** Read the contents of frame iRead from the wal file into buffer pOut ** (which is nOut bytes in size). Return SQLITE_OK if successful, or an @@ -3302,12 +3471,17 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){ ** time the read transaction on this connection was started, then ** the write is disallowed. */ - if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ + SEH_TRY { + if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ + rc = SQLITE_BUSY_SNAPSHOT; + } + } + SEH_EXCEPT { rc = SQLITE_IOERR; } + + if( rc!=SQLITE_OK ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); pWal->writeLock = 0; - rc = SQLITE_BUSY_SNAPSHOT; } - return rc; } @@ -3343,30 +3517,35 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ Pgno iMax = pWal->hdr.mxFrame; Pgno iFrame; - /* Restore the clients cache of the wal-index header to the state it - ** was in before the client began writing to the database. - */ - memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); - - for(iFrame=pWal->hdr.mxFrame+1; - ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; - iFrame++ - ){ - /* This call cannot fail. Unless the page for which the page number - ** is passed as the second argument is (a) in the cache and - ** (b) has an outstanding reference, then xUndo is either a no-op - ** (if (a) is false) or simply expels the page from the cache (if (b) - ** is false). - ** - ** If the upper layer is doing a rollback, it is guaranteed that there - ** are no outstanding references to any page other than page 1. And - ** page 1 is never written to the log until the transaction is - ** committed. As a result, the call to xUndo may not fail. + SEH_TRY { + /* Restore the clients cache of the wal-index header to the state it + ** was in before the client began writing to the database. */ - assert( walFramePgno(pWal, iFrame)!=1 ); - rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); + memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); + + for(iFrame=pWal->hdr.mxFrame+1; + ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; + iFrame++ + ){ + /* This call cannot fail. Unless the page for which the page number + ** is passed as the second argument is (a) in the cache and + ** (b) has an outstanding reference, then xUndo is either a no-op + ** (if (a) is false) or simply expels the page from the cache (if (b) + ** is false). + ** + ** If the upper layer is doing a rollback, it is guaranteed that there + ** are no outstanding references to any page other than page 1. And + ** page 1 is never written to the log until the transaction is + ** committed. As a result, the call to xUndo may not fail. + */ + assert( walFramePgno(pWal, iFrame)!=1 ); + rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); + } + if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); + } + SEH_EXCEPT { + rc = SQLITE_IOERR; } - if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } return rc; } @@ -3410,7 +3589,12 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ pWal->hdr.mxFrame = aWalData[0]; pWal->hdr.aFrameCksum[0] = aWalData[1]; pWal->hdr.aFrameCksum[1] = aWalData[2]; - walCleanupHash(pWal); + SEH_TRY { + walCleanupHash(pWal); + } + SEH_EXCEPT { + rc = SQLITE_IOERR; + } } return rc; @@ -3591,7 +3775,7 @@ static int walRewriteChecksums(Wal *pWal, u32 iLast){ ** Write a set of frames to the log. The caller must hold the write-lock ** on the log file (obtained using sqlite3WalBeginWriteTransaction()). */ -int sqlite3WalFrames( +static int walFrames( Wal *pWal, /* Wal handle to write to */ int szPage, /* Database page-size in bytes */ PgHdr *pList, /* List of dirty pages to write */ @@ -3700,7 +3884,7 @@ int sqlite3WalFrames( ** checksums must be recomputed when the transaction is committed. */ if( iFirst && (p->pDirty || isCommit==0) ){ u32 iWrite = 0; - VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite); + VVA_ONLY(rc =) walFindFrame(pWal, p->pgno, &iWrite); assert( rc==SQLITE_OK || iWrite==0 ); if( iWrite>=iFirst ){ i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE; @@ -3819,6 +4003,24 @@ int sqlite3WalFrames( return rc; } +int sqlite3WalFrames( + Wal *pWal, /* Wal handle to write to */ + int szPage, /* Database page-size in bytes */ + PgHdr *pList, /* List of dirty pages to write */ + Pgno nTruncate, /* Database size after this commit */ + int isCommit, /* True if this is a commit */ + int sync_flags /* Flags to pass to OsSync() (or 0) */ +){ + int rc; + SEH_TRY { + rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags); + } + SEH_EXCEPT { + rc = walHandleException(pWal); + } + return rc; +} + /* ** This routine is called to implement sqlite3_wal_checkpoint() and ** related interfaces. @@ -3848,6 +4050,7 @@ int sqlite3WalCheckpoint( assert( pWal->ckptLock==0 ); assert( pWal->writeLock==0 ); + assert( pWal->readLock<0 ); /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ @@ -3898,30 +4101,34 @@ int sqlite3WalCheckpoint( /* Read the wal-index header. */ - if( rc==SQLITE_OK ){ - walDisableBlocking(pWal); - rc = walIndexReadHdr(pWal, &isChanged); - (void)walEnableBlocking(pWal); - if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ - sqlite3OsUnfetch(pWal->pDbFd, 0, 0); + SEH_TRY { + if( rc==SQLITE_OK ){ + walDisableBlocking(pWal); + rc = walIndexReadHdr(pWal, &isChanged); + (void)walEnableBlocking(pWal); + if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ + sqlite3OsUnfetch(pWal->pDbFd, 0, 0); + } } - } - - /* Copy data from the log to the database file. */ - if( rc==SQLITE_OK ){ - - if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); + + /* Copy data from the log to the database file. */ + if( rc==SQLITE_OK ){ + if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); + } } - + /* If no error occurred, set the output variables. */ if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); } } + SEH_EXCEPT { + rc = walHandleException(pWal); + } if( isChanged ){ /* If a new wal-index header was loaded before the checkpoint was @@ -3998,7 +4205,9 @@ int sqlite3WalExclusiveMode(Wal *pWal, int op){ ** locks are taken in this case). Nor should the pager attempt to ** upgrade to exclusive-mode following such an error. */ +#ifndef SQLITE_USE_SEH assert( pWal->readLock>=0 || pWal->lockError ); +#endif assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); if( op==0 ){ @@ -4099,16 +4308,21 @@ int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ */ int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ int rc; - rc = walLockShared(pWal, WAL_CKPT_LOCK); - if( rc==SQLITE_OK ){ - WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; - if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) - || pNew->mxFramenBackfillAttempted - ){ - rc = SQLITE_ERROR_SNAPSHOT; - walUnlockShared(pWal, WAL_CKPT_LOCK); + SEH_TRY { + rc = walLockShared(pWal, WAL_CKPT_LOCK); + if( rc==SQLITE_OK ){ + WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; + if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) + || pNew->mxFramenBackfillAttempted + ){ + rc = SQLITE_ERROR_SNAPSHOT; + walUnlockShared(pWal, WAL_CKPT_LOCK); + } } } + SEH_EXCEPT { + rc = walHandleException(pWal); + } return rc; } diff --git a/test/snapshot_fault.test b/test/snapshot_fault.test index 2adb793650..10c5094594 100644 --- a/test/snapshot_fault.test +++ b/test/snapshot_fault.test @@ -23,6 +23,7 @@ set testprefix snapshot_fault # checkpointing the db. # do_faultsim_test 1.0 -prep { + catch { db2 close } faultsim_delete_and_reopen sqlite3 db2 test.db db2 eval { diff --git a/test/walseh1.test b/test/walseh1.test new file mode 100644 index 0000000000..ba5d786c48 --- /dev/null +++ b/test/walseh1.test @@ -0,0 +1,106 @@ +# 2021 August 16 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/malloc_common.tcl +set testprefix seh1 + +set ::seh_countdown 0 +proc seh_faultsim_callback {iFault} { + if {$iFault==650} { + incr ::seh_countdown -1 + if {$::seh_countdown==0} { return 1 } + } + return 0 +} + +proc seh_injectinstall {} { + sqlite3_test_control_fault_install seh_faultsim_callback +} +proc seh_injectuninstall {} { + sqlite3_test_control_fault_install +} +proc seh_injectstart {iFail} { + set ::seh_countdown $iFail +} +proc seh_injectstop {} { + set res [expr $::seh_countdown<=0] + set ::seh_countdown 0 + set res +} + +set FAULTSIM(seh) [list \ + -injectinstall seh_injectinstall \ + -injectstart seh_injectstart \ + -injectstop seh_injectstop \ + -injecterrlist {{1 {disk I/O error}}} \ + -injectuninstall seh_injectuninstall \ +] + +do_execsql_test 1.0 { + PRAGMA journal_mode = wal; + CREATE TABLE t1(x, y); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(3, 4); +} {wal} +faultsim_save_and_close + +do_faultsim_test 1 -faults seh -prep { + catch { db2 close } + faultsim_restore_and_reopen + execsql { SELECT * FROM sqlite_schema } + sqlite3 db2 test.db +} -body { + execsql { SELECT * FROM t1 } db2 +} -test { + faultsim_test_result {0 {1 2 3 4}} +} +catch { db2 close } + +faultsim_save_and_close + +do_faultsim_test 2 -faults seh -prep { + catch { db close } + faultsim_restore_and_reopen +} -body { + execsql { SELECT * FROM t1 } +} -test { + faultsim_test_result {0 {1 2 3 4}} +} + +do_faultsim_test 3 -faults seh -prep { + catch { db close } + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO t1 VALUES(5, 6) } + execsql { SELECT * FROM t1 } +} -test { + faultsim_test_result {0 {1 2 3 4 5 6}} +} +catch { db close } + +do_faultsim_test 4 -faults seh -prep { + catch { db close } + faultsim_restore_and_reopen +} -body { + execsql { PRAGMA wal_checkpoint } + execsql { INSERT INTO t1 VALUES(7, 8) } + execsql { SELECT * FROM t1 } +} -test { + faultsim_test_result {0 {1 2 3 4 7 8}} +} +catch { db close } + +finish_test + + From aecd7f9d75d0fd7d3d03a8ea23b1507c632ca30b Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 19 Aug 2021 23:10:57 +0000 Subject: [PATCH 02/15] Enable this branch to run both with and without the -DSQLITE_USE_SEH option. FossilOrigin-Name: 840e0a14ebc4a85d4ede0223287d4c1e4465e9f20c3c43bfc74775dddec1fa8f --- manifest | 17 +++++++-------- manifest.uuid | 2 +- src/wal.c | 57 ++++++++++++++++++++++----------------------------- 3 files changed, 33 insertions(+), 43 deletions(-) diff --git a/manifest b/manifest index aa4b2f1276..66ae90556b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\sSQLITE_USE_SEH\sis\sdefined,\shandle\sstructured-exceptions\sthrown\sby\sMSVC\sbuilds\sif\sthe\s*-shm\sfile\smapping\sis\saccessed\safter\sit\sbecomes\sinvalid\sfor\ssome\sreason. -D 2021-08-19T21:01:15.043 +C Enable\sthis\sbranch\sto\srun\sboth\swith\sand\swithout\sthe\s-DSQLITE_USE_SEH\soption. +D 2021-08-19T23:10:57.409 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c dd9ca83fcd91eb237790c18e972f8f2fd30cf86848d6fa9fc09da25e8acf56ae +F src/wal.c c07f7f1301f2af98e2ae83b5bde451b715da14ca88a355f85a7d4656f8f295c3 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,10 +1921,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 13abba0941a724eb62455650976b03678e4455b6b3090c84a2ab2f4a7656b4d8 -R f5105d1628b1a51745c8bcb5cc4af959 -T *branch * wal-shm-exceptions -T *sym-wal-shm-exceptions * -T -sym-trunk * -U dan -Z 55cb3a3675f7aa624d05737d0648760c +P 5c5fa47076c5da25ca92248df3a4c11b90a0225a07f05d7220fa95d9bbb36f43 +R 7dea1ca77fe483a4591a9d63bfe86a5f +U drh +Z 84658daaaacd80f58fddb8eaeaf9e417 diff --git a/manifest.uuid b/manifest.uuid index 7c3a0bb78c..5bfd9ee381 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5c5fa47076c5da25ca92248df3a4c11b90a0225a07f05d7220fa95d9bbb36f43 \ No newline at end of file +840e0a14ebc4a85d4ede0223287d4c1e4465e9f20c3c43bfc74775dddec1fa8f \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index c8cf4cc1b3..9a4451a091 100644 --- a/src/wal.c +++ b/src/wal.c @@ -624,8 +624,8 @@ struct WalIterator { # define SEH_TRY __try { \ assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); TESTONLY(pWal->nSehTry++); -# define SEH_EXCEPT TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); \ - } __except( sehExceptionFilter(pWal, GetExceptionCode()) ) +# define SEH_EXCEPT(X) TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); \ + } __except( sehExceptionFilter(pWal, GetExceptionCode()) ){ X } # define SEH_INJECT_FAULT sehInjectFault(pWal) @@ -650,10 +650,13 @@ static void sehInjectFault(Wal *pWal){ } } +#define SEH_FREE_ON_ERROR(X) pWal->pFree = X + #else # define SEH_TRY -# define SEH_EXCEPT if(0) +# define SEH_EXCEPT(X) # define SEH_INJECT_FAULT +# define SEH_FREE_ON_ERROR(X) #endif /* ifdef SQLITE_USE_SEH */ @@ -1365,7 +1368,8 @@ static int walIndexRecover(Wal *pWal){ /* Malloc a buffer to read frames into. */ szFrame = szPage + WAL_FRAME_HDRSIZE; - pWal->pFree = aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); + aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); + SEH_FREE_ON_ERROR(aFrame); if( !aFrame ){ rc = SQLITE_NOMEM_BKPT; goto recovery_error; @@ -1444,7 +1448,7 @@ static int walIndexRecover(Wal *pWal){ } sqlite3_free(aFrame); - pWal->pFree = 0; + SEH_FREE_ON_ERROR(0); } finished: @@ -1863,7 +1867,7 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ memset(p, 0, nByte); p->nSegment = nSegment; aTmp = (ht_slot*)&(((u8*)p)[nByte]); - pWal->pFree = p; + SEH_FREE_ON_ERROR(p); for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && ipFree = p = 0; + p = 0; + SEH_FREE_ON_ERROR(0); } *pp = p; return rc; @@ -2261,9 +2266,11 @@ static int walCheckpoint( } walcheckpoint_out: +#ifdef SQLITE_USE_SEH assert( pWal->pFree==(void*)pIter ); - walIteratorFree(pIter); pWal->pFree = 0; +#endif + walIteratorFree(pIter); return rc; } @@ -2980,7 +2987,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** invalid in SQLITE_USE_SEH builds. It is used as follows: ** ** SEH_TRY { ... } -** SEH_EXCEPT { rc = walHandleException(pWal); } +** SEH_EXCEPT( rc = walHandleException(pWal); ) ** ** This function does three things: ** @@ -3113,9 +3120,7 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ SEH_TRY { rc = walSnapshotRecover(pWal, pBuf1, pBuf2); } - SEH_EXCEPT { - rc = SQLITE_IOERR; - } + SEH_EXCEPT( rc = SQLITE_IOERR; ) pWal->ckptLock = 0; } @@ -3251,9 +3256,7 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ SEH_TRY { rc = walBeginReadTransaction(pWal, pChanged); } - SEH_EXCEPT { - rc = walHandleException(pWal); - } + SEH_EXCEPT( rc = walHandleException(pWal); ) return rc; } @@ -3386,7 +3389,7 @@ int sqlite3WalFindFrame( SEH_TRY { rc = walFindFrame(pWal, pgno, piRead); } - SEH_EXCEPT { rc = SQLITE_IOERR; } + SEH_EXCEPT( rc = SQLITE_IOERR; ) return rc; } @@ -3476,7 +3479,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){ rc = SQLITE_BUSY_SNAPSHOT; } } - SEH_EXCEPT { rc = SQLITE_IOERR; } + SEH_EXCEPT( rc = SQLITE_IOERR; ) if( rc!=SQLITE_OK ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); @@ -3543,9 +3546,7 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ } if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } - SEH_EXCEPT { - rc = SQLITE_IOERR; - } + SEH_EXCEPT( rc = SQLITE_IOERR; ) } return rc; } @@ -3592,9 +3593,7 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ SEH_TRY { walCleanupHash(pWal); } - SEH_EXCEPT { - rc = SQLITE_IOERR; - } + SEH_EXCEPT( rc = SQLITE_IOERR; ) } return rc; @@ -4015,9 +4014,7 @@ int sqlite3WalFrames( SEH_TRY { rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags); } - SEH_EXCEPT { - rc = walHandleException(pWal); - } + SEH_EXCEPT( rc = walHandleException(pWal); ) return rc; } @@ -4126,9 +4123,7 @@ int sqlite3WalCheckpoint( if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); } } - SEH_EXCEPT { - rc = walHandleException(pWal); - } + SEH_EXCEPT( rc = walHandleException(pWal); ) if( isChanged ){ /* If a new wal-index header was loaded before the checkpoint was @@ -4320,9 +4315,7 @@ int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ } } } - SEH_EXCEPT { - rc = walHandleException(pWal); - } + SEH_EXCEPT( rc = walHandleException(pWal); ) return rc; } From b15c63cbb954aafebd8a01826e9154830f6d03e6 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 20 Aug 2021 11:50:12 +0000 Subject: [PATCH 03/15] Fix a problem on this branch causing checkpoints that do not proceed because they can't get the CHECKPOINT lock to return incorrect output values. FossilOrigin-Name: 5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/wal.c | 14 +++++++------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 66ae90556b..a3c3624cf6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enable\sthis\sbranch\sto\srun\sboth\swith\sand\swithout\sthe\s-DSQLITE_USE_SEH\soption. -D 2021-08-19T23:10:57.409 +C Fix\sa\sproblem\son\sthis\sbranch\scausing\scheckpoints\sthat\sdo\snot\sproceed\sbecause\sthey\scan't\sget\sthe\sCHECKPOINT\slock\sto\sreturn\sincorrect\soutput\svalues. +D 2021-08-20T11:50:12.817 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c c07f7f1301f2af98e2ae83b5bde451b715da14ca88a355f85a7d4656f8f295c3 +F src/wal.c 42c64a0c198c0610a4f54158faff9ad8b0f3f390cb03c1a69692dc70f886b711 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,7 +1921,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 5c5fa47076c5da25ca92248df3a4c11b90a0225a07f05d7220fa95d9bbb36f43 -R 7dea1ca77fe483a4591a9d63bfe86a5f -U drh -Z 84658daaaacd80f58fddb8eaeaf9e417 +P 840e0a14ebc4a85d4ede0223287d4c1e4465e9f20c3c43bfc74775dddec1fa8f +R 97abf4da384cedc02121f231f21869ab +U dan +Z 53bdf1f79fced94468e78efd135afd05 diff --git a/manifest.uuid b/manifest.uuid index 5bfd9ee381..827b32b4dd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -840e0a14ebc4a85d4ede0223287d4c1e4465e9f20c3c43bfc74775dddec1fa8f \ No newline at end of file +5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 9a4451a091..e17d3959b0 100644 --- a/src/wal.c +++ b/src/wal.c @@ -4113,14 +4113,14 @@ int sqlite3WalCheckpoint( if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ rc = SQLITE_CORRUPT_BKPT; }else{ - rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); + rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf); + } + + /* If no error occurred, set the output variables. */ + if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ + if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; + if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); } - } - - /* If no error occurred, set the output variables. */ - if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ - if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; - if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); } } SEH_EXCEPT( rc = walHandleException(pWal); ) From c6effdbfba68315a45593a29febf4e915549befa Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 20 Aug 2021 16:19:19 +0000 Subject: [PATCH 04/15] Add some assert() statements and fix small issues with code on this branch. FossilOrigin-Name: bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45 --- manifest | 12 +++--- manifest.uuid | 2 +- src/wal.c | 110 ++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 86 insertions(+), 38 deletions(-) diff --git a/manifest b/manifest index a3c3624cf6..d417bb139e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\son\sthis\sbranch\scausing\scheckpoints\sthat\sdo\snot\sproceed\sbecause\sthey\scan't\sget\sthe\sCHECKPOINT\slock\sto\sreturn\sincorrect\soutput\svalues. -D 2021-08-20T11:50:12.817 +C Add\ssome\sassert()\sstatements\sand\sfix\ssmall\sissues\swith\scode\son\sthis\sbranch. +D 2021-08-20T16:19:19.544 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 42c64a0c198c0610a4f54158faff9ad8b0f3f390cb03c1a69692dc70f886b711 +F src/wal.c d47742fa0d58fa622416cfd105b4b309f39006f30d903e02db2f48236f3d83d7 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,7 +1921,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 840e0a14ebc4a85d4ede0223287d4c1e4465e9f20c3c43bfc74775dddec1fa8f -R 97abf4da384cedc02121f231f21869ab +P 5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa +R eab33be79c818813f4366ae19768ee1d U dan -Z 53bdf1f79fced94468e78efd135afd05 +Z 8887602c0a0185b63b60ad6538fd96e1 diff --git a/manifest.uuid b/manifest.uuid index 827b32b4dd..4034ae736f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa \ No newline at end of file +bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index e17d3959b0..f6c2d86df8 100644 --- a/src/wal.c +++ b/src/wal.c @@ -528,10 +528,10 @@ struct Wal { u32 iReCksum; /* On commit, recalculate checksums from here */ const char *zWalName; /* Name of WAL file */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ -#ifdef SQLITE_USE_SEH # ifdef SQLITE_DEBUG int nSehTry; /* Number of nested SEH_TRY{} blocks */ # endif +#ifdef SQLITE_USE_SEH u32 lockMask; /* Mask of locks held */ void *pFree; /* Pointer to sqlite3_free() if exception thrown */ #endif @@ -622,9 +622,12 @@ struct WalIterator { #include # define SEH_TRY __try { \ - assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); TESTONLY(pWal->nSehTry++); + assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \ + TESTONLY(pWal->nSehTry++); -# define SEH_EXCEPT(X) TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); \ +# define SEH_EXCEPT(X) \ + TESTONLY(pWal->nSehTry--); \ + assert( pWal->nSehTry==0 ); \ } __except( sehExceptionFilter(pWal, GetExceptionCode()) ){ X } # define SEH_INJECT_FAULT sehInjectFault(pWal) @@ -643,6 +646,12 @@ static int sehExceptionFilter(Wal *pWal, int eCode){ return EXCEPTION_CONTINUE_SEARCH; } +/* +** If one is configured, invoke the xTestCallback callback with 650 as +** the argument. If it returns true, throw the same exception that is +** thrown by the system if the *-shm file mapping is accessed after it +** has been invalidated. +*/ static void sehInjectFault(Wal *pWal){ assert( pWal->nSehTry>0 ); if( sqlite3FaultSim(650) ){ @@ -650,13 +659,27 @@ static void sehInjectFault(Wal *pWal){ } } -#define SEH_FREE_ON_ERROR(X) pWal->pFree = X +/* +** There are two ways to use this macro. To set a pointer to be freed +** if an exception is thrown: +** +** SEH_FREE_ON_ERROR(0, pPtr); +** +** and to cancel the same: +** +** SEH_FREE_ON_ERROR(pPtr, 0); +** +** In the first case, there must not already be a pointer registered to +** be freed. In the second case, pPtr must be the registered pointer. +*/ +#define SEH_FREE_ON_ERROR(X,Y) \ + assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y #else -# define SEH_TRY -# define SEH_EXCEPT(X) -# define SEH_INJECT_FAULT -# define SEH_FREE_ON_ERROR(X) +# define SEH_TRY TESTONLY(pWal->nSehTry++); +# define SEH_EXCEPT(X) TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); +# define SEH_INJECT_FAULT assert( pWal->nSehTry>0 ); +# define SEH_FREE_ON_ERROR(X,Y) #endif /* ifdef SQLITE_USE_SEH */ @@ -1369,7 +1392,7 @@ static int walIndexRecover(Wal *pWal){ /* Malloc a buffer to read frames into. */ szFrame = szPage + WAL_FRAME_HDRSIZE; aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); - SEH_FREE_ON_ERROR(aFrame); + SEH_FREE_ON_ERROR(0, aFrame); if( !aFrame ){ rc = SQLITE_NOMEM_BKPT; goto recovery_error; @@ -1447,8 +1470,8 @@ static int walIndexRecover(Wal *pWal){ if( iFrame<=iLast ) break; } + SEH_FREE_ON_ERROR(aFrame, 0); sqlite3_free(aFrame); - SEH_FREE_ON_ERROR(0); } finished: @@ -1867,7 +1890,7 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ memset(p, 0, nByte); p->nSegment = nSegment; aTmp = (ht_slot*)&(((u8*)p)[nByte]); - SEH_FREE_ON_ERROR(p); + SEH_FREE_ON_ERROR(0, p); for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && ipFree==(void*)pIter ); - pWal->pFree = 0; -#endif + SEH_FREE_ON_ERROR(pIter, 0); walIteratorFree(pIter); return rc; } @@ -2306,9 +2326,7 @@ int sqlite3WalClose( if( pWal ){ int isDelete = 0; /* True to unlink wal and wal-index files */ -#ifdef SQLITE_USE_SEH - assert( pWal->lockMask==0 ); -#endif + assert( walAssertLockmask(pWal) ); /* If an EXCLUSIVE lock can be obtained on the database file (using the ** ordinary, rollback-mode locking methods, this guarantees that the @@ -3020,6 +3038,13 @@ static int walHandleException(Wal *pWal){ return SQLITE_IOERR; } +/* +** Assert that the Wal.lockMask mask, which indicates the locks held +** by the connenction, is consistent with the Wal.readLock, Wal.writeLock +** and Wal.ckptLock variables. To be used as: +** +** assert( walAssertLockmask(pWal) ); +*/ static int walAssertLockmask(Wal *pWal){ if( pWal->exclusiveMode==0 ){ static const int S = 1; @@ -3134,18 +3159,8 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ #endif /* SQLITE_ENABLE_SNAPSHOT */ /* -** Begin a read transaction on the database. -** -** This routine used to be called sqlite3OpenSnapshot() and with good reason: -** it takes a snapshot of the state of the WAL and wal-index for the current -** instant in time. The current thread will continue to use this snapshot. -** Other threads might append new content to the WAL and wal-index but -** that extra content is ignored by the current thread. -** -** If the database contents have changes since the previous read -** transaction, then *pChanged is set to 1 before returning. The -** Pager layer will use this to know that its cache is stale and -** needs to be flushed. +** This function does the work of sqlite3WalBeginReadTransaction() (see +** below). That function simply calls this one inside an SEH_TRY{...} block. */ static int walBeginReadTransaction(Wal *pWal, int *pChanged){ int rc; /* Return code */ @@ -3157,6 +3172,7 @@ static int walBeginReadTransaction(Wal *pWal, int *pChanged){ #endif assert( pWal->ckptLock==0 ); + assert( pWal->nSehTry>0 ); #ifdef SQLITE_ENABLE_SNAPSHOT if( pSnapshot ){ @@ -3251,6 +3267,20 @@ static int walBeginReadTransaction(Wal *pWal, int *pChanged){ return rc; } +/* +** Begin a read transaction on the database. +** +** This routine used to be called sqlite3OpenSnapshot() and with good reason: +** it takes a snapshot of the state of the WAL and wal-index for the current +** instant in time. The current thread will continue to use this snapshot. +** Other threads might append new content to the WAL and wal-index but +** that extra content is ignored by the current thread. +** +** If the database contents have changes since the previous read +** transaction, then *pChanged is set to 1 before returning. The +** Pager layer will use this to know that its cache is stale and +** needs to be flushed. +*/ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ int rc; SEH_TRY { @@ -3380,6 +3410,17 @@ static int walFindFrame( return SQLITE_OK; } +/* +** Search the wal file for page pgno. If found, set *piRead to the frame that +** contains the page. Otherwise, if pgno is not in the wal file, set *piRead +** to zero. +** +** Return SQLITE_OK if successful, or an error code if an error occurs. If an +** error does occur, the final value of *piRead is undefined. +** +** The difference between this function and walFindFrame() is that this +** function wraps walFindFrame() in an SEH_TRY{...} block. +*/ int sqlite3WalFindFrame( Wal *pWal, /* WAL handle */ Pgno pgno, /* Database page number to read data for */ @@ -4002,6 +4043,13 @@ static int walFrames( return rc; } +/* +** Write a set of frames to the log. The caller must hold the write-lock +** on the log file (obtained using sqlite3WalBeginWriteTransaction()). +** +** The difference between this function and walFrames() is that this +** function wraps walFrames() in an SEH_TRY{...} block. +*/ int sqlite3WalFrames( Wal *pWal, /* Wal handle to write to */ int szPage, /* Database page-size in bytes */ From 5b6c3c8f7d27226a0386867c1c110f79435d9ba0 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 20 Aug 2021 17:23:19 +0000 Subject: [PATCH 05/15] Add missing SEH_INJECT_FAULT macros. FossilOrigin-Name: 27e9bdb3a90a5826f45d32e0378e9afa90a16ac762a75236f38218f41bc45ded --- manifest | 12 ++--- manifest.uuid | 2 +- src/wal.c | 143 ++++++++++++++++++++++++++------------------------ 3 files changed, 82 insertions(+), 75 deletions(-) diff --git a/manifest b/manifest index d417bb139e..18648cc431 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssome\sassert()\sstatements\sand\sfix\ssmall\sissues\swith\scode\son\sthis\sbranch. -D 2021-08-20T16:19:19.544 +C Add\smissing\sSEH_INJECT_FAULT\smacros. +D 2021-08-20T17:23:19.198 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c d47742fa0d58fa622416cfd105b4b309f39006f30d903e02db2f48236f3d83d7 +F src/wal.c 5f98987c924f3262e19bc1c124cc4e02553f768a86cfdfb4d193db04c4d0b3da F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,7 +1921,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 5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa -R eab33be79c818813f4366ae19768ee1d +P bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45 +R 18bce27bc9709a49e95cb84782c68c82 U dan -Z 8887602c0a0185b63b60ad6538fd96e1 +Z 8c053f205f09cec18507fce552900c67 diff --git a/manifest.uuid b/manifest.uuid index 4034ae736f..f413569b7c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45 \ No newline at end of file +27e9bdb3a90a5826f45d32e0378e9afa90a16ac762a75236f38218f41bc45ded \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index f6c2d86df8..ef50aac040 100644 --- a/src/wal.c +++ b/src/wal.c @@ -1133,6 +1133,7 @@ static int walFramePage(u32 iFrame){ */ static u32 walFramePgno(Wal *pWal, u32 iFrame){ int iHash = walFramePage(iFrame); + SEH_INJECT_FAULT; if( iHash==0 ){ return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; } @@ -1228,7 +1229,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ idx = iFrame - sLoc.iZero; assert( idx <= HASHTABLE_NSLOT/2 + 1 ); - + /* If this is the first entry to be added to this hash-table, zero the ** entire hash table and aPgno[] array before proceeding. */ @@ -1467,6 +1468,7 @@ static int walIndexRecover(Wal *pWal){ } } #endif + SEH_INJECT_FAULT; if( iFrame<=iLast ) break; } @@ -1498,6 +1500,7 @@ finished: }else{ pInfo->aReadMark[i] = READMARK_NOT_USED; } + SEH_INJECT_FAULT; walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); }else if( rc!=SQLITE_BUSY ){ goto recovery_error; @@ -2154,7 +2157,7 @@ static int walCheckpoint( rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); if( rc==SQLITE_OK ){ u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED); - AtomicStore(pInfo->aReadMark+i, iMark); + AtomicStore(pInfo->aReadMark+i, iMark); SEH_INJECT_FAULT; walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); }else if( rc==SQLITE_BUSY ){ mxSafeFrame = y; @@ -2206,6 +2209,7 @@ static int walCheckpoint( while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ i64 iOffset; assert( walFramePgno(pWal, iFrame)==iDbpage ); + SEH_INJECT_FAULT; if( AtomicLoad(&db->u1.isInterrupted) ){ rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; break; @@ -2235,7 +2239,7 @@ static int walCheckpoint( } } if( rc==SQLITE_OK ){ - AtomicStore(&pInfo->nBackfill, mxSafeFrame); + AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT; } } @@ -2312,6 +2316,73 @@ static void walLimitSize(Wal *pWal, i64 nMax){ } } +#ifdef SQLITE_USE_SEH +/* +** This is the "standard" exception handler used in a few places to handle +** an exception thrown by reading from the *-shm mapping after it has become +** invalid in SQLITE_USE_SEH builds. It is used as follows: +** +** SEH_TRY { ... } +** SEH_EXCEPT( rc = walHandleException(pWal); ) +** +** This function does three things: +** +** 1) Determines the locks that should be held, based on the contents of +** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other +** held locks are assumed to be transient locks that would have been +** released had the exception not been thrown and are dropped. +** +** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free(). +** +** 3) Returns SQLITE_IOERR. +*/ +static int walHandleException(Wal *pWal){ + if( pWal->exclusiveMode==0 ){ + static const int S = 1; + static const int E = (1<lockMask & ~( + (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) + ); + for(ii=0; iipFree); + pWal->pFree = 0; + return SQLITE_IOERR; +} + +/* +** Assert that the Wal.lockMask mask, which indicates the locks held +** by the connenction, is consistent with the Wal.readLock, Wal.writeLock +** and Wal.ckptLock variables. To be used as: +** +** assert( walAssertLockmask(pWal) ); +*/ +static int walAssertLockmask(Wal *pWal){ + if( pWal->exclusiveMode==0 ){ + static const int S = 1; + static const int E = (1<readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) +#ifdef SQLITE_ENABLE_SNAPSHOT + | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0) +#endif + ); + assert( mExpect==pWal->lockMask ); + } + return 1; +} +#else +# define walAssertLockmask(x) 1 +#endif /* ifdef SQLITE_USE_SEH */ + /* ** Close a connection to a log file. */ @@ -2998,71 +3069,6 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ return rc; } -#ifdef SQLITE_USE_SEH -/* -** This is the "standard" exception handler used in a few places to handle -** an exception thrown by reading from the *-shm mapping after it has become -** invalid in SQLITE_USE_SEH builds. It is used as follows: -** -** SEH_TRY { ... } -** SEH_EXCEPT( rc = walHandleException(pWal); ) -** -** This function does three things: -** -** 1) Determines the locks that should be held, based on the contents of -** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other -** held locks are assumed to be transient locks that would have been -** released had the exception not been thrown and are dropped. -** -** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free(). -** -** 3) Returns SQLITE_IOERR. -*/ -static int walHandleException(Wal *pWal){ - if( pWal->exclusiveMode==0 ){ - static const int S = 1; - static const int E = (1<lockMask & ~( - (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) - | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) - | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) - ); - for(ii=0; iipFree); - pWal->pFree = 0; - return SQLITE_IOERR; -} - -/* -** Assert that the Wal.lockMask mask, which indicates the locks held -** by the connenction, is consistent with the Wal.readLock, Wal.writeLock -** and Wal.ckptLock variables. To be used as: -** -** assert( walAssertLockmask(pWal) ); -*/ -static int walAssertLockmask(Wal *pWal){ - if( pWal->exclusiveMode==0 ){ - static const int S = 1; - static const int E = (1<readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) - | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) - | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) -#ifdef SQLITE_ENABLE_SNAPSHOT - | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0) -#endif - ); - assert( mExpect==pWal->lockMask ); - } - return 1; -} -#endif - #ifdef SQLITE_ENABLE_SNAPSHOT /* ** This function does the work of sqlite3WalSnapshotRecover(). @@ -4167,6 +4173,7 @@ int sqlite3WalCheckpoint( /* If no error occurred, set the output variables. */ if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; + SEH_INJECT_FAULT; if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); } } From 67ae593ffecb046d94882fdadcb1f174e91631a5 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 20 Aug 2021 18:18:12 +0000 Subject: [PATCH 06/15] Use VVA_ONLY() instead of TESTONLY() in SEH macros so that the build works for coverage testing. FossilOrigin-Name: 9e9d5b566da72adf780685ea27da7d76a7274e904a533438255af92875c94503 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/wal.c | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 18648cc431..0ba922e1f6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\smissing\sSEH_INJECT_FAULT\smacros. -D 2021-08-20T17:23:19.198 +C Use\sVVA_ONLY()\sinstead\sof\sTESTONLY()\sin\sSEH\smacros\sso\sthat\sthe\sbuild\nworks\sfor\scoverage\stesting. +D 2021-08-20T18:18:12.982 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 5f98987c924f3262e19bc1c124cc4e02553f768a86cfdfb4d193db04c4d0b3da +F src/wal.c 2000742eae6204d2e6dff721eabf7905171af22bb99e3760670188f8a18d66f4 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,7 +1921,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 bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45 -R 18bce27bc9709a49e95cb84782c68c82 -U dan -Z 8c053f205f09cec18507fce552900c67 +P 27e9bdb3a90a5826f45d32e0378e9afa90a16ac762a75236f38218f41bc45ded +R 66057be76f6babcd4edb6b4970a8bed6 +U drh +Z 72862037c4132917dc5cd800ca04f4aa diff --git a/manifest.uuid b/manifest.uuid index f413569b7c..e50bfb0721 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -27e9bdb3a90a5826f45d32e0378e9afa90a16ac762a75236f38218f41bc45ded \ No newline at end of file +9e9d5b566da72adf780685ea27da7d76a7274e904a533438255af92875c94503 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index ef50aac040..d32e639735 100644 --- a/src/wal.c +++ b/src/wal.c @@ -623,10 +623,10 @@ struct WalIterator { # define SEH_TRY __try { \ assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \ - TESTONLY(pWal->nSehTry++); + VVA_ONLY(pWal->nSehTry++); # define SEH_EXCEPT(X) \ - TESTONLY(pWal->nSehTry--); \ + VVA_ONLY(pWal->nSehTry--); \ assert( pWal->nSehTry==0 ); \ } __except( sehExceptionFilter(pWal, GetExceptionCode()) ){ X } @@ -639,7 +639,7 @@ struct WalIterator { ** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise. */ static int sehExceptionFilter(Wal *pWal, int eCode){ - TESTONLY(pWal->nSehTry--); + VVA_ONLY(pWal->nSehTry--); if( eCode==EXCEPTION_ACCESS_VIOLATION ){ return EXCEPTION_EXECUTE_HANDLER; } @@ -676,8 +676,8 @@ static void sehInjectFault(Wal *pWal){ assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y #else -# define SEH_TRY TESTONLY(pWal->nSehTry++); -# define SEH_EXCEPT(X) TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); +# define SEH_TRY VVA_ONLY(pWal->nSehTry++); +# define SEH_EXCEPT(X) VVA_ONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); # define SEH_INJECT_FAULT assert( pWal->nSehTry>0 ); # define SEH_FREE_ON_ERROR(X,Y) #endif /* ifdef SQLITE_USE_SEH */ From 101a6b87c79f83dcc08cd513f3fc30bbe808962c Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 21 Aug 2021 15:49:15 +0000 Subject: [PATCH 07/15] Add test cases to ensure that there is at least one test that causes an exception to be thrown from each SEH_INJECT_FAULT macro. FossilOrigin-Name: e480146f49004c818ad93464289761d8a7246b502bd079f8140d0a6f684ebe4e --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/walseh1.test | 32 +++++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 0ba922e1f6..76b263f2dc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\sVVA_ONLY()\sinstead\sof\sTESTONLY()\sin\sSEH\smacros\sso\sthat\sthe\sbuild\nworks\sfor\scoverage\stesting. -D 2021-08-20T18:18:12.982 +C Add\stest\scases\sto\sensure\sthat\sthere\sis\sat\sleast\sone\stest\sthat\scauses\san\sexception\sto\sbe\sthrown\sfrom\seach\sSEH_INJECT_FAULT\smacro. +D 2021-08-21T15:49:15.749 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1739,7 +1739,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 -F test/walseh1.test 970946bdd40bc37d1552811b54ec94dd4a5a4178354b4afa129f2053b99bf09f +F test/walseh1.test 7aff09e275a10a4b140f0a34c9da55de2d3747582590f16b638831e1dd7396b2 F test/walsetlk.test 3185bebc90557e0d611442c8d64f7a0cb7b06f8e156eea37a4a7358f722715be F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f @@ -1921,7 +1921,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 27e9bdb3a90a5826f45d32e0378e9afa90a16ac762a75236f38218f41bc45ded -R 66057be76f6babcd4edb6b4970a8bed6 -U drh -Z 72862037c4132917dc5cd800ca04f4aa +P 9e9d5b566da72adf780685ea27da7d76a7274e904a533438255af92875c94503 +R 1ec6de0718c621705d76375df7f5b74b +U dan +Z 1df868f8b39d7326ed3c02e05075825f diff --git a/manifest.uuid b/manifest.uuid index e50bfb0721..d330c3b47b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9e9d5b566da72adf780685ea27da7d76a7274e904a533438255af92875c94503 \ No newline at end of file +e480146f49004c818ad93464289761d8a7246b502bd079f8140d0a6f684ebe4e \ No newline at end of file diff --git a/test/walseh1.test b/test/walseh1.test index ba5d786c48..b5b22d2a82 100644 --- a/test/walseh1.test +++ b/test/walseh1.test @@ -13,7 +13,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl -set testprefix seh1 +set testprefix walseh1 set ::seh_countdown 0 proc seh_faultsim_callback {iFault} { @@ -101,6 +101,36 @@ do_faultsim_test 4 -faults seh -prep { } catch { db close } +do_faultsim_test 5 -faults seh -prep { + catch { db close } + faultsim_restore_and_reopen + execsql { + PRAGMA cache_size = 5; + BEGIN; + WITH s(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50 + ) + INSERT INTO t1 SELECT randomblob(500), randomblob(500) FROM s; + } +} -body { + execsql ROLLBACK +} -test { + faultsim_test_result {0 {}} +} +catch { db close } + +do_faultsim_test 6 -faults seh -prep { + catch { db close } + faultsim_restore_and_reopen +} -body { + execsql { PRAGMA wal_checkpoint = TRUNCATE } + execsql { INSERT INTO t1 VALUES(7, 8) } + execsql { SELECT * FROM t1 } +} -test { + faultsim_test_result {0 {1 2 3 4 7 8}} +} +catch { db close } + finish_test From ee7c667a364035db0ca9ced959b918e6ed40d7bf Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 26 Aug 2021 21:12:07 +0000 Subject: [PATCH 08/15] Change the structuree exception handler in wal.c to catch EXCEPTION_IN_PAGE_ERROR instead of EXCEPTION_ACCESS_VIOLATION. FossilOrigin-Name: 0c6ab539cfbc908550fa993a587e85d644b6335853ff9781caae860c461c045d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/wal.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 76b263f2dc..7b07305bc4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stest\scases\sto\sensure\sthat\sthere\sis\sat\sleast\sone\stest\sthat\scauses\san\sexception\sto\sbe\sthrown\sfrom\seach\sSEH_INJECT_FAULT\smacro. -D 2021-08-21T15:49:15.749 +C Change\sthe\sstructuree\sexception\shandler\sin\swal.c\sto\scatch\sEXCEPTION_IN_PAGE_ERROR\sinstead\sof\sEXCEPTION_ACCESS_VIOLATION. +D 2021-08-26T21:12:07.088 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 2000742eae6204d2e6dff721eabf7905171af22bb99e3760670188f8a18d66f4 +F src/wal.c 75bcffce59a3108ad3e24c186977821ffe5083ab2044ff477a5bbc4a9e8a5455 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,7 +1921,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 9e9d5b566da72adf780685ea27da7d76a7274e904a533438255af92875c94503 -R 1ec6de0718c621705d76375df7f5b74b +P e480146f49004c818ad93464289761d8a7246b502bd079f8140d0a6f684ebe4e +R e565d7a955f7dfbceec6b3e9d7245e4b U dan -Z 1df868f8b39d7326ed3c02e05075825f +Z 2c7b74af84f6da4d9875b4b1565fc82a diff --git a/manifest.uuid b/manifest.uuid index d330c3b47b..4b4b64c0bd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e480146f49004c818ad93464289761d8a7246b502bd079f8140d0a6f684ebe4e \ No newline at end of file +0c6ab539cfbc908550fa993a587e85d644b6335853ff9781caae860c461c045d \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index d32e639735..f832e1b017 100644 --- a/src/wal.c +++ b/src/wal.c @@ -640,7 +640,7 @@ struct WalIterator { */ static int sehExceptionFilter(Wal *pWal, int eCode){ VVA_ONLY(pWal->nSehTry--); - if( eCode==EXCEPTION_ACCESS_VIOLATION ){ + if( eCode==EXCEPTION_IN_PAGE_ERROR ){ return EXCEPTION_EXECUTE_HANDLER; } return EXCEPTION_CONTINUE_SEARCH; @@ -655,7 +655,7 @@ static int sehExceptionFilter(Wal *pWal, int eCode){ static void sehInjectFault(Wal *pWal){ assert( pWal->nSehTry>0 ); if( sqlite3FaultSim(650) ){ - RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, NULL); + RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 0, NULL); } } From 9023444fea771dd0b38bf92efa1751e02b0e89d0 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 10 Sep 2021 21:28:56 +0000 Subject: [PATCH 09/15] If an EXCEPTION_IN_PAGE_ERROR exception is caught, make the underlying OS error code available via sqlite3_system_errno(). FossilOrigin-Name: fdb20e9ee48465b94aa6ac3c5e263ecaa7c3b10f4a193e79f965b7c35944b08b --- manifest | 24 +++++++++++------------ manifest.uuid | 2 +- src/pager.c | 6 ++++++ src/pager.h | 4 ++++ src/sqlite.h.in | 1 + src/util.c | 17 ++++++++++++++++ src/wal.c | 49 +++++++++++++++++++++++++++++++++++------------ src/wal.h | 4 ++++ test/walseh1.test | 13 ++++++++++++- 9 files changed, 94 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index 7b07305bc4..a0bc1c1835 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sstructuree\sexception\shandler\sin\swal.c\sto\scatch\sEXCEPTION_IN_PAGE_ERROR\sinstead\sof\sEXCEPTION_ACCESS_VIOLATION. -D 2021-08-26T21:12:07.088 +C If\san\sEXCEPTION_IN_PAGE_ERROR\sexception\sis\scaught,\smake\sthe\sunderlying\sOS\serror\scode\savailable\svia\ssqlite3_system_errno(). +D 2021-09-10T21:28:56.797 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -531,8 +531,8 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c b11e4610769922253dec27d7af4a07ff84f65169d19bda5e9b12a152a706f7f5 F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 95c255256b13827caf038c8f963d334784073f38ab6ef9d70371d9d04f3c43e0 -F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f +F src/pager.c 555cff0be2d255827dbc93761c0265d077faf34f31b65ccf16d76d053dfd0467 +F src/pager.h 53b3ba002dbc7568608489f67c249224102d10f372c098a1a9dd58308bc76d3c F src/parse.y 0ba0baec5de6921ec8ba8bbcf1018969144ef29d26112e17539d8fbb1662e3eb F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 @@ -546,7 +546,7 @@ F src/resolve.c 42b94d37a54200707a95566eff4f7e8a380e32d080016b699f23bd79a73a5028 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 0577308f097363b6ebac223e210418810acf74e677f580597f7d0718476fe3ef F src/shell.c.in f795a4ae3c35631f5edcfa754c7824ff1d8a75b23a07e22e664b50f82e826346 -F src/sqlite.h.in 43fcf0fe2af04081f420a906fc020bde1243851ba44b0aa567a27f94bf8c3145 +F src/sqlite.h.in 79d8c9a7e9886851243183e4b610022d87e6dd73bf2e1218d3105ab4577af9a0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510 F src/sqliteInt.h a65ddfb177549c82dcd1374a2f23260328eb65ced55b50843419386177e159be @@ -614,7 +614,7 @@ F src/trigger.c 3f612ce5f0858b6c23460a3c799d01f408b49b0b29d931d8b8e6fc224a8667de F src/update.c 69c4c10bc6873a80c0a77cb578f9fc60ee90003d03f9530bc3370fa24615772d F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 -F src/util.c eafc8cfeb66fdbf8839922d13019b7882f242ac31b383e3451aab7744c54df3e +F src/util.c a14724ed2a504488c34bd3a510ae33e46be00d0b80296651aba3a3d36303e460 F src/vacuum.c 454973a59fb20bb982efc2df568a098616db6328a0491b6e84e2e07f7333db45 F src/vdbe.c e5cdac52d7163c032ae3c54f1cff9391acd23ba79cea0d5a9524c00cc0a856e8 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe @@ -628,8 +628,8 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 75bcffce59a3108ad3e24c186977821ffe5083ab2044ff477a5bbc4a9e8a5455 -F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a +F src/wal.c 8cc813d34b345728987b78bcb0a02f7b6e4734031eea1feb1b6d1d0e56ac5a21 +F src/wal.h 04a9e53121d5076f2a173b0f2facb39d33047093fee71bd3bbe6b1f6f1f5fd4b F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b @@ -1739,7 +1739,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 -F test/walseh1.test 7aff09e275a10a4b140f0a34c9da55de2d3747582590f16b638831e1dd7396b2 +F test/walseh1.test 5a94409fb1a7029070040286336fef5ce61315121123e25cfb7e0622b017e59d F test/walsetlk.test 3185bebc90557e0d611442c8d64f7a0cb7b06f8e156eea37a4a7358f722715be F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f @@ -1921,7 +1921,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 e480146f49004c818ad93464289761d8a7246b502bd079f8140d0a6f684ebe4e -R e565d7a955f7dfbceec6b3e9d7245e4b +P 0c6ab539cfbc908550fa993a587e85d644b6335853ff9781caae860c461c045d +R 33294cd0e1de3328b05fc8fdf4f59e56 U dan -Z 2c7b74af84f6da4d9875b4b1565fc82a +Z ff4d8e1dd5c81ec2fdd90cee5190a162 diff --git a/manifest.uuid b/manifest.uuid index 4b4b64c0bd..e5d92301b8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0c6ab539cfbc908550fa993a587e85d644b6335853ff9781caae860c461c045d \ No newline at end of file +fdb20e9ee48465b94aa6ac3c5e263ecaa7c3b10f4a193e79f965b7c35944b08b \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 12a78cde80..31bcb32a04 100644 --- a/src/pager.c +++ b/src/pager.c @@ -7706,4 +7706,10 @@ int sqlite3PagerWalFramesize(Pager *pPager){ } #endif +#ifdef SQLITE_USE_SEH +int sqlite3PagerWalSystemErrno(Pager *pPager){ + return sqlite3WalSystemErrno(pPager->pWal); +} +#endif + #endif /* SQLITE_OMIT_DISKIO */ diff --git a/src/pager.h b/src/pager.h index 8d899bd1a6..dde845a023 100644 --- a/src/pager.h +++ b/src/pager.h @@ -239,4 +239,8 @@ void sqlite3PagerRekey(DbPage*, Pgno, u16); # define enable_simulated_io_errors() #endif +#ifdef SQLITE_USE_SEH +int sqlite3PagerWalSystemErrno(Pager*); +#endif + #endif /* SQLITE_PAGER_H */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index e4ea66a725..6a2cc53c66 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -528,6 +528,7 @@ int sqlite3_exec( #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) +#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) diff --git a/src/util.c b/src/util.c index 2d1c64ad13..3eb0419b66 100644 --- a/src/util.c +++ b/src/util.c @@ -136,6 +136,23 @@ void sqlite3ErrorClear(sqlite3 *db){ */ void sqlite3SystemError(sqlite3 *db, int rc){ if( rc==SQLITE_IOERR_NOMEM ) return; +#ifdef SQLITE_USE_SEH + if( rc==SQLITE_IOERR_IN_PAGE ){ + int ii; + int iErr; + sqlite3BtreeEnterAll(db); + for(ii=0; iinDb; ii++){ + if( db->aDb[ii].pBt ){ + iErr = sqlite3PagerWalSystemErrno(sqlite3BtreePager(db->aDb[ii].pBt)); + if( iErr ){ + db->iSysErrno = iErr; + } + } + } + sqlite3BtreeLeaveAll(db); + return; + } +#endif rc &= 0xff; if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){ db->iSysErrno = sqlite3OsGetLastError(db->pVfs); diff --git a/src/wal.c b/src/wal.c index f832e1b017..78ef82145c 100644 --- a/src/wal.c +++ b/src/wal.c @@ -534,6 +534,7 @@ struct Wal { #ifdef SQLITE_USE_SEH u32 lockMask; /* Mask of locks held */ void *pFree; /* Pointer to sqlite3_free() if exception thrown */ + int iSysErrno; /* System error code following exception */ #endif #ifdef SQLITE_DEBUG u8 lockError; /* True if a locking error has occurred */ @@ -628,7 +629,7 @@ struct WalIterator { # define SEH_EXCEPT(X) \ VVA_ONLY(pWal->nSehTry--); \ assert( pWal->nSehTry==0 ); \ - } __except( sehExceptionFilter(pWal, GetExceptionCode()) ){ X } + } __except( sehExceptionFilter(pWal, GetExceptionCode(), GetExceptionInformation() ) ){ X } # define SEH_INJECT_FAULT sehInjectFault(pWal) @@ -638,9 +639,12 @@ struct WalIterator { ** indicates that the exception may have been caused by accessing the *-shm ** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise. */ -static int sehExceptionFilter(Wal *pWal, int eCode){ +static int sehExceptionFilter(Wal *pWal, int eCode, EXCEPTION_POINTERS *p){ VVA_ONLY(pWal->nSehTry--); if( eCode==EXCEPTION_IN_PAGE_ERROR ){ + if( p && p->ExceptionRecord && p->ExceptionRecord->NumberParameters>=3 ){ + pWal->iSysErrno = (int)p->ExceptionRecord->ExceptionInformation[2]; + } return EXCEPTION_EXECUTE_HANDLER; } return EXCEPTION_CONTINUE_SEARCH; @@ -653,10 +657,17 @@ static int sehExceptionFilter(Wal *pWal, int eCode){ ** has been invalidated. */ static void sehInjectFault(Wal *pWal){ - assert( pWal->nSehTry>0 ); - if( sqlite3FaultSim(650) ){ - RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 0, NULL); - } + int res; + assert( pWal->nSehTry>0 ); + + res = sqlite3FaultSim(650); + if( res!=0 ){ + ULONG aArg[3]; + aArg[0] = 0; + aArg[1] = 0; + aArg[2] = (ULONG)res; + RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, aArg); + } } /* @@ -2353,7 +2364,7 @@ static int walHandleException(Wal *pWal){ } sqlite3_free(pWal->pFree); pWal->pFree = 0; - return SQLITE_IOERR; + return SQLITE_IOERR_IN_PAGE; } /* @@ -2379,6 +2390,20 @@ static int walAssertLockmask(Wal *pWal){ } return 1; } + +/* +** Return and zero the "system error" field set when an +** EXCEPTION_IN_PAGE_ERROR exception is caught. +*/ +int sqlite3WalSystemErrno(Wal *pWal){ + int iRet = 0; + if( pWal ){ + iRet = pWal->iSysErrno; + pWal->iSysErrno = 0; + } + return iRet; +} + #else # define walAssertLockmask(x) 1 #endif /* ifdef SQLITE_USE_SEH */ @@ -3151,7 +3176,7 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ SEH_TRY { rc = walSnapshotRecover(pWal, pBuf1, pBuf2); } - SEH_EXCEPT( rc = SQLITE_IOERR; ) + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) pWal->ckptLock = 0; } @@ -3436,7 +3461,7 @@ int sqlite3WalFindFrame( SEH_TRY { rc = walFindFrame(pWal, pgno, piRead); } - SEH_EXCEPT( rc = SQLITE_IOERR; ) + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) return rc; } @@ -3526,7 +3551,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){ rc = SQLITE_BUSY_SNAPSHOT; } } - SEH_EXCEPT( rc = SQLITE_IOERR; ) + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) if( rc!=SQLITE_OK ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); @@ -3593,7 +3618,7 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ } if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } - SEH_EXCEPT( rc = SQLITE_IOERR; ) + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) } return rc; } @@ -3640,7 +3665,7 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ SEH_TRY { walCleanupHash(pWal); } - SEH_EXCEPT( rc = SQLITE_IOERR; ) + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) } return rc; diff --git a/src/wal.h b/src/wal.h index 02e2bab360..d39bb50f3d 100644 --- a/src/wal.h +++ b/src/wal.h @@ -151,5 +151,9 @@ int sqlite3WalWriteLock(Wal *pWal, int bLock); void sqlite3WalDb(Wal *pWal, sqlite3 *db); #endif +#ifdef SQLITE_USE_SEH +int sqlite3WalSystemErrno(Wal*); +#endif + #endif /* ifndef SQLITE_OMIT_WAL */ #endif /* SQLITE_WAL_H */ diff --git a/test/walseh1.test b/test/walseh1.test index b5b22d2a82..62fb9a47a8 100644 --- a/test/walseh1.test +++ b/test/walseh1.test @@ -16,10 +16,11 @@ source $testdir/malloc_common.tcl set testprefix walseh1 set ::seh_countdown 0 +set ::seh_errno 10 proc seh_faultsim_callback {iFault} { if {$iFault==650} { incr ::seh_countdown -1 - if {$::seh_countdown==0} { return 1 } + if {$::seh_countdown==0} { return $::seh_errno } } return 0 } @@ -31,6 +32,7 @@ proc seh_injectuninstall {} { sqlite3_test_control_fault_install } proc seh_injectstart {iFail} { + set ::seh_errno [expr 2+$iFail*10] set ::seh_countdown $iFail } proc seh_injectstop {} { @@ -47,6 +49,13 @@ set FAULTSIM(seh) [list \ -injectuninstall seh_injectuninstall \ ] +proc test_system_errno {db expect} { + set serrno [sqlite3_system_errno $db] + if {$serrno!=$expect} { + error "surprising system_errno. Expected $expect, got $serrno" + } +} + do_execsql_test 1.0 { PRAGMA journal_mode = wal; CREATE TABLE t1(x, y); @@ -64,6 +73,7 @@ do_faultsim_test 1 -faults seh -prep { execsql { SELECT * FROM t1 } db2 } -test { faultsim_test_result {0 {1 2 3 4}} + if {$testrc} { test_system_errno db2 $::seh_errno } } catch { db2 close } @@ -76,6 +86,7 @@ do_faultsim_test 2 -faults seh -prep { execsql { SELECT * FROM t1 } } -test { faultsim_test_result {0 {1 2 3 4}} + if {$testrc} { test_system_errno db $::seh_errno } } do_faultsim_test 3 -faults seh -prep { From 51f0c762f0dad1126568d08f85a71113858c35b1 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 11 Sep 2021 14:33:05 +0000 Subject: [PATCH 10/15] Fix a case where the system error was not being set correctly. FossilOrigin-Name: 13a524b351a0812214b223aa4e0a9d778ae7a75cf9875da1147a09c5cb76b9fe --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbeaux.c | 1 + test/walseh1.test | 5 ++++- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index a0bc1c1835..bef88c5593 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\san\sEXCEPTION_IN_PAGE_ERROR\sexception\sis\scaught,\smake\sthe\sunderlying\sOS\serror\scode\savailable\svia\ssqlite3_system_errno(). -D 2021-09-10T21:28:56.797 +C Fix\sa\scase\swhere\sthe\ssystem\serror\swas\snot\sbeing\sset\scorrectly. +D 2021-09-11T14:33:05.275 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -620,7 +620,7 @@ F src/vdbe.c e5cdac52d7163c032ae3c54f1cff9391acd23ba79cea0d5a9524c00cc0a856e8 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h 38206c8dd6b60ff03d9fd4f626b1b4fd0eef7cdc44f2fc2c1973b0f932a3f26b F src/vdbeapi.c aa5aaf2c37676b83af5724c6cd8207a3064ed46a217fd180957f75ac84f7a2a5 -F src/vdbeaux.c 2368a8888f17368d4040a05966f7d2a2276cac4eeeba50793828186d999e3c8f +F src/vdbeaux.c 258c4ea5afea94b0d21aa9f46015769de7d7c9cf41b9d94672de74a6f4a3a241 F src/vdbeblob.c 60a7694760e35b2bba166cf49eb6a1eb0b31581102b49de78008ca3032406065 F src/vdbemem.c 53881aa0a7845922a075b3f375695588618098871a7a4120af4c297b80fa3e64 F src/vdbesort.c cd5130f683706c1a43e165a74187745fb3351cb56052cf9dc91de820634bbde2 @@ -1739,7 +1739,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 -F test/walseh1.test 5a94409fb1a7029070040286336fef5ce61315121123e25cfb7e0622b017e59d +F test/walseh1.test 82da37763b0d87942dccd191e58321532ce3d44b87ef36e04ff9ce13f382bbae F test/walsetlk.test 3185bebc90557e0d611442c8d64f7a0cb7b06f8e156eea37a4a7358f722715be F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f @@ -1921,7 +1921,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 0c6ab539cfbc908550fa993a587e85d644b6335853ff9781caae860c461c045d -R 33294cd0e1de3328b05fc8fdf4f59e56 +P fdb20e9ee48465b94aa6ac3c5e263ecaa7c3b10f4a193e79f965b7c35944b08b +R 19613aef7c9a0f6d6a0d415bcd0e8fe9 U dan -Z ff4d8e1dd5c81ec2fdd90cee5190a162 +Z 115def4376f9950aab2266e8ac285bc1 diff --git a/manifest.uuid b/manifest.uuid index e5d92301b8..1f797882d8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fdb20e9ee48465b94aa6ac3c5e263ecaa7c3b10f4a193e79f965b7c35944b08b \ No newline at end of file +13a524b351a0812214b223aa4e0a9d778ae7a75cf9875da1147a09c5cb76b9fe \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index c04bd0d379..e93d5cbf46 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3118,6 +3118,7 @@ int sqlite3VdbeHalt(Vdbe *p){ sqlite3VdbeLeave(p); return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ + sqlite3SystemError(db, rc); p->rc = rc; sqlite3RollbackAll(db, SQLITE_OK); p->nChange = 0; diff --git a/test/walseh1.test b/test/walseh1.test index 62fb9a47a8..c3a655f534 100644 --- a/test/walseh1.test +++ b/test/walseh1.test @@ -97,8 +97,8 @@ do_faultsim_test 3 -faults seh -prep { execsql { SELECT * FROM t1 } } -test { faultsim_test_result {0 {1 2 3 4 5 6}} + if {$testrc} { test_system_errno db $::seh_errno } } -catch { db close } do_faultsim_test 4 -faults seh -prep { catch { db close } @@ -109,6 +109,7 @@ do_faultsim_test 4 -faults seh -prep { execsql { SELECT * FROM t1 } } -test { faultsim_test_result {0 {1 2 3 4 7 8}} + if {$testrc} { test_system_errno db $::seh_errno } } catch { db close } @@ -127,6 +128,7 @@ do_faultsim_test 5 -faults seh -prep { execsql ROLLBACK } -test { faultsim_test_result {0 {}} + if {$testrc} { test_system_errno db $::seh_errno } } catch { db close } @@ -139,6 +141,7 @@ do_faultsim_test 6 -faults seh -prep { execsql { SELECT * FROM t1 } } -test { faultsim_test_result {0 {1 2 3 4 7 8}} + if {$testrc} { test_system_errno db $::seh_errno } } catch { db close } From 5d3cc0c09b1f64efd0bebde0ffc85eea571c00dd Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 10 Jul 2023 18:16:49 +0000 Subject: [PATCH 11/15] Fix a warning. Unclear yet if the code is correct this way or not. FossilOrigin-Name: 2df4fd76ef48bb63389df8d783059af6b8f2cbb2c11d07953b408e71f50b625b --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/wal.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 3c7a4ef6e2..1e805163d5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\swal-shm-exceptions\sbranch. -D 2023-07-10T18:05:23.333 +C Fix\sa\swarning.\s\sUnclear\syet\sif\sthe\scode\sis\scorrect\sthis\sway\sor\snot. +D 2023-07-10T18:16:49.671 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -719,7 +719,7 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8 F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c df70125aa233626b8aa56dd6be7cbbe7234e10e01a0610152e583b65eeebc474 +F src/wal.c b4668b94644c79bd9e44ba0aacaeb32631413d1ccee72e67606443a30cc6e56e F src/wal.h 04a9e53121d5076f2a173b0f2facb39d33047093fee71bd3bbe6b1f6f1f5fd4b F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2 F src/where.c 2dc708cf8b6a691fb79f16bbc46567497ee6f991043318d421e294b2da114d93 @@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e59cea2d851be68559e7d01a01cb05684c44d151d022ea9790ce99671016ab00 07d95ed60f0a17ea13b4bc19c2ab2ec9052fedd27c9e1e57a1ec6e3a6470e5b7 -R ccbc614d43527056706e7e54f93af172 +P f655d08d019bab0c578886e91ca24fd956d1b3dea9b9c9104812b3cf62e5e556 +R 7d2a7db7a45657e046a46b76cd581cc4 U drh -Z da656ee3765bdd3f9ae04fb3fd79cf86 +Z 908a871ddbc8b91ee09e4dbf74793fad # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8d0a378f48..1ce8d7c8d6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f655d08d019bab0c578886e91ca24fd956d1b3dea9b9c9104812b3cf62e5e556 \ No newline at end of file +2df4fd76ef48bb63389df8d783059af6b8f2cbb2c11d07953b408e71f50b625b \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 1e1382129b..0cb4f0344a 100644 --- a/src/wal.c +++ b/src/wal.c @@ -666,7 +666,7 @@ static void sehInjectFault(Wal *pWal){ aArg[0] = 0; aArg[1] = 0; aArg[2] = (ULONG)res; - RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG*)aArg); + RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG_PTR*)aArg); } } From 7994d9dab77cfb9adaf01ef04601eb9856fb2f7b Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 10 Jul 2023 19:13:40 +0000 Subject: [PATCH 12/15] Compile for SEH if the USE_SEH=1 option is specified on the nmake command line. FossilOrigin-Name: 0e67a82f6cfe681d4676ac5c92d92e95b9dcc3198df21516bccdde002f5e52ae --- Makefile.msc | 7 +++++++ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index e8efe58296..c250810008 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -402,6 +402,13 @@ EXT_FEATURE_FLAGS = !ENDIF !ENDIF +# Include USE_SEH=1 on the nmake command-line to activate the +# structured exception handling logic. +# +!IF $(USE_SEH)!=0 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH +!ENDIF + ############################################################################### ############################### END OF OPTIONS ################################ ############################################################################### diff --git a/manifest b/manifest index 1e805163d5..81fa654b49 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Fix\sa\swarning.\s\sUnclear\syet\sif\sthe\scode\sis\scorrect\sthis\sway\sor\snot. -D 2023-07-10T18:16:49.671 +C Compile\sfor\sSEH\sif\sthe\sUSE_SEH=1\soption\sis\sspecified\son\sthe\snmake\scommand\sline. +D 2023-07-10T19:13:40.460 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F Makefile.in 0f4cb3955aaff8a40ec3857ba1784bd98b69802e51eff979f874b65713b627b2 F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 -F Makefile.msc 7248d860f71ab164b4cec3c415e6cc1bd9fee860c370d65bd8bb49e9572521e2 +F Makefile.msc 3cd72b65de28d1355dd5bf496c190dc50578b77b0cfe080986abaef3abfb21c8 F README.md c1c4218efcc4071a6e26db2b517fdbc1035696a29b370edd655faddbef02b224 F VERSION c6366dc72582d3144ce87b013cc35fe48d62f6d07d5be0c9716ea33c862144aa F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f655d08d019bab0c578886e91ca24fd956d1b3dea9b9c9104812b3cf62e5e556 -R 7d2a7db7a45657e046a46b76cd581cc4 +P 2df4fd76ef48bb63389df8d783059af6b8f2cbb2c11d07953b408e71f50b625b +R 023694c34457958614951e26d46dca77 U drh -Z 908a871ddbc8b91ee09e4dbf74793fad +Z 96490a1ad3ea195c140b420d8f7d8322 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 1ce8d7c8d6..dabe35bc53 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2df4fd76ef48bb63389df8d783059af6b8f2cbb2c11d07953b408e71f50b625b \ No newline at end of file +0e67a82f6cfe681d4676ac5c92d92e95b9dcc3198df21516bccdde002f5e52ae \ No newline at end of file From c0b6112d04758f95555b6f9aa2a59bc6fd7e1a23 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 10 Jul 2023 19:21:09 +0000 Subject: [PATCH 13/15] Minor style changes to the previous MSVC makefile changes on this branch. FossilOrigin-Name: 4c950872c870a5968fa4cb8840cf60569a66c0e508811ee79992825ec9c02da3 --- Makefile.msc | 21 ++++++++++++++------- autoconf/Makefile.msc | 14 ++++++++++++++ manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index c250810008..6fc4c83390 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -52,6 +52,13 @@ MINIMAL_AMALGAMATION = 0 USE_STDCALL = 0 !ENDIF +# Set this non-0 to use structured exception handling (SEH) for WAL mode +# in the core library. +# +!IFNDEF USE_SEH +USE_SEH = 0 +!ENDIF + # Set this non-0 to have the shell executable link against the core dynamic # link library. # @@ -389,6 +396,13 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1 !ENDIF +# Should structured exception handling (SEH) be enabled for WAL mode in +# the core library? +# +!IF $(USE_SEH)!=0 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH=1 +!ENDIF + # These are the "extended" SQLite compilation options used when compiling for # the Windows 10 platform. # @@ -402,13 +416,6 @@ EXT_FEATURE_FLAGS = !ENDIF !ENDIF -# Include USE_SEH=1 on the nmake command-line to activate the -# structured exception handling logic. -# -!IF $(USE_SEH)!=0 -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH -!ENDIF - ############################################################################### ############################### END OF OPTIONS ################################ ############################################################################### diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index 09daa867ec..24154dd5d8 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -52,6 +52,13 @@ MINIMAL_AMALGAMATION = 0 USE_STDCALL = 0 !ENDIF +# Set this non-0 to use structured exception handling (SEH) for WAL mode +# in the core library. +# +!IFNDEF USE_SEH +USE_SEH = 0 +!ENDIF + # Set this non-0 to have the shell executable link against the core dynamic # link library. # @@ -311,6 +318,13 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1 !ENDIF +# Should structured exception handling (SEH) be enabled for WAL mode in +# the core library? +# +!IF $(USE_SEH)!=0 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH=1 +!ENDIF + # These are the "extended" SQLite compilation options used when compiling for # the Windows 10 platform. # diff --git a/manifest b/manifest index 81fa654b49..983bba5257 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Compile\sfor\sSEH\sif\sthe\sUSE_SEH=1\soption\sis\sspecified\son\sthe\snmake\scommand\sline. -D 2023-07-10T19:13:40.460 +C Minor\sstyle\schanges\sto\sthe\sprevious\sMSVC\smakefile\schanges\son\sthis\sbranch. +D 2023-07-10T19:21:09.466 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F Makefile.in 0f4cb3955aaff8a40ec3857ba1784bd98b69802e51eff979f874b65713b627b2 F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 -F Makefile.msc 3cd72b65de28d1355dd5bf496c190dc50578b77b0cfe080986abaef3abfb21c8 +F Makefile.msc daad4a19e0b3c3c3b79b64d4ddbf75e3f506405e8d3f3f604d6f48b26043c51f F README.md c1c4218efcc4071a6e26db2b517fdbc1035696a29b370edd655faddbef02b224 F VERSION c6366dc72582d3144ce87b013cc35fe48d62f6d07d5be0c9716ea33c862144aa F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -15,7 +15,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8 F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac -F autoconf/Makefile.msc 20366d19fbfc3fceecce95344a2114069eaab4fc22e4f02430da167a1e2ddf04 +F autoconf/Makefile.msc 00f11ce1f7904416fe841c33e7d789defe8c39e1df6b97e93ed2af3b1bbaf9d7 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56 F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277 @@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2df4fd76ef48bb63389df8d783059af6b8f2cbb2c11d07953b408e71f50b625b -R 023694c34457958614951e26d46dca77 -U drh -Z 96490a1ad3ea195c140b420d8f7d8322 +P 0e67a82f6cfe681d4676ac5c92d92e95b9dcc3198df21516bccdde002f5e52ae +R 2485a85a908a05b5fd0644b2f7fd3722 +U mistachkin +Z 5b8cb43f82a279de421ae118ca8d7765 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index dabe35bc53..3f7af51b45 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0e67a82f6cfe681d4676ac5c92d92e95b9dcc3198df21516bccdde002f5e52ae \ No newline at end of file +4c950872c870a5968fa4cb8840cf60569a66c0e508811ee79992825ec9c02da3 \ No newline at end of file From 66422b57f9892262c0d5638a0c5d165658fcee43 Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 11 Jul 2023 15:52:52 +0000 Subject: [PATCH 14/15] Get fault injection for testing working correctly. Other code clean-up. FossilOrigin-Name: ff492277ed00c1f637a5b4ccd6d8193ea22f6781f90073861588a2b7d5c045b7 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/wal.c | 23 +++++++++++++++++------ 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 983bba5257..bd506d9ad1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\sstyle\schanges\sto\sthe\sprevious\sMSVC\smakefile\schanges\son\sthis\sbranch. -D 2023-07-10T19:21:09.466 +C Get\sfault\sinjection\sfor\stesting\sworking\scorrectly.\s\sOther\scode\sclean-up. +D 2023-07-11T15:52:52.116 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -719,7 +719,7 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8 F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c b4668b94644c79bd9e44ba0aacaeb32631413d1ccee72e67606443a30cc6e56e +F src/wal.c e4bfb243cc1f6f89c7fba5dd8872ae38a8c1dcc760c276dbb164edb7290072a6 F src/wal.h 04a9e53121d5076f2a173b0f2facb39d33047093fee71bd3bbe6b1f6f1f5fd4b F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2 F src/where.c 2dc708cf8b6a691fb79f16bbc46567497ee6f991043318d421e294b2da114d93 @@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0e67a82f6cfe681d4676ac5c92d92e95b9dcc3198df21516bccdde002f5e52ae -R 2485a85a908a05b5fd0644b2f7fd3722 -U mistachkin -Z 5b8cb43f82a279de421ae118ca8d7765 +P 4c950872c870a5968fa4cb8840cf60569a66c0e508811ee79992825ec9c02da3 +R 966aa4944515db815a2a3b1d2b09adbd +U drh +Z 4e4c72cb034026cb3cf7caeaeea5ca69 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 3f7af51b45..066d2d9ef2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4c950872c870a5968fa4cb8840cf60569a66c0e508811ee79992825ec9c02da3 \ No newline at end of file +ff492277ed00c1f637a5b4ccd6d8193ea22f6781f90073861588a2b7d5c045b7 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 0cb4f0344a..6c153d65ba 100644 --- a/src/wal.c +++ b/src/wal.c @@ -528,15 +528,13 @@ struct Wal { u32 iReCksum; /* On commit, recalculate checksums from here */ const char *zWalName; /* Name of WAL file */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ -# ifdef SQLITE_DEBUG - int nSehTry; /* Number of nested SEH_TRY{} blocks */ -# endif #ifdef SQLITE_USE_SEH u32 lockMask; /* Mask of locks held */ void *pFree; /* Pointer to sqlite3_free() if exception thrown */ int iSysErrno; /* System error code following exception */ #endif #ifdef SQLITE_DEBUG + int nSehTry; /* Number of nested SEH_TRY{} blocks */ u8 lockError; /* True if a locking error has occurred */ #endif #ifdef SQLITE_ENABLE_SNAPSHOT @@ -618,19 +616,32 @@ struct WalIterator { sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ ) +/* +** Structured Exception Handling (SEH) is a Windows-specific technique +** for catching exceptions raised while accessing memory-mapped files. +** +** The -DSQLITE_USE_SEH compile-time option means to use SEH to catch and +** deal with system-level errors that arise during WAL -shm file processing. +** Without this compile-time option, any system-level faults that appear +** while accessing the memory-mapped -shm file will cause a process-wide +** signal to be deliver, which will more than likely cause the entire +** process to exit. +*/ #ifdef SQLITE_USE_SEH - #include +/* Beginning of a block of code in which an exception might occur */ # define SEH_TRY __try { \ assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \ VVA_ONLY(pWal->nSehTry++); +/* The end of a block of code in which an exception might occur */ # define SEH_EXCEPT(X) \ VVA_ONLY(pWal->nSehTry--); \ assert( pWal->nSehTry==0 ); \ } __except( sehExceptionFilter(pWal, GetExceptionCode(), GetExceptionInformation() ) ){ X } +/* Simulate a memory-mapping fault in the -shm file for testing purposes */ # define SEH_INJECT_FAULT sehInjectFault(pWal) /* @@ -662,10 +673,10 @@ static void sehInjectFault(Wal *pWal){ res = sqlite3FaultSim(650); if( res!=0 ){ - ULONG aArg[3]; + ULONG_PTR aArg[3]; aArg[0] = 0; aArg[1] = 0; - aArg[2] = (ULONG)res; + aArg[2] = (ULONG_PTR)res; RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG_PTR*)aArg); } } From 5e22dfb6a582bc6df0bfbcf6e5b63df0ada22904 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 26 Jul 2023 18:34:34 +0000 Subject: [PATCH 15/15] Add a comment describing the contents of the ExceptionInformation[] array for win32 EXCEPTION_IN_PAGE_ERROR exceptions. No changes to code. FossilOrigin-Name: 8e20354242d5f34a90b6c00d9034535ef6f6086ee4971230c7fd69985e2777d2 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/wal.c | 5 +++++ 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 7da2e11f83..3e7111a133 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\slatest\strunk\senhancements\sinto\sthe\swal-shm-exceptions\sbranch. -D 2023-07-24T12:59:53.689 +C Add\sa\scomment\sdescribing\sthe\scontents\sof\sthe\sExceptionInformation[]\sarray\sfor\swin32\sEXCEPTION_IN_PAGE_ERROR\sexceptions.\sNo\schanges\sto\scode. +D 2023-07-26T18:34:34.647 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -535,8 +535,8 @@ F ext/wasm/index.html b4e55de741be9fb7656445ea55085f703a784aebde620e1c4852fa21c1 F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54 F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234db31b187a899d10 -F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96 w ext/wasm/scratchpad-wasmfs-main.html -F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63 w ext/wasm/scratchpad-wasmfs-main.js +F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96 +F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63 F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d F ext/wasm/speedtest1-wasmfs.mjs ac5cadbf4ffe69e9eaac8b45e8523f030521e02bb67d654c6eb5236d9c456cbe F ext/wasm/speedtest1-worker.html e33e2064bda572c0c3ebaec7306c35aa758d9d27e245d67e807f8cc4a9351cc5 @@ -720,7 +720,7 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8 F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 17a7ec957bd66e46a7d6403a8d55ce92518fb382ec598a5f50e2326de0206a80 +F src/wal.c 02e10f033a6972bc7d50122b400318003199c504cda48f61ad404564505f4e89 F src/wal.h 04a9e53121d5076f2a173b0f2facb39d33047093fee71bd3bbe6b1f6f1f5fd4b F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2 F src/where.c 477fcc5e561ef169e6002499602af6b805156c2aae6b2f5c2c93ef8c1cd64768 @@ -2045,8 +2045,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ff492277ed00c1f637a5b4ccd6d8193ea22f6781f90073861588a2b7d5c045b7 c1b080e39397c983c13a5e79303223827de7b4946c18a79396851ec1814782f3 -R 2d227170a4d38cef4891eb7e41ae2e61 -U drh -Z bee2c2751faa3281b3853d97c12aa683 +P 3187ee3f69fc28a259ba0e951ac10a65c07ef2c3866acbefaf9544333a930cc6 +R 7f170a7bcc2480971e636112d216d36a +U dan +Z abd48397a81b9e2e4bef4b928510bd64 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index a0ad36f77d..7fc53587a5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3187ee3f69fc28a259ba0e951ac10a65c07ef2c3866acbefaf9544333a930cc6 \ No newline at end of file +8e20354242d5f34a90b6c00d9034535ef6f6086ee4971230c7fd69985e2777d2 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 48f5586209..c9d8eaebe5 100644 --- a/src/wal.c +++ b/src/wal.c @@ -654,6 +654,11 @@ static int sehExceptionFilter(Wal *pWal, int eCode, EXCEPTION_POINTERS *p){ VVA_ONLY(pWal->nSehTry--); if( eCode==EXCEPTION_IN_PAGE_ERROR ){ if( p && p->ExceptionRecord && p->ExceptionRecord->NumberParameters>=3 ){ + /* From MSDN: For this type of exception, the first element of the + ** ExceptionInformation[] array is a read-write flag - 0 if the exception + ** was thrown while reading, 1 if while writing. The second element is + ** the virtual address being accessed. The "third array element specifies + ** the underlying NTSTATUS code that resulted in the exception". */ pWal->iSysErrno = (int)p->ExceptionRecord->ExceptionInformation[2]; } return EXCEPTION_EXECUTE_HANDLER;