From 8714de97c0137a02a885c8eba79701b22d59ff81 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 4 May 2020 19:42:35 +0000 Subject: [PATCH 01/11] Changes to avoid deadlock in SQLITE_ENABLE_SETLK_TIMEOUT builds. FossilOrigin-Name: 553423c23142cf0ec219192315d57ce8a0e10c3d8678d28bc110a1a9a7c17cee --- main.mk | 1 + manifest | 31 ++++--- manifest.uuid | 2 +- src/btree.c | 1 - src/main.c | 48 ++--------- src/pager.c | 20 ++--- src/pager.h | 9 +- src/sqliteInt.h | 1 - src/wal.c | 222 ++++++++++++++++++++++++++++-------------------- src/wal.h | 2 +- 10 files changed, 162 insertions(+), 175 deletions(-) diff --git a/main.mk b/main.mk index 04c54d74f4..654bd043f3 100644 --- a/main.mk +++ b/main.mk @@ -423,6 +423,7 @@ TESTSRC2 = \ $(TOP)/src/vdbeaux.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/vdbemem.c \ + $(TOP)/src/vdbevtab.c \ $(TOP)/src/where.c \ $(TOP)/src/wherecode.c \ $(TOP)/src/whereexpr.c \ diff --git a/manifest b/manifest index be344da311..fdafb00a6b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ensure\sthat\sthe\smaster-journal\sname\sis\sin\sa\sform\ssuitable\sto\sbe\spassed\ninto\ssqlite3_uri_parameter(). -D 2020-05-04T11:47:38.857 +C Changes\sto\savoid\sdeadlock\sin\sSQLITE_ENABLE_SETLK_TIMEOUT\sbuilds. +D 2020-05-04T19:42:35.009 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -455,7 +455,7 @@ F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 0c20162946c82e216ae3abab6334d52f1c9b09035c13619ade404b5e7fe3ce21 +F main.mk addd0a300e90ad090dc4a934df8a6f1b6c52c057a1aebb93682aed29fb68a345 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -474,7 +474,7 @@ F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 3383ad76753193c3529318ba30db41747663639428d2f6cb7cbcd8034d4a99cd +F src/btree.c 54d404ff88f1432fc056c638e4868fe66dac98cb0f89a6cae4bd6b636053af0f F src/btree.h 989ef3c33413549e3e148f3dcb46c030f317dac130dc86809ba6b9aa4b16c72a F src/btreeInt.h 887cdd2ea7f4a65143074a8a7c8928b0546f8c18dda3c06a408ce7992cbab0c0 F src/build.c ec6c0bda1e43ef55e5f5121a77ba19fac51fc6585f95ce2da795bcedcf6e8f36 @@ -497,7 +497,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 8e4211d04eb460c0694d486c6ba1c068d468c6f653c3f237869a802ad82854de F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 421310045bd78afefb772294a99e50f37d87ae578786a6169074e6291e30d969 -F src/main.c 7e07ff5ec447451d28398d528fda25c272f86cce67bc59a9846ee5bdfb23e1d9 +F src/main.c 28ec4d31a95affad6a6667762b55c28e67d43a195c33af03f98badc64158b916 F src/malloc.c a3e13b001f988ecec6bdb90c0ea8912c8c786e623724d7098da623d8d01d19b1 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -520,8 +520,8 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c 7ef8b60222558a373d89c18d0c3bc44365b45273a528183d40bec5bb76ce23fc F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 52cee2f72710be47b5b13ff66b339ca3855e5bc48e92a94114d2affedc70041f -F src/pager.h 3b33619a90180e0874c7eca31d6f6ceb464d9322c6fb4e9a7bbb318c8a17bdb3 +F src/pager.c 8b5a3b3d12706a8692bf9b36ef0fb94029d855730f51e4615afddb9c7cc4b301 +F src/pager.h eaf8bd9b78f5033a480f66d3a9b5426d04ee352586ee75b9bc7cd50670f6a5b1 F src/parse.y c8eff38606f443d5ba245263fa7abc05e4116d95656e050c4b78e9bfbf931add F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 @@ -538,7 +538,7 @@ F src/shell.c.in cf2d24f54412c06e5fb34af7fabc748651125e1dceac29b740e91f06d23447b F src/sqlite.h.in 00fdd0a9cdcb4ca3ea6aed8466a23e158c4a2feb5c2552de62c70f40d2418289 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197 -F src/sqliteInt.h 1f6909cd268d1cda2f04914d150997b17afd8ff7e5cf1930cc1f88d337a49f74 +F src/sqliteInt.h 26de171e0adccf6e465434b9fcce18fcfcc757e9a727356b029fc1676639540c F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032 F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -617,8 +617,8 @@ F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143 F src/vdbevtab.c 8094dfc28dad82d60a1c832020a1b201a5381dc185c14638affc6d4e9d54c653 F src/vtab.c 7b704a90515a239c6cdba6a66b1bb3a385e62326cceb5ecb05ec7a091d6b8515 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 8efa749ff1e84fb69127bdab1d0f3545afc1706f4dde6f19f2f6237d7dc9c2d2 -F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a +F src/wal.c b6c5fb152c9ed73017202b4ffda1ee97a8c6cc57a3596e29ab4b763207013d49 +F src/wal.h 642f7896526181a95dde213fe1a0a515899d8eb2fa7cb562f042b0637d11d3d7 F src/walker.c 7c429c694abd12413a5c17aec9f47cfe9eba6807e6b0a32df883e8e3a14835ed F src/where.c 9546c82056e8cdb27291f98cf1adca5d271240b399bb97b32f77fc2bea6146c9 F src/whereInt.h 6b874aa15f94e43a2cec1080be64d955b04deeafeac90ffb5d6975c0d511be3c @@ -1863,7 +1863,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 efdecb13091316aeac2722f58577cb0314e008e857f2816a2a222bac0a83e9e1 -R 6897970c2b5b2cca1a8fed26518d5a6e -U drh -Z ec3fad1620b6ab238b8dc4b9fa847a46 +P d1ba026d882f070b351280028e2fa88a3cca59b46d4683302e24c6677e0951b9 +R 7034fe62283804a1df8fc178d6719787 +T *branch * setlk-deadlock-changes +T *sym-setlk-deadlock-changes * +T -sym-trunk * +U dan +Z b3c62bfe3502546b0ce8fe477018d01b diff --git a/manifest.uuid b/manifest.uuid index 1cca894bf0..fdb4fc8030 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d1ba026d882f070b351280028e2fa88a3cca59b46d4683302e24c6677e0951b9 \ No newline at end of file +553423c23142cf0ec219192315d57ce8a0e10c3d8678d28bc110a1a9a7c17cee \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 7ad40ced71..76845e072a 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3467,7 +3467,6 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ } }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && btreeInvokeBusyHandler(pBt) ); - sqlite3PagerResetLockTimeout(pBt->pPager); if( rc==SQLITE_OK ){ if( p->inTrans==TRANS_NONE ){ diff --git a/src/main.c b/src/main.c index 7322e28279..e386bb3848 100644 --- a/src/main.c +++ b/src/main.c @@ -1551,8 +1551,7 @@ const char *sqlite3ErrStr(int rc){ */ static int sqliteDefaultBusyCallback( void *ptr, /* Database connection */ - int count, /* Number of times table has been busy */ - sqlite3_file *pFile /* The file on which the lock occurred */ + int count /* Number of times table has been busy */ ){ #if SQLITE_OS_WIN || HAVE_USLEEP /* This case is for systems that have support for sleeping for fractions of @@ -1566,31 +1565,6 @@ static int sqliteDefaultBusyCallback( int tmout = db->busyTimeout; int delay, prior; -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){ - if( count ){ - /* If this is the second or later invocation of the busy-handler, - ** but tmout==0, then code in wal.c must have disabled the blocking - ** lock before the SQLITE_BUSY error was hit. In this case, no delay - ** occurred while waiting for the lock, so fall through to the xSleep() - ** code below to delay a while before retrying the lock. - ** - ** Alternatively, if tmout!=0, then SQLite has already waited - ** sqlite3.busyTimeout ms for a lock. In this case, return 0 to - ** indicate that the lock should not be retried and the SQLITE_BUSY - ** error returned to the application. */ - if( tmout ){ - tmout = 0; - sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout); - return 0; - } - }else{ - return 1; - } - } -#else - UNUSED_PARAMETER(pFile); -#endif assert( count>=0 ); if( count < NDELAY ){ delay = delays[count]; @@ -1610,7 +1584,6 @@ static int sqliteDefaultBusyCallback( ** must be done in increments of whole seconds */ sqlite3 *db = (sqlite3 *)ptr; int tmout = ((sqlite3 *)ptr)->busyTimeout; - UNUSED_PARAMETER(pFile); if( (count+1)*1000 > tmout ){ return 0; } @@ -1631,16 +1604,7 @@ static int sqliteDefaultBusyCallback( int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){ int rc; if( p->xBusyHandler==0 || p->nBusy<0 ) return 0; - if( p->bExtraFileArg ){ - /* Add an extra parameter with the pFile pointer to the end of the - ** callback argument list */ - int (*xTra)(void*,int,sqlite3_file*); - xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler; - rc = xTra(p->pBusyArg, p->nBusy, pFile); - }else{ - /* Legacy style busy handler callback */ - rc = p->xBusyHandler(p->pBusyArg, p->nBusy); - } + rc = p->xBusyHandler(p->pBusyArg, p->nBusy); if( rc==0 ){ p->nBusy = -1; }else{ @@ -1665,7 +1629,6 @@ int sqlite3_busy_handler( db->busyHandler.xBusyHandler = xBusy; db->busyHandler.pBusyArg = pArg; db->busyHandler.nBusy = 0; - db->busyHandler.bExtraFileArg = 0; db->busyTimeout = 0; sqlite3_mutex_leave(db->mutex); return SQLITE_OK; @@ -1716,7 +1679,6 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){ sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback, (void*)db); db->busyTimeout = ms; - db->busyHandler.bExtraFileArg = 1; }else{ sqlite3_busy_handler(db, 0, 0); } @@ -3359,7 +3321,7 @@ static int openDatabase( #endif #ifdef SQLITE_ENABLE_BYTECODE_VTAB - if( !db->mallocFailed && rc==SQLITE_OK){ + if( !db->mallocFailed && rc==SQLITE_OK ){ rc = sqlite3VdbeBytecodeVtabInit(db); } #endif @@ -4520,11 +4482,11 @@ int sqlite3_snapshot_open( rc = SQLITE_OK; } if( rc==SQLITE_OK ){ - rc = sqlite3PagerSnapshotOpen(pPager, pSnapshot); + rc = sqlite3PagerSnapshotOpen(pPager, db, pSnapshot); } if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pBt, 0, 0); - sqlite3PagerSnapshotOpen(pPager, 0); + sqlite3PagerSnapshotOpen(pPager, 0, 0); } if( bUnlock ){ sqlite3PagerSnapshotUnlock(pPager); diff --git a/src/pager.c b/src/pager.c index 0d08a2dfaa..dd723b788d 100644 --- a/src/pager.c +++ b/src/pager.c @@ -5705,7 +5705,6 @@ void sqlite3PagerUnrefPageOne(DbPage *pPg){ assert( pPg->pgno==1 ); assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */ pPager = pPg->pPager; - sqlite3PagerResetLockTimeout(pPager); sqlite3PcacheRelease(pPg); pagerUnlockIfUnused(pPager); } @@ -6998,16 +6997,6 @@ sqlite3_file *sqlite3PagerFile(Pager *pPager){ return pPager->fd; } -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT -/* -** Reset the lock timeout for pager. -*/ -void sqlite3PagerResetLockTimeout(Pager *pPager){ - int x = 0; - sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x); -} -#endif - /* ** Return the file handle for the journal file (if it exists). ** This will be either the rollback journal or the WAL file. @@ -7421,7 +7410,6 @@ int sqlite3PagerCheckpoint( pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace, pnLog, pnCkpt ); - sqlite3PagerResetLockTimeout(pPager); } return rc; } @@ -7606,10 +7594,14 @@ int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot){ ** read transaction is opened, attempt to read from the snapshot it ** identifies. If this is not a WAL database, return an error. */ -int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot){ +int sqlite3PagerSnapshotOpen( + Pager *pPager, + sqlite3 *db, + sqlite3_snapshot *pSnapshot +){ int rc = SQLITE_OK; if( pPager->pWal ){ - sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot); + sqlite3WalSnapshotOpen(pPager->pWal, db, pSnapshot); }else{ rc = SQLITE_ERROR; } diff --git a/src/pager.h b/src/pager.h index 2c99d67a9b..a044daa18b 100644 --- a/src/pager.h +++ b/src/pager.h @@ -177,8 +177,8 @@ int sqlite3PagerSharedLock(Pager *pPager); int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); # ifdef SQLITE_ENABLE_SNAPSHOT - int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); - int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); + int sqlite3PagerSnapshotGet(Pager*, sqlite3_snapshot **ppSnapshot); + int sqlite3PagerSnapshotOpen(Pager*, sqlite3*, sqlite3_snapshot *pSnapshot); int sqlite3PagerSnapshotRecover(Pager *pPager); int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot); void sqlite3PagerSnapshotUnlock(Pager *pPager); @@ -210,11 +210,6 @@ int sqlite3PagerIsMemdb(Pager*); void sqlite3PagerCacheStat(Pager *, int, int, int *); void sqlite3PagerClearCache(Pager*); int sqlite3SectorSize(sqlite3_file *); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT -void sqlite3PagerResetLockTimeout(Pager *pPager); -#else -# define sqlite3PagerResetLockTimeout(X) -#endif /* Functions used to truncate the database file. */ void sqlite3PagerTruncateImage(Pager*,Pgno); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 4a78d0cfda..b01f323935 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -994,7 +994,6 @@ struct BusyHandler { int (*xBusyHandler)(void *,int); /* The busy callback */ void *pBusyArg; /* First arg to busy callback */ int nBusy; /* Incremented with each busy call */ - u8 bExtraFileArg; /* Include sqlite3_file as callback arg */ }; /* diff --git a/src/wal.c b/src/wal.c index b230858599..020a481e28 100644 --- a/src/wal.c +++ b/src/wal.c @@ -466,6 +466,9 @@ struct Wal { #endif #ifdef SQLITE_ENABLE_SNAPSHOT WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ +# ifdef SQLITE_ENABLE_SETLK_TIMEOUT + sqlite3 *dbSnapshot; +# endif #endif }; @@ -1128,11 +1131,6 @@ static int walIndexRecover(Wal *pWal){ u32 aFrameCksum[2] = {0, 0}; int iLock; /* Lock offset to lock for checkpoint */ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int tmout = 0; - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); -#endif - /* Obtain an exclusive lock on all byte in the locking range not already ** locked by the caller. The caller is guaranteed to have locked the ** WAL_WRITE_LOCK byte, and may have also locked the WAL_CKPT_LOCK byte. @@ -2750,22 +2748,45 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ int rc; /* Return code */ int cnt = 0; /* Number of TryBeginRead attempts */ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int tmout = 0; -#endif + #ifdef SQLITE_ENABLE_SNAPSHOT int bChanged = 0; WalIndexHdr *pSnapshot = pWal->pSnapshot; - if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ - bChanged = 1; - } + if( pSnapshot ){ +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + int busyTimeout = pWal->dbSnapshot->busyTimeout; + if( busyTimeout ){ + int tmout = busyTimeout; + sqlite3OsFileControl(pWal->pDbFd,SQLITE_FCNTL_LOCK_TIMEOUT,(void*)&tmout); + } #endif + if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ + bChanged = 1; + } + + /* It is possible that there is a checkpointer thread running + ** concurrent with this code. If this is the case, it may be that the + ** checkpointer has already determined that it will checkpoint + ** snapshot X, where X is later in the wal file than pSnapshot, but + ** has not yet set the pInfo->nBackfillAttempted variable to indicate + ** its intent. To avoid the race condition this leads to, ensure that + ** there is no checkpointer process by taking a shared CKPT lock + ** before checking pInfo->nBackfillAttempted. */ + rc = walLockShared(pWal, WAL_CKPT_LOCK); + #ifdef SQLITE_ENABLE_SETLK_TIMEOUT - /* Disable blocking locks. They are not useful when trying to open a - ** read-transaction, and blocking may cause deadlock anyway. */ - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); + if( busyTimeout ){ + int tmout = 0; + sqlite3OsFileControl(pWal->pDbFd,SQLITE_FCNTL_LOCK_TIMEOUT,(void*)&tmout); + } +#endif + + if( rc!=SQLITE_OK ){ + return rc; + } + } #endif do{ @@ -2776,16 +2797,6 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ testcase( rc==SQLITE_PROTOCOL ); testcase( rc==SQLITE_OK ); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - /* If they were disabled earlier and the read-transaction has been - ** successfully opened, re-enable blocking locks. This is because the - ** connection may attempt to upgrade to a write-transaction, which does - ** benefit from using blocking locks. */ - if( rc==SQLITE_OK ){ - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); - } -#endif - #ifdef SQLITE_ENABLE_SNAPSHOT if( rc==SQLITE_OK ){ if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ @@ -2807,48 +2818,40 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 ); assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame ); - /* It is possible that there is a checkpointer thread running - ** concurrent with this code. If this is the case, it may be that the - ** checkpointer has already determined that it will checkpoint - ** snapshot X, where X is later in the wal file than pSnapshot, but - ** has not yet set the pInfo->nBackfillAttempted variable to indicate - ** its intent. To avoid the race condition this leads to, ensure that - ** there is no checkpointer process by taking a shared CKPT lock - ** before checking pInfo->nBackfillAttempted. - ** - ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing - ** this already? - */ - rc = walLockShared(pWal, WAL_CKPT_LOCK); - - if( rc==SQLITE_OK ){ - /* Check that the wal file has not been wrapped. Assuming that it has - ** not, also check that no checkpointer has attempted to checkpoint any - ** frames beyond pSnapshot->mxFrame. If either of these conditions are - ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr - ** with *pSnapshot and set *pChanged as appropriate for opening the - ** snapshot. */ - if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) - && pSnapshot->mxFrame>=pInfo->nBackfillAttempted - ){ - assert( pWal->readLock>0 ); - memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr)); - *pChanged = bChanged; - }else{ - rc = SQLITE_ERROR_SNAPSHOT; - } - - /* Release the shared CKPT lock obtained above. */ - walUnlockShared(pWal, WAL_CKPT_LOCK); - pWal->minFrame = 1; + /* Check that the wal file has not been wrapped. Assuming that it has + ** not, also check that no checkpointer has attempted to checkpoint any + ** frames beyond pSnapshot->mxFrame. If either of these conditions are + ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr + ** with *pSnapshot and set *pChanged as appropriate for opening the + ** snapshot. */ + if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) + && pSnapshot->mxFrame>=pInfo->nBackfillAttempted + ){ + assert( pWal->readLock>0 ); + memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr)); + *pChanged = bChanged; + }else{ + rc = SQLITE_ERROR_SNAPSHOT; } + /* A client using a non-current snapshot may not ignore any frames + ** from the start of the wal file. This is because, for a system + ** where (minFrame < iSnapshot < maxFrame), a checkpointer may + ** have omitted to checkpoint a frame earlier than minFrame in + ** the file because there exists a frame after iSnapshot that + ** is the same database page. */ + pWal->minFrame = 1; if( rc!=SQLITE_OK ){ sqlite3WalEndReadTransaction(pWal); } } } + + /* Release the shared CKPT lock obtained above. */ + if( pSnapshot ){ + walUnlockShared(pWal, WAL_CKPT_LOCK); + } #endif return rc; } @@ -3584,6 +3587,9 @@ int sqlite3WalCheckpoint( int isChanged = 0; /* True if a new wal-index header is loaded */ int eMode2 = eMode; /* Mode to pass to walCheckpoint() */ int (*xBusy2)(void*) = xBusy; /* Busy handler for eMode2 */ +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + int bSetLk = 0; +#endif assert( pWal->ckptLock==0 ); assert( pWal->writeLock==0 ); @@ -3595,41 +3601,54 @@ int sqlite3WalCheckpoint( if( pWal->readOnly ) return SQLITE_READONLY; WALTRACE(("WAL%p: checkpoint begins\n", pWal)); - /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive - ** "checkpoint" lock on the database file. */ - rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); - if( rc ){ - /* EVIDENCE-OF: R-10421-19736 If any other process is running a - ** checkpoint operation at the same time, the lock cannot be obtained and - ** SQLITE_BUSY is returned. - ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, - ** it will not be invoked in this case. - */ - testcase( rc==SQLITE_BUSY ); - testcase( xBusy!=0 ); - return rc; - } - pWal->ckptLock = 1; - - /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and - ** TRUNCATE modes also obtain the exclusive "writer" lock on the database - ** file. - ** - ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained - ** immediately, and a busy-handler is configured, it is invoked and the - ** writer lock retried until either the busy-handler returns 0 or the - ** lock is successfully obtained. - */ - if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ - rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1); - if( rc==SQLITE_OK ){ - pWal->writeLock = 1; - }else if( rc==SQLITE_BUSY ){ - eMode2 = SQLITE_CHECKPOINT_PASSIVE; +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + if( db->busyTimeout ){ + int tmout = db->busyTimeout; + sqlite3_file *fd = pWal->pDbFd; + if( SQLITE_OK== + sqlite3OsFileControl(fd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout) + ){ xBusy2 = 0; - rc = SQLITE_OK; + bSetLk = 1; } } +#endif + + /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive + ** "checkpoint" lock on the database file. + ** EVIDENCE-OF: R-10421-19736 If any other process is running a + ** checkpoint operation at the same time, the lock cannot be obtained and + ** SQLITE_BUSY is returned. + ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured, + ** it will not be invoked in this case. + */ + rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); + testcase( rc==SQLITE_BUSY ); + testcase( rc!=SQLITE_OK && xBusy2!=0 ); + if( rc==SQLITE_OK ){ + pWal->ckptLock = 1; + + /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and + ** TRUNCATE modes also obtain the exclusive "writer" lock on the database + ** file. + ** + ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained + ** immediately, and a busy-handler is configured, it is invoked and the + ** writer lock retried until either the busy-handler returns 0 or the + ** lock is successfully obtained. + */ + if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){ + rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1); + if( rc==SQLITE_OK ){ + pWal->writeLock = 1; + }else if( rc==SQLITE_BUSY ){ + eMode2 = SQLITE_CHECKPOINT_PASSIVE; + xBusy2 = 0; + rc = SQLITE_OK; + } + } + } + /* Read the wal-index header. */ if( rc==SQLITE_OK ){ @@ -3665,10 +3684,20 @@ int sqlite3WalCheckpoint( memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); } +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + if( bSetLk ){ + int tmout = 0; + sqlite3_file *fd = pWal->pDbFd; + sqlite3OsFileControl(fd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); + } +#endif + /* Release the locks. */ sqlite3WalEndWriteTransaction(pWal); - walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); - pWal->ckptLock = 0; + if( pWal->ckptLock ){ + walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); + pWal->ckptLock = 0; + } WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc); } @@ -3786,8 +3815,15 @@ int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){ /* Try to open on pSnapshot when the next read-transaction starts */ -void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){ +void sqlite3WalSnapshotOpen( + Wal *pWal, + sqlite3 *db, + sqlite3_snapshot *pSnapshot +){ pWal->pSnapshot = (WalIndexHdr*)pSnapshot; +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + pWal->dbSnapshot = db; +#endif } /* diff --git a/src/wal.h b/src/wal.h index 1610607481..bebd643700 100644 --- a/src/wal.h +++ b/src/wal.h @@ -130,7 +130,7 @@ int sqlite3WalHeapMemory(Wal *pWal); #ifdef SQLITE_ENABLE_SNAPSHOT int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot); -void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot); +void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3*, sqlite3_snapshot *pSnapshot); int sqlite3WalSnapshotRecover(Wal *pWal); int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot); void sqlite3WalSnapshotUnlock(Wal *pWal); From 58021b237ae7e84069aaa564c0b6834a23296aed Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 5 May 2020 20:30:07 +0000 Subject: [PATCH 02/11] Unless upgrading an existing read transaction, have ENABLE_SETLK_TIMEOUT builds attempt to use a blocking lock when opening a write transaction on a wal mode database. FossilOrigin-Name: d6f819a9e6b35f3fd558bd93255a6a24ad690a0fa15a82b009ca9c641db983c6 --- manifest | 27 ++++++------ manifest.uuid | 2 +- src/btree.c | 15 ++++++- src/os_unix.c | 18 ++++---- src/pager.c | 16 ++++++- src/pager.h | 6 +++ src/wal.c | 114 ++++++++++++++++++++++++++++++++++---------------- src/wal.h | 4 ++ test/wal.test | 1 + 9 files changed, 140 insertions(+), 63 deletions(-) diff --git a/manifest b/manifest index fdafb00a6b..8d829988c3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Changes\sto\savoid\sdeadlock\sin\sSQLITE_ENABLE_SETLK_TIMEOUT\sbuilds. -D 2020-05-04T19:42:35.009 +C Unless\supgrading\san\sexisting\sread\stransaction,\shave\sENABLE_SETLK_TIMEOUT\sbuilds\sattempt\sto\suse\sa\sblocking\slock\swhen\sopening\sa\swrite\stransaction\son\sa\swal\smode\sdatabase. +D 2020-05-05T20:30:07.254 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -474,7 +474,7 @@ F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 54d404ff88f1432fc056c638e4868fe66dac98cb0f89a6cae4bd6b636053af0f +F src/btree.c 2a152165efcbde2a0df808705cb44b8d2588440f0a9ebcbe534ca95843c10355 F src/btree.h 989ef3c33413549e3e148f3dcb46c030f317dac130dc86809ba6b9aa4b16c72a F src/btreeInt.h 887cdd2ea7f4a65143074a8a7c8928b0546f8c18dda3c06a408ce7992cbab0c0 F src/build.c ec6c0bda1e43ef55e5f5121a77ba19fac51fc6585f95ce2da795bcedcf6e8f36 @@ -517,11 +517,11 @@ F src/os.c 669cc3839cc35d20f81faf0be1ab6d4581cea35e9d8f3a9d48a98d6571f7c285 F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c 7ef8b60222558a373d89c18d0c3bc44365b45273a528183d40bec5bb76ce23fc +F src/os_unix.c daabdb3c33ef4a6b49ff6809968af2f8c0d3c5811bc654d74375f015180235aa F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 8b5a3b3d12706a8692bf9b36ef0fb94029d855730f51e4615afddb9c7cc4b301 -F src/pager.h eaf8bd9b78f5033a480f66d3a9b5426d04ee352586ee75b9bc7cd50670f6a5b1 +F src/pager.c be4d6d58df5c5d02b84547fd253a80f035ea2ee53931a5393d96af0ba3f04edb +F src/pager.h 5e2c0e5bd32aa4ae6c25eda2722490bb3f671f24d2e5d665d33df13285c1d520 F src/parse.y c8eff38606f443d5ba245263fa7abc05e4116d95656e050c4b78e9bfbf931add F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 @@ -617,8 +617,8 @@ F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143 F src/vdbevtab.c 8094dfc28dad82d60a1c832020a1b201a5381dc185c14638affc6d4e9d54c653 F src/vtab.c 7b704a90515a239c6cdba6a66b1bb3a385e62326cceb5ecb05ec7a091d6b8515 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c b6c5fb152c9ed73017202b4ffda1ee97a8c6cc57a3596e29ab4b763207013d49 -F src/wal.h 642f7896526181a95dde213fe1a0a515899d8eb2fa7cb562f042b0637d11d3d7 +F src/wal.c 4099109dcf2b302e0d151e6fa0678d9bbc3eb923b8bd13a3cd07db0e7df5016b +F src/wal.h 484890eaaefb89c0f2043ae34c20bf367383f201f63da631ecae424797a7f60d F src/walker.c 7c429c694abd12413a5c17aec9f47cfe9eba6807e6b0a32df883e8e3a14835ed F src/where.c 9546c82056e8cdb27291f98cf1adca5d271240b399bb97b32f77fc2bea6146c9 F src/whereInt.h 6b874aa15f94e43a2cec1080be64d955b04deeafeac90ffb5d6975c0d511be3c @@ -1658,7 +1658,7 @@ F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c37 F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65 F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad F test/vtabdrop.test 65d4cf6722972e5499bdaf0c0d70ee3b8133944a4e4bc31862563f32a7edca12 -F test/wal.test cdf0ca6cc0447520d19ef1c83287824ebeb3e82d75af856511ba96841a79fc9b +F test/wal.test 16180bc4becda176428ad02eaea437b4b8f5ae099314de443a4e12b2dcc007a2 F test/wal2.test 537f59e5c5932e3b45bf3591ae3e48a2601360c2e52821b633e222fe6ebd5b09 F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2 F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c @@ -1863,10 +1863,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 d1ba026d882f070b351280028e2fa88a3cca59b46d4683302e24c6677e0951b9 -R 7034fe62283804a1df8fc178d6719787 -T *branch * setlk-deadlock-changes -T *sym-setlk-deadlock-changes * -T -sym-trunk * +P 553423c23142cf0ec219192315d57ce8a0e10c3d8678d28bc110a1a9a7c17cee +R aa33971255c5eac84a2aa86cb20ae159 U dan -Z b3c62bfe3502546b0ce8fe477018d01b +Z dc53b638850c8fa914d5b99111645e25 diff --git a/manifest.uuid b/manifest.uuid index fdb4fc8030..2f292c1a11 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -553423c23142cf0ec219192315d57ce8a0e10c3d8678d28bc110a1a9a7c17cee \ No newline at end of file +d6f819a9e6b35f3fd558bd93255a6a24ad690a0fa15a82b009ca9c641db983c6 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 76845e072a..3b8d0529ce 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3437,6 +3437,18 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ pBt->btsFlags &= ~BTS_INITIALLY_EMPTY; if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY; do { + Pager *pPager = pBt->pPager; + +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + /* If transitioning from no transaction directly to a write transaction, + ** block for the WRITER lock first if possible. */ + if( pBt->pPage1==0 && wrflag ){ + assert( pBt->inTransaction==TRANS_NONE ); + rc = sqlite3PagerWalWriteLock(p->db, pPager, 1); + if( rc!=SQLITE_OK ) break; + } +#endif + /* Call lockBtree() until either pBt->pPage1 is populated or ** lockBtree() returns something other than SQLITE_OK. lockBtree() ** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after @@ -3450,7 +3462,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){ rc = SQLITE_READONLY; }else{ - rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db)); + rc = sqlite3PagerBegin(pPager, wrflag>1, sqlite3TempInMemory(p->db)); if( rc==SQLITE_OK ){ rc = newDatabase(pBt); }else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){ @@ -3463,6 +3475,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ } if( rc!=SQLITE_OK ){ + sqlite3PagerWalWriteLock(p->db, pPager, 0); unlockBtreeIfUnused(pBt); } }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && diff --git a/src/os_unix.c b/src/os_unix.c index 56e53929ea..e1ed575b01 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4819,22 +4819,24 @@ static int unixShmLock( assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 ); assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 ); - /* Check that, if this to be a blocking lock, that locks have been - ** obtained in the following order. + /* Check that, if this to be a blocking lock, no locks that occur later + ** in the following list than the lock being obtained are already held: ** ** 1. Checkpointer lock (ofst==1). - ** 2. Recover lock (ofst==2). + ** 2. Write lock (ofst==0). ** 3. Read locks (ofst>=3 && ofstiBusyTimeout==0 - || (flags & SQLITE_SHM_UNLOCK) || ofst==0 - || ((p->exclMask|p->sharedMask)&~((1<iBusyTimeout==0 || ( + (ofst!=2) /* not RECOVER */ + && (n==1) /* Single lock only */ + && (ofst!=1 || (p->exclMask|p->sharedMask)==0) + && (ofst!=0 || (p->exclMask|p->sharedMask)<3) + && (ofst<3 || (p->exclMask|p->sharedMask)<(1<exclusiveMode==0 ){ + rc = sqlite3WalWriteLock(db, pPager->pWal, bLock); + } + return rc; +} +#endif #ifdef SQLITE_ENABLE_SNAPSHOT /* diff --git a/src/pager.h b/src/pager.h index a044daa18b..c203908c83 100644 --- a/src/pager.h +++ b/src/pager.h @@ -185,6 +185,12 @@ int sqlite3PagerSharedLock(Pager *pPager); # endif #endif +#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_ENABLE_SETLK_TIMEOUT) + int sqlite3PagerWalWriteLock(sqlite3*, Pager*, int); +#else +# define sqlite3PagerWalWriteLock(x,y,z) SQLITE_OK +#endif + #ifdef SQLITE_DIRECT_OVERFLOW_READ int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno); #endif diff --git a/src/wal.c b/src/wal.c index 020a481e28..a70a716244 100644 --- a/src/wal.c +++ b/src/wal.c @@ -2731,6 +2731,65 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ } #endif /* SQLITE_ENABLE_SNAPSHOT */ +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT +/* +** Attempt to enable blocking locks. Blocking locks are enabled only if (a) +** they are supported by the VFS, and (b) the database handle is configured +** with a busy-timeout. Return 1 if blocking locks are successfully enabled, +** or 0 otherwise. +*/ +static int walEnableBlocking(sqlite3 *db, Wal *pWal){ + int res = 0; + if( db->busyTimeout ){ + int rc; + int tmout = db->busyTimeout; + rc = sqlite3OsFileControl( + pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout + ); + res = (rc==SQLITE_OK); + } + return res; +} + +/* +** Disable blocking locks. +*/ +static void walDisableBlocking(Wal *pWal){ + int tmout = 0; + sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); +} + +/* +** If parameter bLock is true, attempt to enable blocking locks, take +** the WRITER lock, and then disable blocking locks. If blocking locks +** cannot be enabled, no attempt to obtain the WRITER lock is made. Return +** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not +** an error if blocking locks can not be enabled. +** +** If the bLock parameter is false and the WRITER lock is held, release it. +*/ +int sqlite3WalWriteLock(sqlite3 *db, Wal *pWal, int bLock){ + int rc = SQLITE_OK; + assert( pWal->readLock<0 || bLock==0 ); + if( bLock ){ + if( walEnableBlocking(db, pWal) ){ + rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); + if( rc==SQLITE_OK ){ + pWal->writeLock = 1; + } + walDisableBlocking(pWal); + } + }else if( pWal->writeLock ){ + walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); + pWal->writeLock = 0; + } + return rc; +} +#else +# define walEnableBlocking(x,y) 0 +# define walDisableBlocking(x) +#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */ + /* ** Begin a read transaction on the database. ** @@ -2754,14 +2813,6 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ int bChanged = 0; WalIndexHdr *pSnapshot = pWal->pSnapshot; if( pSnapshot ){ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int busyTimeout = pWal->dbSnapshot->busyTimeout; - if( busyTimeout ){ - int tmout = busyTimeout; - sqlite3OsFileControl(pWal->pDbFd,SQLITE_FCNTL_LOCK_TIMEOUT,(void*)&tmout); - } -#endif - if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){ bChanged = 1; } @@ -2774,14 +2825,9 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ ** its intent. To avoid the race condition this leads to, ensure that ** there is no checkpointer process by taking a shared CKPT lock ** before checking pInfo->nBackfillAttempted. */ + walEnableBlocking(pWal->dbSnapshot, pWal); rc = walLockShared(pWal, WAL_CKPT_LOCK); - -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( busyTimeout ){ - int tmout = 0; - sqlite3OsFileControl(pWal->pDbFd,SQLITE_FCNTL_LOCK_TIMEOUT,(void*)&tmout); - } -#endif + walDisableBlocking(pWal); if( rc!=SQLITE_OK ){ return rc; @@ -2861,8 +2907,8 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ ** read-lock. */ void sqlite3WalEndReadTransaction(Wal *pWal){ - sqlite3WalEndWriteTransaction(pWal); if( pWal->readLock>=0 ){ + sqlite3WalEndWriteTransaction(pWal); walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); pWal->readLock = -1; } @@ -3022,6 +3068,16 @@ Pgno sqlite3WalDbsize(Wal *pWal){ int sqlite3WalBeginWriteTransaction(Wal *pWal){ int rc; +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + /* If the write-lock is already held, then it was obtained before the + ** read-transaction was even opened, making this call a no-op. + ** Return early. */ + if( pWal->writeLock ){ + assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) ); + return SQLITE_OK; + } +#endif + /* Cannot start a write transaction without first holding a read ** transaction. */ assert( pWal->readLock>=0 ); @@ -3587,9 +3643,6 @@ int sqlite3WalCheckpoint( int isChanged = 0; /* True if a new wal-index header is loaded */ int eMode2 = eMode; /* Mode to pass to walCheckpoint() */ int (*xBusy2)(void*) = xBusy; /* Busy handler for eMode2 */ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - int bSetLk = 0; -#endif assert( pWal->ckptLock==0 ); assert( pWal->writeLock==0 ); @@ -3601,18 +3654,11 @@ int sqlite3WalCheckpoint( if( pWal->readOnly ) return SQLITE_READONLY; WALTRACE(("WAL%p: checkpoint begins\n", pWal)); -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( db->busyTimeout ){ - int tmout = db->busyTimeout; - sqlite3_file *fd = pWal->pDbFd; - if( SQLITE_OK== - sqlite3OsFileControl(fd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout) - ){ - xBusy2 = 0; - bSetLk = 1; - } + /* Enable blocking locks, if possible. If blocking locks are successfully + ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */ + if( walEnableBlocking(db, pWal) ){ + xBusy2 = 0; } -#endif /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive ** "checkpoint" lock on the database file. @@ -3684,13 +3730,7 @@ int sqlite3WalCheckpoint( memset(&pWal->hdr, 0, sizeof(WalIndexHdr)); } -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - if( bSetLk ){ - int tmout = 0; - sqlite3_file *fd = pWal->pDbFd; - sqlite3OsFileControl(fd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); - } -#endif + walDisableBlocking(pWal); /* Release the locks. */ sqlite3WalEndWriteTransaction(pWal); diff --git a/src/wal.h b/src/wal.h index bebd643700..99ebc937af 100644 --- a/src/wal.h +++ b/src/wal.h @@ -146,5 +146,9 @@ int sqlite3WalFramesize(Wal *pWal); /* Return the sqlite3_file object for the WAL file */ sqlite3_file *sqlite3WalFile(Wal *pWal); +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT +int sqlite3WalWriteLock(sqlite3 *db, Wal *pWal, int bLock); +#endif + #endif /* ifndef SQLITE_OMIT_WAL */ #endif /* SQLITE_WAL_H */ diff --git a/test/wal.test b/test/wal.test index a003b6ad20..acc2780081 100644 --- a/test/wal.test +++ b/test/wal.test @@ -43,6 +43,7 @@ proc sqlite3_wal {args} { [lindex $args 0] eval { PRAGMA journal_mode = wal } [lindex $args 0] eval { PRAGMA synchronous = normal } [lindex $args 0] function blob blob + db timeout 1000 } proc log_deleted {logfile} { From d0e6d133017d7fb82f0d16071eefc2c962762390 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 6 May 2020 17:18:57 +0000 Subject: [PATCH 03/11] Add tests for running recovery when opening a write transaction or performing a checkpoint with blocking locks enabled. Fix some failing assert() statements. FossilOrigin-Name: d096ea3fe20f8af90f9e3f798fd0a69527b32ac8e208ade58b9d0af0e831f41b --- manifest | 15 +++++----- manifest.uuid | 2 +- src/os_unix.c | 1 - src/wal.c | 42 ++++++++++++++++---------- test/walsetlk.test | 75 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 111 insertions(+), 24 deletions(-) create mode 100644 test/walsetlk.test diff --git a/manifest b/manifest index 3d7f93a31e..755c31ef40 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\slatest\strunk\schanges\sinto\sthis\sbranch. -D 2020-05-06T15:07:25.513 +C Add\stests\sfor\srunning\srecovery\swhen\sopening\sa\swrite\stransaction\sor\sperforming\sa\scheckpoint\swith\sblocking\slocks\senabled.\sFix\ssome\sfailing\sassert()\sstatements. +D 2020-05-06T17:18:57.298 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -517,7 +517,7 @@ F src/os.c 669cc3839cc35d20f81faf0be1ab6d4581cea35e9d8f3a9d48a98d6571f7c285 F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c daabdb3c33ef4a6b49ff6809968af2f8c0d3c5811bc654d74375f015180235aa +F src/os_unix.c 0e1acfbb8a75f2a4acede6078b072238df63981b172a9cd16f8b090d68291c15 F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c be4d6d58df5c5d02b84547fd253a80f035ea2ee53931a5393d96af0ba3f04edb @@ -617,7 +617,7 @@ F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143 F src/vdbevtab.c 8094dfc28dad82d60a1c832020a1b201a5381dc185c14638affc6d4e9d54c653 F src/vtab.c 7b704a90515a239c6cdba6a66b1bb3a385e62326cceb5ecb05ec7a091d6b8515 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 4099109dcf2b302e0d151e6fa0678d9bbc3eb923b8bd13a3cd07db0e7df5016b +F src/wal.c 9cf3f288cd4e48b49725e03037b60246a154ca8775892c75c319db8f5652ae8a F src/wal.h 484890eaaefb89c0f2043ae34c20bf367383f201f63da631ecae424797a7f60d F src/walker.c 7c429c694abd12413a5c17aec9f47cfe9eba6807e6b0a32df883e8e3a14835ed F src/where.c 9546c82056e8cdb27291f98cf1adca5d271240b399bb97b32f77fc2bea6146c9 @@ -1689,6 +1689,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 +F test/walsetlk.test 9da1ee8a18b0416a5ce1914331c1303bcb6cb7bac905eb660f788f023718d8f4 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747 @@ -1863,7 +1864,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 d6f819a9e6b35f3fd558bd93255a6a24ad690a0fa15a82b009ca9c641db983c6 9a84d8eb44b12ddea921baa73ac3bffa8c8d23a852605dc1dbde37907360bd79 -R de537778f79587f163af3363949d5ea7 +P a3727dba10b476f414f0a049b35f2a5c169a408eccefa6833821560684e07f8b +R e1d7b36a881e7c026e918bb1e2d9268d U dan -Z 87b208fa9f7bcdf2aaff63753ffc5546 +Z 92e7a8a964d43aa5533a6dd765b70a70 diff --git a/manifest.uuid b/manifest.uuid index 9593fe8777..78c3a449bb 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a3727dba10b476f414f0a049b35f2a5c169a408eccefa6833821560684e07f8b \ No newline at end of file +d096ea3fe20f8af90f9e3f798fd0a69527b32ac8e208ade58b9d0af0e831f41b \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index e1ed575b01..72c446ea77 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4832,7 +4832,6 @@ static int unixShmLock( #ifdef SQLITE_ENABLE_SETLK_TIMEOUT assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || ( (ofst!=2) /* not RECOVER */ - && (n==1) /* Single lock only */ && (ofst!=1 || (p->exclMask|p->sharedMask)==0) && (ofst!=0 || (p->exclMask|p->sharedMask)<3) && (ofst<3 || (p->exclMask|p->sharedMask)<(1<writeLock==0 ); if( badHdr ){ if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){ if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){ walUnlockShared(pWal, WAL_WRITE_LOCK); rc = SQLITE_READONLY_RECOVERY; } - }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){ - pWal->writeLock = 1; - if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ - badHdr = walIndexTryHdr(pWal, pChanged); - if( badHdr ){ - /* If the wal-index header is still malformed even while holding - ** a WRITE lock, it can only mean that the header is corrupted and - ** needs to be reconstructed. So run recovery to do exactly that. - */ - rc = walIndexRecover(pWal); - *pChanged = 1; + }else{ + int bWriteLock = pWal->writeLock; + if( bWriteLock + || SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) + ){ + pWal->writeLock = 1; + if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ + badHdr = walIndexTryHdr(pWal, pChanged); + if( badHdr ){ + /* If the wal-index header is still malformed even while holding + ** a WRITE lock, it can only mean that the header is corrupted and + ** needs to be reconstructed. So run recovery to do exactly that. + */ + rc = walIndexRecover(pWal); + *pChanged = 1; + } + } + if( bWriteLock==0 ){ + pWal->writeLock = 0; + walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); } } - pWal->writeLock = 0; - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); } } @@ -2808,6 +2814,7 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ int rc; /* Return code */ int cnt = 0; /* Number of TryBeginRead attempts */ + assert( pWal->ckptLock==0 ); #ifdef SQLITE_ENABLE_SNAPSHOT int bChanged = 0; @@ -2832,6 +2839,7 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ if( rc!=SQLITE_OK ){ return rc; } + pWal->ckptLock = 1; } #endif @@ -2895,8 +2903,10 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ } /* Release the shared CKPT lock obtained above. */ - if( pSnapshot ){ + if( pWal->ckptLock ){ + assert( pSnapshot ); walUnlockShared(pWal, WAL_CKPT_LOCK); + pWal->ckptLock = 0; } #endif return rc; @@ -3698,7 +3708,9 @@ int sqlite3WalCheckpoint( /* Read the wal-index header. */ if( rc==SQLITE_OK ){ + walDisableBlocking(pWal); rc = walIndexReadHdr(pWal, &isChanged); + walEnableBlocking(db, pWal); if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ sqlite3OsUnfetch(pWal->pDbFd, 0, 0); } diff --git a/test/walsetlk.test b/test/walsetlk.test new file mode 100644 index 0000000000..ff7ec18b3f --- /dev/null +++ b/test/walsetlk.test @@ -0,0 +1,75 @@ +# 2020 May 06 +# +# 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 +set testprefix walsetlk + +ifcapable !wal {finish_test ; return } +db timeout 1000 + +#------------------------------------------------------------------------- +# 1.*: Test that nothing goes wrong if recovery is forced while opening +# a write transaction or performing a checkpoint with blocking locks. +# + +do_execsql_test 1.0 { + CREATE TABLE t1(x, y); + PRAGMA journal_mode = wal; + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(3, 4); + INSERT INTO t1 VALUES(5, 6); + INSERT INTO t1 VALUES(7, 8); +} {wal} + +sqlite3 db2 test.db +db2 timeout 1000 + +do_execsql_test -db db2 1.1 { + SELECT * FROM t1 +} {1 2 3 4 5 6 7 8} + +set fd [open test.db-shm r+] +puts $fd "blahblahblahblah" +flush $fd + +do_execsql_test 1.2 { + BEGIN; + INSERT INTO t1 VALUES(9, 10); +} + +do_execsql_test -db db2 1.3 { + SELECT * FROM t1 +} {1 2 3 4 5 6 7 8} + +do_test 1.3 { + list [catch {db2 eval { BEGIN EXCLUSIVE }} msg] $msg +} {1 {database is locked}} + +do_execsql_test 1.4 { COMMIT } +do_execsql_test -db db2 1.5 { + SELECT * FROM t1 +} {1 2 3 4 5 6 7 8 9 10} + +puts $fd "blahblahblahblah" +flush $fd + +do_execsql_test -db db2 1.6 { + PRAGMA wal_checkpoint = TRUNCATE +} {0 0 0} + +do_test 1.7 { + file size test.db-wal +} 0 + +finish_test + From 861fb1e9dc039f00ff4997254b956352f37d71ac Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 6 May 2020 19:14:41 +0000 Subject: [PATCH 04/11] Block on the WRITER lock when attempting to run recovery. FossilOrigin-Name: 105d6c9bbcadc64faa2b24e315cb13227b17cfc6bf1b3512713f80ce56976a3d --- manifest | 22 +++---- manifest.uuid | 2 +- src/btree.c | 6 +- src/main.c | 4 +- src/pager.c | 17 ++++-- src/pager.h | 8 ++- src/wal.c | 163 ++++++++++++++++++++++++++++---------------------- src/wal.h | 5 +- 8 files changed, 130 insertions(+), 97 deletions(-) diff --git a/manifest b/manifest index 755c31ef40..df00f221f3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sfor\srunning\srecovery\swhen\sopening\sa\swrite\stransaction\sor\sperforming\sa\scheckpoint\swith\sblocking\slocks\senabled.\sFix\ssome\sfailing\sassert()\sstatements. -D 2020-05-06T17:18:57.298 +C Block\son\sthe\sWRITER\slock\swhen\sattempting\sto\srun\srecovery. +D 2020-05-06T19:14:41.236 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -474,7 +474,7 @@ F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c e810b07f2212f36c1f317b94bd9af818be4a0aec24e935c11c39470dcd77c149 +F src/btree.c 4d5a7d2208dd8d921049780c9f06201cd6a656822c4f0931807b54f3dcd79097 F src/btree.h 989ef3c33413549e3e148f3dcb46c030f317dac130dc86809ba6b9aa4b16c72a F src/btreeInt.h 887cdd2ea7f4a65143074a8a7c8928b0546f8c18dda3c06a408ce7992cbab0c0 F src/build.c ec6c0bda1e43ef55e5f5121a77ba19fac51fc6585f95ce2da795bcedcf6e8f36 @@ -497,7 +497,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 8e4211d04eb460c0694d486c6ba1c068d468c6f653c3f237869a802ad82854de F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 421310045bd78afefb772294a99e50f37d87ae578786a6169074e6291e30d969 -F src/main.c 5ae818ae552d3f68d1e67707a200d557125cdfb4f9e14e5cf1b4f12181974934 +F src/main.c 685d391fc37ad2c1162ad6784cae4a454dcd3632bbab319464af733d71eca72f F src/malloc.c a3e13b001f988ecec6bdb90c0ea8912c8c786e623724d7098da623d8d01d19b1 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -520,8 +520,8 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c 0e1acfbb8a75f2a4acede6078b072238df63981b172a9cd16f8b090d68291c15 F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c be4d6d58df5c5d02b84547fd253a80f035ea2ee53931a5393d96af0ba3f04edb -F src/pager.h 5e2c0e5bd32aa4ae6c25eda2722490bb3f671f24d2e5d665d33df13285c1d520 +F src/pager.c 96436cb1920074d4ade120a1a8a9d0ae3f52df06651e21b7eccc5eae2f02b111 +F src/pager.h 8d1dc9a2c3fc5eb6eeed75f48a076f425e77706f8935f05817fa05a308f587b5 F src/parse.y c8eff38606f443d5ba245263fa7abc05e4116d95656e050c4b78e9bfbf931add F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 @@ -617,8 +617,8 @@ F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143 F src/vdbevtab.c 8094dfc28dad82d60a1c832020a1b201a5381dc185c14638affc6d4e9d54c653 F src/vtab.c 7b704a90515a239c6cdba6a66b1bb3a385e62326cceb5ecb05ec7a091d6b8515 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 9cf3f288cd4e48b49725e03037b60246a154ca8775892c75c319db8f5652ae8a -F src/wal.h 484890eaaefb89c0f2043ae34c20bf367383f201f63da631ecae424797a7f60d +F src/wal.c d23410a4330d11b8c699e0e463f334f2fca6c5af2c144e34674ccaef5b73f8fc +F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7c429c694abd12413a5c17aec9f47cfe9eba6807e6b0a32df883e8e3a14835ed F src/where.c 9546c82056e8cdb27291f98cf1adca5d271240b399bb97b32f77fc2bea6146c9 F src/whereInt.h 6b874aa15f94e43a2cec1080be64d955b04deeafeac90ffb5d6975c0d511be3c @@ -1864,7 +1864,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 a3727dba10b476f414f0a049b35f2a5c169a408eccefa6833821560684e07f8b -R e1d7b36a881e7c026e918bb1e2d9268d +P d096ea3fe20f8af90f9e3f798fd0a69527b32ac8e208ade58b9d0af0e831f41b +R 452bcfebade640ff986656d7117060f0 U dan -Z 92e7a8a964d43aa5533a6dd765b70a70 +Z 21f20f1df91440f33362da9da7770293 diff --git a/manifest.uuid b/manifest.uuid index 78c3a449bb..1ed2372a34 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d096ea3fe20f8af90f9e3f798fd0a69527b32ac8e208ade58b9d0af0e831f41b \ No newline at end of file +105d6c9bbcadc64faa2b24e315cb13227b17cfc6bf1b3512713f80ce56976a3d \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index e80add6eb4..47b1136fd7 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3442,9 +3442,10 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ #ifdef SQLITE_ENABLE_SETLK_TIMEOUT /* If transitioning from no transaction directly to a write transaction, ** block for the WRITER lock first if possible. */ + sqlite3PagerWalDb(pPager, p->db); if( pBt->pPage1==0 && wrflag ){ assert( pBt->inTransaction==TRANS_NONE ); - rc = sqlite3PagerWalWriteLock(p->db, pPager, 1); + rc = sqlite3PagerWalWriteLock(pPager, 1); if( rc!=SQLITE_OK ) break; } #endif @@ -3475,9 +3476,10 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ } if( rc!=SQLITE_OK ){ - sqlite3PagerWalWriteLock(p->db, pPager, 0); + sqlite3PagerWalWriteLock(pPager, 0); unlockBtreeIfUnused(pBt); } + sqlite3PagerWalDb(pPager, 0); }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && btreeInvokeBusyHandler(pBt) ); diff --git a/src/main.c b/src/main.c index e96f5e1133..0bc8edfec0 100644 --- a/src/main.c +++ b/src/main.c @@ -4481,11 +4481,11 @@ int sqlite3_snapshot_open( rc = SQLITE_OK; } if( rc==SQLITE_OK ){ - rc = sqlite3PagerSnapshotOpen(pPager, db, pSnapshot); + rc = sqlite3PagerSnapshotOpen(pPager, pSnapshot); } if( rc==SQLITE_OK ){ rc = sqlite3BtreeBeginTrans(pBt, 0, 0); - sqlite3PagerSnapshotOpen(pPager, 0, 0); + sqlite3PagerSnapshotOpen(pPager, 0); } if( bUnlock ){ sqlite3PagerSnapshotUnlock(pPager); diff --git a/src/pager.c b/src/pager.c index 1570b3e704..a826f256bf 100644 --- a/src/pager.c +++ b/src/pager.c @@ -7581,13 +7581,23 @@ int sqlite3PagerCloseWal(Pager *pPager, sqlite3 *db){ ** with the same db and bLock parameters as were passed to this function. ** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise. */ -int sqlite3PagerWalWriteLock(sqlite3 *db, Pager *pPager, int bLock){ +int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){ int rc = SQLITE_OK; if( pagerUseWal(pPager) && pPager->exclusiveMode==0 ){ - rc = sqlite3WalWriteLock(db, pPager->pWal, bLock); + rc = sqlite3WalWriteLock(pPager->pWal, bLock); } return rc; } + +/* +** Set the database handle used by the wal layer to determine if +** blocking locks are required. +*/ +void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){ + if( pagerUseWal(pPager) ){ + sqlite3WalDb(pPager->pWal, db); + } +} #endif #ifdef SQLITE_ENABLE_SNAPSHOT @@ -7610,12 +7620,11 @@ int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot){ */ int sqlite3PagerSnapshotOpen( Pager *pPager, - sqlite3 *db, sqlite3_snapshot *pSnapshot ){ int rc = SQLITE_OK; if( pPager->pWal ){ - sqlite3WalSnapshotOpen(pPager->pWal, db, pSnapshot); + sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot); }else{ rc = SQLITE_ERROR; } diff --git a/src/pager.h b/src/pager.h index c203908c83..62a371ef89 100644 --- a/src/pager.h +++ b/src/pager.h @@ -178,7 +178,7 @@ int sqlite3PagerSharedLock(Pager *pPager); int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); # ifdef SQLITE_ENABLE_SNAPSHOT int sqlite3PagerSnapshotGet(Pager*, sqlite3_snapshot **ppSnapshot); - int sqlite3PagerSnapshotOpen(Pager*, sqlite3*, sqlite3_snapshot *pSnapshot); + int sqlite3PagerSnapshotOpen(Pager*, sqlite3_snapshot *pSnapshot); int sqlite3PagerSnapshotRecover(Pager *pPager); int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot); void sqlite3PagerSnapshotUnlock(Pager *pPager); @@ -186,9 +186,11 @@ int sqlite3PagerSharedLock(Pager *pPager); #endif #if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_ENABLE_SETLK_TIMEOUT) - int sqlite3PagerWalWriteLock(sqlite3*, Pager*, int); + int sqlite3PagerWalWriteLock(Pager*, int); + void sqlite3PagerWalDb(Pager*, sqlite3*); #else -# define sqlite3PagerWalWriteLock(x,y,z) SQLITE_OK +# define sqlite3PagerWalWriteLock(y,z) SQLITE_OK +# define sqlite3PagerWalDb(x,y) #endif #ifdef SQLITE_DIRECT_OVERFLOW_READ diff --git a/src/wal.c b/src/wal.c index 7abff64078..41a11d6548 100644 --- a/src/wal.c +++ b/src/wal.c @@ -466,9 +466,9 @@ struct Wal { #endif #ifdef SQLITE_ENABLE_SNAPSHOT WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */ -# ifdef SQLITE_ENABLE_SETLK_TIMEOUT - sqlite3 *dbSnapshot; -# endif +#endif +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + sqlite3 *db; #endif }; @@ -2118,6 +2118,88 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){ */ #define WAL_RETRY (-1) +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT +/* +** Attempt to enable blocking locks. Blocking locks are enabled only if (a) +** they are supported by the VFS, and (b) the database handle is configured +** with a busy-timeout. Return 1 if blocking locks are successfully enabled, +** or 0 otherwise. +*/ +static int walEnableBlocking(Wal *pWal){ + int res = 0; + if( pWal->db ){ + int tmout = pWal->db->busyTimeout; + if( tmout ){ + int rc; + rc = sqlite3OsFileControl( + pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout + ); + res = (rc==SQLITE_OK); + } + } + return res; +} + +/* +** Disable blocking locks. +*/ +static void walDisableBlocking(Wal *pWal){ + int tmout = 0; + sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); +} + +/* +** If parameter bLock is true, attempt to enable blocking locks, take +** the WRITER lock, and then disable blocking locks. If blocking locks +** cannot be enabled, no attempt to obtain the WRITER lock is made. Return +** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not +** an error if blocking locks can not be enabled. +** +** If the bLock parameter is false and the WRITER lock is held, release it. +*/ +int sqlite3WalWriteLock(Wal *pWal, int bLock){ + int rc = SQLITE_OK; + assert( pWal->readLock<0 || bLock==0 ); + if( bLock ){ + assert( pWal->db ); + if( walEnableBlocking(pWal) ){ + rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); + if( rc==SQLITE_OK ){ + pWal->writeLock = 1; + } + walDisableBlocking(pWal); + } + }else if( pWal->writeLock ){ + walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); + pWal->writeLock = 0; + } + return rc; +} + +/* +** Set the database handle used to determine if blocking locks are required. +*/ +void sqlite3WalDb(Wal *pWal, sqlite3 *db){ + pWal->db = db; +} + +/* +** Take an exclusive WRITE lock. Blocking if so configured. +*/ +static int walLockWriter(Wal *pWal){ + int rc; + walEnableBlocking(pWal); + rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); + walDisableBlocking(pWal); + return rc; +} +#else +# define walEnableBlocking(x) 0 +# define walDisableBlocking(x) +# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1) +# define sqlite3WalDb(pWal) +#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */ + /* ** Read the wal-index header from the wal-index and into pWal->hdr. ** If the wal-header appears to be corrupt, try to reconstruct the @@ -2183,9 +2265,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){ } }else{ int bWriteLock = pWal->writeLock; - if( bWriteLock - || SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) - ){ + if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){ pWal->writeLock = 1; if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){ badHdr = walIndexTryHdr(pWal, pChanged); @@ -2737,65 +2817,6 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ } #endif /* SQLITE_ENABLE_SNAPSHOT */ -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT -/* -** Attempt to enable blocking locks. Blocking locks are enabled only if (a) -** they are supported by the VFS, and (b) the database handle is configured -** with a busy-timeout. Return 1 if blocking locks are successfully enabled, -** or 0 otherwise. -*/ -static int walEnableBlocking(sqlite3 *db, Wal *pWal){ - int res = 0; - if( db->busyTimeout ){ - int rc; - int tmout = db->busyTimeout; - rc = sqlite3OsFileControl( - pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout - ); - res = (rc==SQLITE_OK); - } - return res; -} - -/* -** Disable blocking locks. -*/ -static void walDisableBlocking(Wal *pWal){ - int tmout = 0; - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); -} - -/* -** If parameter bLock is true, attempt to enable blocking locks, take -** the WRITER lock, and then disable blocking locks. If blocking locks -** cannot be enabled, no attempt to obtain the WRITER lock is made. Return -** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not -** an error if blocking locks can not be enabled. -** -** If the bLock parameter is false and the WRITER lock is held, release it. -*/ -int sqlite3WalWriteLock(sqlite3 *db, Wal *pWal, int bLock){ - int rc = SQLITE_OK; - assert( pWal->readLock<0 || bLock==0 ); - if( bLock ){ - if( walEnableBlocking(db, pWal) ){ - rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); - if( rc==SQLITE_OK ){ - pWal->writeLock = 1; - } - walDisableBlocking(pWal); - } - }else if( pWal->writeLock ){ - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - pWal->writeLock = 0; - } - return rc; -} -#else -# define walEnableBlocking(x,y) 0 -# define walDisableBlocking(x) -#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */ - /* ** Begin a read transaction on the database. ** @@ -2832,7 +2853,7 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ ** its intent. To avoid the race condition this leads to, ensure that ** there is no checkpointer process by taking a shared CKPT lock ** before checking pInfo->nBackfillAttempted. */ - walEnableBlocking(pWal->dbSnapshot, pWal); + walEnableBlocking(pWal); rc = walLockShared(pWal, WAL_CKPT_LOCK); walDisableBlocking(pWal); @@ -3666,7 +3687,8 @@ int sqlite3WalCheckpoint( /* Enable blocking locks, if possible. If blocking locks are successfully ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */ - if( walEnableBlocking(db, pWal) ){ + sqlite3WalDb(pWal, db); + if( walEnableBlocking(pWal) ){ xBusy2 = 0; } @@ -3710,7 +3732,7 @@ int sqlite3WalCheckpoint( if( rc==SQLITE_OK ){ walDisableBlocking(pWal); rc = walIndexReadHdr(pWal, &isChanged); - walEnableBlocking(db, pWal); + walEnableBlocking(pWal); if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ sqlite3OsUnfetch(pWal->pDbFd, 0, 0); } @@ -3743,6 +3765,7 @@ int sqlite3WalCheckpoint( } walDisableBlocking(pWal); + sqlite3WalDb(pWal, 0); /* Release the locks. */ sqlite3WalEndWriteTransaction(pWal); @@ -3869,13 +3892,9 @@ int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot){ */ void sqlite3WalSnapshotOpen( Wal *pWal, - sqlite3 *db, sqlite3_snapshot *pSnapshot ){ pWal->pSnapshot = (WalIndexHdr*)pSnapshot; -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT - pWal->dbSnapshot = db; -#endif } /* diff --git a/src/wal.h b/src/wal.h index 99ebc937af..02e2bab360 100644 --- a/src/wal.h +++ b/src/wal.h @@ -130,7 +130,7 @@ int sqlite3WalHeapMemory(Wal *pWal); #ifdef SQLITE_ENABLE_SNAPSHOT int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot); -void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3*, sqlite3_snapshot *pSnapshot); +void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot); int sqlite3WalSnapshotRecover(Wal *pWal); int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot); void sqlite3WalSnapshotUnlock(Wal *pWal); @@ -147,7 +147,8 @@ int sqlite3WalFramesize(Wal *pWal); sqlite3_file *sqlite3WalFile(Wal *pWal); #ifdef SQLITE_ENABLE_SETLK_TIMEOUT -int sqlite3WalWriteLock(sqlite3 *db, Wal *pWal, int bLock); +int sqlite3WalWriteLock(Wal *pWal, int bLock); +void sqlite3WalDb(Wal *pWal, sqlite3 *db); #endif #endif /* ifndef SQLITE_OMIT_WAL */ From fc87ab8c4ab229a2adae3297148eb3ebdad1134f Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 6 May 2020 19:22:59 +0000 Subject: [PATCH 05/11] Fix compiler warnings in non-SQLITE_ENABLE_SETLK_TIMEOUT builds. FossilOrigin-Name: 22de99ef410ba2a540871f3e61157d8dc4b969416f14808aeca73971b17fcd51 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/btree.c | 2 +- src/wal.c | 6 +++--- test/walsetlk.test | 10 +++++----- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/manifest b/manifest index df00f221f3..a5993cb39a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Block\son\sthe\sWRITER\slock\swhen\sattempting\sto\srun\srecovery. -D 2020-05-06T19:14:41.236 +C Fix\scompiler\swarnings\sin\snon-SQLITE_ENABLE_SETLK_TIMEOUT\sbuilds. +D 2020-05-06T19:22:59.197 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -474,7 +474,7 @@ F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 4d5a7d2208dd8d921049780c9f06201cd6a656822c4f0931807b54f3dcd79097 +F src/btree.c 98e6ff5f2f0ad531bc3f7c0be1e7c8b51339b9b1badc98da141c5e0f8ed3c9b3 F src/btree.h 989ef3c33413549e3e148f3dcb46c030f317dac130dc86809ba6b9aa4b16c72a F src/btreeInt.h 887cdd2ea7f4a65143074a8a7c8928b0546f8c18dda3c06a408ce7992cbab0c0 F src/build.c ec6c0bda1e43ef55e5f5121a77ba19fac51fc6585f95ce2da795bcedcf6e8f36 @@ -617,7 +617,7 @@ F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143 F src/vdbevtab.c 8094dfc28dad82d60a1c832020a1b201a5381dc185c14638affc6d4e9d54c653 F src/vtab.c 7b704a90515a239c6cdba6a66b1bb3a385e62326cceb5ecb05ec7a091d6b8515 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c d23410a4330d11b8c699e0e463f334f2fca6c5af2c144e34674ccaef5b73f8fc +F src/wal.c 24566cac365e172a893f18a83fd6da8c4b9cfbbae118831a43b4ef427e21b710 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7c429c694abd12413a5c17aec9f47cfe9eba6807e6b0a32df883e8e3a14835ed F src/where.c 9546c82056e8cdb27291f98cf1adca5d271240b399bb97b32f77fc2bea6146c9 @@ -1689,7 +1689,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 -F test/walsetlk.test 9da1ee8a18b0416a5ce1914331c1303bcb6cb7bac905eb660f788f023718d8f4 +F test/walsetlk.test e919d2aab59185a554c170599ae28d46da2f085e2026d54ee2da799f9f328478 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747 @@ -1864,7 +1864,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 d096ea3fe20f8af90f9e3f798fd0a69527b32ac8e208ade58b9d0af0e831f41b -R 452bcfebade640ff986656d7117060f0 +P 105d6c9bbcadc64faa2b24e315cb13227b17cfc6bf1b3512713f80ce56976a3d +R 2005d6d3ddc777ab35d452dcb8060dbf U dan -Z 21f20f1df91440f33362da9da7770293 +Z 02001fbe394dba3af87ef0d8d6630ccb diff --git a/manifest.uuid b/manifest.uuid index 1ed2372a34..e7963e04d3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -105d6c9bbcadc64faa2b24e315cb13227b17cfc6bf1b3512713f80ce56976a3d \ No newline at end of file +22de99ef410ba2a540871f3e61157d8dc4b969416f14808aeca73971b17fcd51 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 47b1136fd7..47585f1a37 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3476,7 +3476,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ } if( rc!=SQLITE_OK ){ - sqlite3PagerWalWriteLock(pPager, 0); + (void)sqlite3PagerWalWriteLock(pPager, 0); unlockBtreeIfUnused(pBt); } sqlite3PagerWalDb(pPager, 0); diff --git a/src/wal.c b/src/wal.c index 41a11d6548..c348f0f38b 100644 --- a/src/wal.c +++ b/src/wal.c @@ -2197,7 +2197,7 @@ static int walLockWriter(Wal *pWal){ # define walEnableBlocking(x) 0 # define walDisableBlocking(x) # define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1) -# define sqlite3WalDb(pWal) +# define sqlite3WalDb(pWal, db) #endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */ /* @@ -2853,7 +2853,7 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ ** its intent. To avoid the race condition this leads to, ensure that ** there is no checkpointer process by taking a shared CKPT lock ** before checking pInfo->nBackfillAttempted. */ - walEnableBlocking(pWal); + (void)walEnableBlocking(pWal); rc = walLockShared(pWal, WAL_CKPT_LOCK); walDisableBlocking(pWal); @@ -3732,7 +3732,7 @@ int sqlite3WalCheckpoint( if( rc==SQLITE_OK ){ walDisableBlocking(pWal); rc = walIndexReadHdr(pWal, &isChanged); - walEnableBlocking(pWal); + (void)walEnableBlocking(pWal); if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ sqlite3OsUnfetch(pWal->pDbFd, 0, 0); } diff --git a/test/walsetlk.test b/test/walsetlk.test index ff7ec18b3f..7964caa055 100644 --- a/test/walsetlk.test +++ b/test/walsetlk.test @@ -51,23 +51,23 @@ do_execsql_test -db db2 1.3 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8} -do_test 1.3 { +do_test 1.4 { list [catch {db2 eval { BEGIN EXCLUSIVE }} msg] $msg } {1 {database is locked}} -do_execsql_test 1.4 { COMMIT } -do_execsql_test -db db2 1.5 { +do_execsql_test 1.5 { COMMIT } +do_execsql_test -db db2 1.6 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8 9 10} puts $fd "blahblahblahblah" flush $fd -do_execsql_test -db db2 1.6 { +do_execsql_test -db db2 1.7 { PRAGMA wal_checkpoint = TRUNCATE } {0 0 0} -do_test 1.7 { +do_test 1.8 { file size test.db-wal } 0 From 7bb8b8a4f743c1bab707a01ba61c7f1fe3695195 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 6 May 2020 20:27:18 +0000 Subject: [PATCH 06/11] Add error code SQLITE_BUSY_TIMEOUT, used internally by the OS layer to indicate that a call to xShmLock() has failed due to timeout of a blocking lock. FossilOrigin-Name: f3ef9c7c2b4ba3de1057ad569f068b241d5f23e6629d8e0dacf85e57fd13b8aa --- manifest | 20 ++--- manifest.uuid | 2 +- src/btree.c | 15 ++-- src/os_unix.c | 12 ++- src/sqlite.h.in | 1 + src/wal.c | 182 +++++++++++++++++++++++---------------------- test/walsetlk.test | 109 +++++++++++++++++++++++++++ 7 files changed, 233 insertions(+), 108 deletions(-) diff --git a/manifest b/manifest index a5993cb39a..7a33b8fa5a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\scompiler\swarnings\sin\snon-SQLITE_ENABLE_SETLK_TIMEOUT\sbuilds. -D 2020-05-06T19:22:59.197 +C Add\serror\scode\sSQLITE_BUSY_TIMEOUT,\sused\sinternally\sby\sthe\sOS\slayer\sto\sindicate\sthat\sa\scall\sto\sxShmLock()\shas\sfailed\sdue\sto\stimeout\sof\sa\sblocking\slock. +D 2020-05-06T20:27:18.129 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -474,7 +474,7 @@ F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 98e6ff5f2f0ad531bc3f7c0be1e7c8b51339b9b1badc98da141c5e0f8ed3c9b3 +F src/btree.c f0cd4a3683b60f456f17e28f24cc72febc0df9c3f3f5126d799f9dc9ee5844b6 F src/btree.h 989ef3c33413549e3e148f3dcb46c030f317dac130dc86809ba6b9aa4b16c72a F src/btreeInt.h 887cdd2ea7f4a65143074a8a7c8928b0546f8c18dda3c06a408ce7992cbab0c0 F src/build.c ec6c0bda1e43ef55e5f5121a77ba19fac51fc6585f95ce2da795bcedcf6e8f36 @@ -517,7 +517,7 @@ F src/os.c 669cc3839cc35d20f81faf0be1ab6d4581cea35e9d8f3a9d48a98d6571f7c285 F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c 0e1acfbb8a75f2a4acede6078b072238df63981b172a9cd16f8b090d68291c15 +F src/os_unix.c ad4f910fd62b83c57dad364913d29a554a694a4461f489c2208306c63ce6eda2 F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 96436cb1920074d4ade120a1a8a9d0ae3f52df06651e21b7eccc5eae2f02b111 @@ -535,7 +535,7 @@ F src/resolve.c d36a2b1639e1c33d7b508abfd3452a63e7fd81737f6f3940bfef085fca6f21f4 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 1720bff2168491ca79af81a03bd18c0383f61d845c6e17caff9d25aabc4ab435 F src/shell.c.in cf2d24f54412c06e5fb34af7fabc748651125e1dceac29b740e91f06d23447b6 -F src/sqlite.h.in fa97fb128377b8fd8398a498eda3d48646b08519c4176adb1457243fdc5bb09a +F src/sqlite.h.in a42bae930f462294801f24468dd56832b09de01072a26dc0df60ddc3c5602210 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197 F src/sqliteInt.h 26de171e0adccf6e465434b9fcce18fcfcc757e9a727356b029fc1676639540c @@ -617,7 +617,7 @@ F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143 F src/vdbevtab.c 8094dfc28dad82d60a1c832020a1b201a5381dc185c14638affc6d4e9d54c653 F src/vtab.c 7b704a90515a239c6cdba6a66b1bb3a385e62326cceb5ecb05ec7a091d6b8515 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 24566cac365e172a893f18a83fd6da8c4b9cfbbae118831a43b4ef427e21b710 +F src/wal.c f4eda6e6886da4c93e679210b14b75435d0087756644179b01896e485dd32677 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7c429c694abd12413a5c17aec9f47cfe9eba6807e6b0a32df883e8e3a14835ed F src/where.c 9546c82056e8cdb27291f98cf1adca5d271240b399bb97b32f77fc2bea6146c9 @@ -1689,7 +1689,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 -F test/walsetlk.test e919d2aab59185a554c170599ae28d46da2f085e2026d54ee2da799f9f328478 +F test/walsetlk.test 5c8bd1832a828db71283c03dc4a74d648c5333a5b2e978f5bda4f0d81bae5490 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747 @@ -1864,7 +1864,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 105d6c9bbcadc64faa2b24e315cb13227b17cfc6bf1b3512713f80ce56976a3d -R 2005d6d3ddc777ab35d452dcb8060dbf +P 22de99ef410ba2a540871f3e61157d8dc4b969416f14808aeca73971b17fcd51 +R e0fe78ea85289605bc2618d432bfef86 U dan -Z 02001fbe394dba3af87ef0d8d6630ccb +Z f7eb10852628454cfaa15a83f2d2254d diff --git a/manifest.uuid b/manifest.uuid index e7963e04d3..b5754b7308 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -22de99ef410ba2a540871f3e61157d8dc4b969416f14808aeca73971b17fcd51 \ No newline at end of file +f3ef9c7c2b4ba3de1057ad569f068b241d5f23e6629d8e0dacf85e57fd13b8aa \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 47585f1a37..8ac3374dd4 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3374,6 +3374,7 @@ int sqlite3BtreeNewDb(Btree *p){ */ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ BtShared *pBt = p->pBt; + Pager *pPager = pBt->pPager; int rc = SQLITE_OK; sqlite3BtreeEnter(p); @@ -3389,7 +3390,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 ); if( (p->db->flags & SQLITE_ResetDatabase) - && sqlite3PagerIsreadonly(pBt->pPager)==0 + && sqlite3PagerIsreadonly(pPager)==0 ){ pBt->btsFlags &= ~BTS_READ_ONLY; } @@ -3436,17 +3437,16 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ pBt->btsFlags &= ~BTS_INITIALLY_EMPTY; if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY; + sqlite3PagerWalDb(pPager, p->db); do { - Pager *pPager = pBt->pPager; #ifdef SQLITE_ENABLE_SETLK_TIMEOUT /* If transitioning from no transaction directly to a write transaction, ** block for the WRITER lock first if possible. */ - sqlite3PagerWalDb(pPager, p->db); if( pBt->pPage1==0 && wrflag ){ assert( pBt->inTransaction==TRANS_NONE ); rc = sqlite3PagerWalWriteLock(pPager, 1); - if( rc!=SQLITE_OK ) break; + if( rc!=SQLITE_BUSY && rc!=SQLITE_OK ) break; } #endif @@ -3479,9 +3479,12 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ (void)sqlite3PagerWalWriteLock(pPager, 0); unlockBtreeIfUnused(pBt); } - sqlite3PagerWalDb(pPager, 0); }while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && btreeInvokeBusyHandler(pBt) ); + sqlite3PagerWalDb(pPager, 0); +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY; +#endif if( rc==SQLITE_OK ){ if( p->inTrans==TRANS_NONE ){ @@ -3533,7 +3536,7 @@ trans_begun: ** open savepoints. If the second parameter is greater than 0 and ** the sub-journal is not already open, then it will be opened here. */ - rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint); + rc = sqlite3PagerOpenSavepoint(pPager, p->db->nSavepoint); } } diff --git a/src/os_unix.c b/src/os_unix.c index 72c446ea77..fb172e7218 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1565,8 +1565,9 @@ static int osSetPosixAdvisoryLock( struct flock *pLock, /* The description of the lock */ unixFile *pFile /* Structure holding timeout value */ ){ + int tm = pFile->iBusyTimeout; int rc = osFcntl(h,F_SETLK,pLock); - while( rc<0 && pFile->iBusyTimeout>0 ){ + while( rc<0 && tm>0 ){ /* On systems that support some kind of blocking file lock with a timeout, ** make appropriate changes here to invoke that blocking file lock. On ** generic posix, however, there is no such API. So we simply try the @@ -1574,7 +1575,7 @@ static int osSetPosixAdvisoryLock( ** the lock is obtained. */ usleep(1000); rc = osFcntl(h,F_SETLK,pLock); - pFile->iBusyTimeout--; + tm--; } return rc; } @@ -4316,13 +4317,16 @@ static int unixShmSystemLock( assert( n>=1 && n<=SQLITE_SHM_NLOCK ); if( pShmNode->hShm>=0 ){ + int res; /* Initialize the locking parameters */ f.l_type = lockType; f.l_whence = SEEK_SET; f.l_start = ofst; f.l_len = n; - rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile); - rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY; + res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile); + if( res==-1 ){ + rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY); + } } /* Update the global lock state and do debug tracing */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index aa0ac9b0ff..90544db29e 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -508,6 +508,7 @@ int sqlite3_exec( #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) +#define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) diff --git a/src/wal.c b/src/wal.c index c348f0f38b..d9e9ef177c 100644 --- a/src/wal.c +++ b/src/wal.c @@ -843,7 +843,7 @@ static int walLockShared(Wal *pWal, int lockIdx){ SQLITE_SHM_LOCK | SQLITE_SHM_SHARED); WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, walLockName(lockIdx), rc ? "failed" : "ok")); - VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); ) + VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) return rc; } static void walUnlockShared(Wal *pWal, int lockIdx){ @@ -859,7 +859,7 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){ SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE); 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!=SQLITE_BUSY); ) + VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) return rc; } static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){ @@ -1679,6 +1679,89 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ return rc; } +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT +/* +** Attempt to enable blocking locks. Blocking locks are enabled only if (a) +** they are supported by the VFS, and (b) the database handle is configured +** with a busy-timeout. Return 1 if blocking locks are successfully enabled, +** or 0 otherwise. +*/ +static int walEnableBlocking(Wal *pWal){ + int res = 0; + if( pWal->db ){ + int tmout = pWal->db->busyTimeout; + if( tmout ){ + int rc; + rc = sqlite3OsFileControl( + pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout + ); + res = (rc==SQLITE_OK); + } + } + return res; +} + +/* +** Disable blocking locks. +*/ +static void walDisableBlocking(Wal *pWal){ + int tmout = 0; + sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); +} + +/* +** If parameter bLock is true, attempt to enable blocking locks, take +** the WRITER lock, and then disable blocking locks. If blocking locks +** cannot be enabled, no attempt to obtain the WRITER lock is made. Return +** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not +** an error if blocking locks can not be enabled. +** +** If the bLock parameter is false and the WRITER lock is held, release it. +*/ +int sqlite3WalWriteLock(Wal *pWal, int bLock){ + int rc = SQLITE_OK; + assert( pWal->readLock<0 || bLock==0 ); + if( bLock ){ + assert( pWal->db ); + if( walEnableBlocking(pWal) ){ + rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); + if( rc==SQLITE_OK ){ + pWal->writeLock = 1; + } + walDisableBlocking(pWal); + } + }else if( pWal->writeLock ){ + walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); + pWal->writeLock = 0; + } + return rc; +} + +/* +** Set the database handle used to determine if blocking locks are required. +*/ +void sqlite3WalDb(Wal *pWal, sqlite3 *db){ + pWal->db = db; +} + +/* +** Take an exclusive WRITE lock. Blocking if so configured. +*/ +static int walLockWriter(Wal *pWal){ + int rc; + walEnableBlocking(pWal); + rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); + walDisableBlocking(pWal); + return rc; +} +#else +# define walEnableBlocking(x) 0 +# define walDisableBlocking(x) +# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1) +# define sqlite3WalDb(pWal, db) +#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */ + + /* ** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and ** n. If the attempt fails and parameter xBusy is not NULL, then it is a @@ -1696,6 +1779,12 @@ static int walBusyLock( do { rc = walLockExclusive(pWal, lockIdx, n); }while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) ); +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + if( rc==SQLITE_BUSY_TIMEOUT ){ + walDisableBlocking(pWal); + rc = SQLITE_BUSY; + } +#endif return rc; } @@ -2118,88 +2207,6 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){ */ #define WAL_RETRY (-1) -#ifdef SQLITE_ENABLE_SETLK_TIMEOUT -/* -** Attempt to enable blocking locks. Blocking locks are enabled only if (a) -** they are supported by the VFS, and (b) the database handle is configured -** with a busy-timeout. Return 1 if blocking locks are successfully enabled, -** or 0 otherwise. -*/ -static int walEnableBlocking(Wal *pWal){ - int res = 0; - if( pWal->db ){ - int tmout = pWal->db->busyTimeout; - if( tmout ){ - int rc; - rc = sqlite3OsFileControl( - pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout - ); - res = (rc==SQLITE_OK); - } - } - return res; -} - -/* -** Disable blocking locks. -*/ -static void walDisableBlocking(Wal *pWal){ - int tmout = 0; - sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout); -} - -/* -** If parameter bLock is true, attempt to enable blocking locks, take -** the WRITER lock, and then disable blocking locks. If blocking locks -** cannot be enabled, no attempt to obtain the WRITER lock is made. Return -** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not -** an error if blocking locks can not be enabled. -** -** If the bLock parameter is false and the WRITER lock is held, release it. -*/ -int sqlite3WalWriteLock(Wal *pWal, int bLock){ - int rc = SQLITE_OK; - assert( pWal->readLock<0 || bLock==0 ); - if( bLock ){ - assert( pWal->db ); - if( walEnableBlocking(pWal) ){ - rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); - if( rc==SQLITE_OK ){ - pWal->writeLock = 1; - } - walDisableBlocking(pWal); - } - }else if( pWal->writeLock ){ - walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); - pWal->writeLock = 0; - } - return rc; -} - -/* -** Set the database handle used to determine if blocking locks are required. -*/ -void sqlite3WalDb(Wal *pWal, sqlite3 *db){ - pWal->db = db; -} - -/* -** Take an exclusive WRITE lock. Blocking if so configured. -*/ -static int walLockWriter(Wal *pWal){ - int rc; - walEnableBlocking(pWal); - rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1); - walDisableBlocking(pWal); - return rc; -} -#else -# define walEnableBlocking(x) 0 -# define walDisableBlocking(x) -# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1) -# define sqlite3WalDb(pWal, db) -#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */ - /* ** Read the wal-index header from the wal-index and into pWal->hdr. ** If the wal-header appears to be corrupt, try to reconstruct the @@ -3688,9 +3695,7 @@ int sqlite3WalCheckpoint( /* Enable blocking locks, if possible. If blocking locks are successfully ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */ sqlite3WalDb(pWal, db); - if( walEnableBlocking(pWal) ){ - xBusy2 = 0; - } + walEnableBlocking(pWal); /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive ** "checkpoint" lock on the database file. @@ -3774,6 +3779,9 @@ int sqlite3WalCheckpoint( pWal->ckptLock = 0; } WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok")); +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT + if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY; +#endif return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc); } diff --git a/test/walsetlk.test b/test/walsetlk.test index 7964caa055..635839c0cf 100644 --- a/test/walsetlk.test +++ b/test/walsetlk.test @@ -12,6 +12,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +source $testdir/lock_common.tcl set testprefix walsetlk ifcapable !wal {finish_test ; return } @@ -71,5 +72,113 @@ do_test 1.8 { file size test.db-wal } 0 +db close +db2 close +#------------------------------------------------------------------------- + +do_multiclient_test tn { + + do_test 2.$tn.1 { + sql1 { + PRAGMA journal_mode = wal; + CREATE TABLE t1(s, v); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(3, 4); + INSERT INTO t1 VALUES(5, 6); + } + code1 { db timeout 2000 } + } {} + + do_test 2.$tn.2 { + sql2 { + BEGIN; + INSERT INTO t1 VALUES(7, 8); + } + } {} + + do_test 2.$tn.3 { + set us [lindex [time { catch {db eval "BEGIN EXCLUSIVE"} }] 0] + expr $us>1000000 && $us<4000000 + } {1} + + do_test 2.$tn.4 { + sql2 { COMMIT } + sql1 { SELECT * FROM t1 } + } {1 2 3 4 5 6 7 8} + + do_test 2.$tn.5 { + sql2 { + BEGIN; + INSERT INTO t1 VALUES(9, 10); + } + } {} + + do_test 2.$tn.6 { + set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0] + expr $us>1000000 && $us<4000000 + } {1} + + do_test 2.$tn.7 { + sql2 { + COMMIT; + BEGIN; + SELECT * FROM t1; + } + } {1 2 3 4 5 6 7 8 9 10} + + do_test 2.$tn.8 { + set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0] + expr $us>1000000 && $us<4000000 + } {1} + + do_test 2.$tn.9 { + sql3 { + INSERT INTO t1 VALUES(11, 12); + } + sql2 { + COMMIT; + BEGIN; + SELECT * FROM t1; + } + sql3 { + INSERT INTO t1 VALUES(13, 14); + } + } {} + + do_test 2.$tn.10 { + set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0] + expr $us>1000000 && $us<4000000 + } {1} + + do_test 2.$tn.11 { + sql3 { + BEGIN; + SELECT * FROM t1; + } + sql1 { INSERT INTO t1 VALUES(15, 16); } + } {} + + do_test 2.$tn.12 { + set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0] + expr $us>1000000 && $us<4000000 + } {1} + + do_test 2.$tn.13 { + sql2 { + COMMIT; + BEGIN; + SELECT * FROM t1; + } + sql1 { INSERT INTO t1 VALUES(17, 18); } + } {} + + do_test 2.$tn.14 { + set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0] + puts $us + expr $us>1000000 && $us<4000000 + } {1} + +} + finish_test From 7a623e1d25f471394ac5550c6eac496ac70fbc1d Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 6 May 2020 20:45:11 +0000 Subject: [PATCH 07/11] Fix a problem preventing building without SQLITE_ENABLE_SETLK_TIMEOUT defined. FossilOrigin-Name: 98eb54c6d83992886f17a00b6fc8998df230e3b5f45bafc6fae0d15a9ee5a4c6 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/os_unix.c | 4 ++++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 7a33b8fa5a..0a7ef8f8c7 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\serror\scode\sSQLITE_BUSY_TIMEOUT,\sused\sinternally\sby\sthe\sOS\slayer\sto\sindicate\sthat\sa\scall\sto\sxShmLock()\shas\sfailed\sdue\sto\stimeout\sof\sa\sblocking\slock. -D 2020-05-06T20:27:18.129 +C Fix\sa\sproblem\spreventing\sbuilding\swithout\sSQLITE_ENABLE_SETLK_TIMEOUT\sdefined. +D 2020-05-06T20:45:11.359 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -517,7 +517,7 @@ F src/os.c 669cc3839cc35d20f81faf0be1ab6d4581cea35e9d8f3a9d48a98d6571f7c285 F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432 F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85 F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 -F src/os_unix.c ad4f910fd62b83c57dad364913d29a554a694a4461f489c2208306c63ce6eda2 +F src/os_unix.c 13f983da988b6460ef3c4c22099c67ab0938291e543644ac4d99eccc8ba604f1 F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 96436cb1920074d4ade120a1a8a9d0ae3f52df06651e21b7eccc5eae2f02b111 @@ -1864,7 +1864,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 22de99ef410ba2a540871f3e61157d8dc4b969416f14808aeca73971b17fcd51 -R e0fe78ea85289605bc2618d432bfef86 +P f3ef9c7c2b4ba3de1057ad569f068b241d5f23e6629d8e0dacf85e57fd13b8aa +R 300add0d813f0b2aa21b7602c0922ab2 U dan -Z f7eb10852628454cfaa15a83f2d2254d +Z 6ae115939550b6311fe0efe8d583ce34 diff --git a/manifest.uuid b/manifest.uuid index b5754b7308..a91752c03e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f3ef9c7c2b4ba3de1057ad569f068b241d5f23e6629d8e0dacf85e57fd13b8aa \ No newline at end of file +98eb54c6d83992886f17a00b6fc8998df230e3b5f45bafc6fae0d15a9ee5a4c6 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index fb172e7218..d510711087 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4325,7 +4325,11 @@ static int unixShmSystemLock( f.l_len = n; res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile); if( res==-1 ){ +#ifdef SQLITE_ENABLE_SETLK_TIMEOUT rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY); +#else + rc = SQLITE_BUSY; +#endif } } From 783e159e48979c551c204cbfe9c8f7dd4550d5e4 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 6 May 2020 20:55:38 +0000 Subject: [PATCH 08/11] Fix harmless compiler warnings. FossilOrigin-Name: 92dc59132f8547635d73c61c21ea29b380c401ddc84a6d01412808e00386b9e8 --- manifest | 20 ++++++++++---------- manifest.uuid | 2 +- src/btree.c | 3 +-- src/main.c | 2 +- src/sqliteInt.h | 2 +- src/wal.c | 2 +- 6 files changed, 15 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index 0a7ef8f8c7..fdf31ea371 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\spreventing\sbuilding\swithout\sSQLITE_ENABLE_SETLK_TIMEOUT\sdefined. -D 2020-05-06T20:45:11.359 +C Fix\sharmless\scompiler\swarnings. +D 2020-05-06T20:55:38.208 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -474,7 +474,7 @@ F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c f0cd4a3683b60f456f17e28f24cc72febc0df9c3f3f5126d799f9dc9ee5844b6 +F src/btree.c a0f550b2df013c6ce2e16f2134b24750654717083679e8bd65d4b3eb991e0706 F src/btree.h 989ef3c33413549e3e148f3dcb46c030f317dac130dc86809ba6b9aa4b16c72a F src/btreeInt.h 887cdd2ea7f4a65143074a8a7c8928b0546f8c18dda3c06a408ce7992cbab0c0 F src/build.c ec6c0bda1e43ef55e5f5121a77ba19fac51fc6585f95ce2da795bcedcf6e8f36 @@ -497,7 +497,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 8e4211d04eb460c0694d486c6ba1c068d468c6f653c3f237869a802ad82854de F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 421310045bd78afefb772294a99e50f37d87ae578786a6169074e6291e30d969 -F src/main.c 685d391fc37ad2c1162ad6784cae4a454dcd3632bbab319464af733d71eca72f +F src/main.c 3f4a08e109b8b100230b62d0317de8b99ed4f2f8ac0f84c96d9bd53b21693f68 F src/malloc.c a3e13b001f988ecec6bdb90c0ea8912c8c786e623724d7098da623d8d01d19b1 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -538,7 +538,7 @@ F src/shell.c.in cf2d24f54412c06e5fb34af7fabc748651125e1dceac29b740e91f06d23447b F src/sqlite.h.in a42bae930f462294801f24468dd56832b09de01072a26dc0df60ddc3c5602210 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197 -F src/sqliteInt.h 26de171e0adccf6e465434b9fcce18fcfcc757e9a727356b029fc1676639540c +F src/sqliteInt.h 9d2caeaee7a317af536a60fcd828425da5d64c4f26aac5356f13dce1de3cb066 F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032 F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -617,7 +617,7 @@ F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143 F src/vdbevtab.c 8094dfc28dad82d60a1c832020a1b201a5381dc185c14638affc6d4e9d54c653 F src/vtab.c 7b704a90515a239c6cdba6a66b1bb3a385e62326cceb5ecb05ec7a091d6b8515 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c f4eda6e6886da4c93e679210b14b75435d0087756644179b01896e485dd32677 +F src/wal.c 43ee77f2b7d0de649bf2da5e22ec19bb4690605d9df35aeceba8a9fb1a4d890c F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7c429c694abd12413a5c17aec9f47cfe9eba6807e6b0a32df883e8e3a14835ed F src/where.c 9546c82056e8cdb27291f98cf1adca5d271240b399bb97b32f77fc2bea6146c9 @@ -1864,7 +1864,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 f3ef9c7c2b4ba3de1057ad569f068b241d5f23e6629d8e0dacf85e57fd13b8aa -R 300add0d813f0b2aa21b7602c0922ab2 -U dan -Z 6ae115939550b6311fe0efe8d583ce34 +P 98eb54c6d83992886f17a00b6fc8998df230e3b5f45bafc6fae0d15a9ee5a4c6 +R 17cffa12f5b799cb65952b123268b435 +U drh +Z 20ca82d31230a53570c1c1a513848271 diff --git a/manifest.uuid b/manifest.uuid index a91752c03e..509ff0de39 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -98eb54c6d83992886f17a00b6fc8998df230e3b5f45bafc6fae0d15a9ee5a4c6 \ No newline at end of file +92dc59132f8547635d73c61c21ea29b380c401ddc84a6d01412808e00386b9e8 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 8ac3374dd4..972063bfa4 100644 --- a/src/btree.c +++ b/src/btree.c @@ -2304,8 +2304,7 @@ static int btreeInvokeBusyHandler(void *pArg){ BtShared *pBt = (BtShared*)pArg; assert( pBt->db ); assert( sqlite3_mutex_held(pBt->db->mutex) ); - return sqlite3InvokeBusyHandler(&pBt->db->busyHandler, - sqlite3PagerFile(pBt->pPager)); + return sqlite3InvokeBusyHandler(&pBt->db->busyHandler); } /* diff --git a/src/main.c b/src/main.c index 0bc8edfec0..83ba434be4 100644 --- a/src/main.c +++ b/src/main.c @@ -1664,7 +1664,7 @@ static int sqliteDefaultBusyCallback( ** If this routine returns non-zero, the lock is retried. If it ** returns 0, the operation aborts with an SQLITE_BUSY error. */ -int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){ +int sqlite3InvokeBusyHandler(BusyHandler *p){ int rc; if( p->xBusyHandler==0 || p->nBusy<0 ) return 0; rc = p->xBusyHandler(p->pBusyArg, p->nBusy); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b01f323935..5ae69e8732 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4584,7 +4584,7 @@ void sqlite3RenameExprlistUnmap(Parse*, ExprList*); CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); char sqlite3AffinityType(const char*, Column*); void sqlite3Analyze(Parse*, Token*, Token*); -int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*); +int sqlite3InvokeBusyHandler(BusyHandler*); int sqlite3FindDb(sqlite3*, Token*); int sqlite3FindDbName(sqlite3 *, const char *); int sqlite3AnalysisLoad(sqlite3*,int iDB); diff --git a/src/wal.c b/src/wal.c index d9e9ef177c..d3db4b27b9 100644 --- a/src/wal.c +++ b/src/wal.c @@ -3695,7 +3695,7 @@ int sqlite3WalCheckpoint( /* Enable blocking locks, if possible. If blocking locks are successfully ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */ sqlite3WalDb(pWal, db); - walEnableBlocking(pWal); + (void)walEnableBlocking(pWal); /* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive ** "checkpoint" lock on the database file. From bc9fc18e4576e3efe9db1c1bb0e2d6a7943e855f Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 6 May 2020 21:24:29 +0000 Subject: [PATCH 09/11] Fix an assert() failure that could follow an IO error. FossilOrigin-Name: e89c864299024cdce395a15c19b000b976142b9eed267901a288adaa695f9e65 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/wal.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index fdf31ea371..3fb759114b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarnings. -D 2020-05-06T20:55:38.208 +C Fix\san\sassert()\sfailure\sthat\scould\sfollow\san\sIO\serror. +D 2020-05-06T21:24:29.750 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -617,7 +617,7 @@ F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143 F src/vdbevtab.c 8094dfc28dad82d60a1c832020a1b201a5381dc185c14638affc6d4e9d54c653 F src/vtab.c 7b704a90515a239c6cdba6a66b1bb3a385e62326cceb5ecb05ec7a091d6b8515 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 43ee77f2b7d0de649bf2da5e22ec19bb4690605d9df35aeceba8a9fb1a4d890c +F src/wal.c fdbf7641be6fa6e57f86484e8b5ffe816dffae176c4fd72a9b76e5e0b99bf6dd F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7c429c694abd12413a5c17aec9f47cfe9eba6807e6b0a32df883e8e3a14835ed F src/where.c 9546c82056e8cdb27291f98cf1adca5d271240b399bb97b32f77fc2bea6146c9 @@ -1864,7 +1864,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 98eb54c6d83992886f17a00b6fc8998df230e3b5f45bafc6fae0d15a9ee5a4c6 -R 17cffa12f5b799cb65952b123268b435 -U drh -Z 20ca82d31230a53570c1c1a513848271 +P 92dc59132f8547635d73c61c21ea29b380c401ddc84a6d01412808e00386b9e8 +R 5643010523c06a5a3b834d328816f805 +U dan +Z 39ee58cca1df36ea8fc4467e7e30965f diff --git a/manifest.uuid b/manifest.uuid index 509ff0de39..9232410316 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -92dc59132f8547635d73c61c21ea29b380c401ddc84a6d01412808e00386b9e8 \ No newline at end of file +e89c864299024cdce395a15c19b000b976142b9eed267901a288adaa695f9e65 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index d3db4b27b9..baa1220b0d 100644 --- a/src/wal.c +++ b/src/wal.c @@ -2945,8 +2945,8 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ ** read-lock. */ void sqlite3WalEndReadTransaction(Wal *pWal){ + sqlite3WalEndWriteTransaction(pWal); if( pWal->readLock>=0 ){ - sqlite3WalEndWriteTransaction(pWal); walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock)); pWal->readLock = -1; } From a8aae52391afb2b1d5eac44c45e8de994642e228 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 6 May 2020 21:25:39 +0000 Subject: [PATCH 10/11] Avoid leaking a file-handle in test file walsetlk.test. FossilOrigin-Name: 3cfc675e2e917b69108feb3a75728b573abe8e44f0890a7d20d307b0b6784c0e --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/walsetlk.test | 1 + 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 3fb759114b..cb6a0296ca 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sassert()\sfailure\sthat\scould\sfollow\san\sIO\serror. -D 2020-05-06T21:24:29.750 +C Avoid\sleaking\sa\sfile-handle\sin\stest\sfile\swalsetlk.test. +D 2020-05-06T21:25:39.157 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1689,7 +1689,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 -F test/walsetlk.test 5c8bd1832a828db71283c03dc4a74d648c5333a5b2e978f5bda4f0d81bae5490 +F test/walsetlk.test 1d5628abc149c2c9d1fc4f5830d2540f02d9efad0ed815407d54035d23cd5df9 F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747 @@ -1864,7 +1864,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 92dc59132f8547635d73c61c21ea29b380c401ddc84a6d01412808e00386b9e8 -R 5643010523c06a5a3b834d328816f805 +P e89c864299024cdce395a15c19b000b976142b9eed267901a288adaa695f9e65 +R 3d441440eb789a6955c09c8d2e120384 U dan -Z 39ee58cca1df36ea8fc4467e7e30965f +Z 6de8f7ead6c68a5c01aa4ce7d42c72c9 diff --git a/manifest.uuid b/manifest.uuid index 9232410316..286ca7607c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e89c864299024cdce395a15c19b000b976142b9eed267901a288adaa695f9e65 \ No newline at end of file +3cfc675e2e917b69108feb3a75728b573abe8e44f0890a7d20d307b0b6784c0e \ No newline at end of file diff --git a/test/walsetlk.test b/test/walsetlk.test index 635839c0cf..b44412d9b1 100644 --- a/test/walsetlk.test +++ b/test/walsetlk.test @@ -72,6 +72,7 @@ do_test 1.8 { file size test.db-wal } 0 +close $fd db close db2 close #------------------------------------------------------------------------- From 11a8182e5c6868a275531315c71f167a410ea86c Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 7 May 2020 14:26:40 +0000 Subject: [PATCH 11/11] Fix an error that could occur if the first transaction executed by a connection configured to use blocking locks is a write-transaction for which the WRITER lock cannot be obtained. FossilOrigin-Name: 49e4dc72f7a4b28e4b49d7b91030bc986aea3ff44dac38cb6e68305800cd1de5 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/btree.c | 2 +- test/walsetlk.test | 17 +++++++++++++++-- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index 99b7c24f76..c9dbb5cb17 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\strunk\schanges\sinto\sthis\sbranch. -D 2020-05-07T14:05:08.190 +C Fix\san\serror\sthat\scould\soccur\sif\sthe\sfirst\stransaction\sexecuted\sby\sa\sconnection\sconfigured\sto\suse\sblocking\slocks\sis\sa\swrite-transaction\sfor\swhich\sthe\sWRITER\slock\scannot\sbe\sobtained. +D 2020-05-07T14:26:40.925 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -474,7 +474,7 @@ F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 F src/backup.c b1c90cd4110248c8e1273ff4578d3a84c0c34725e1b96dacd4a6294a908702de F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c d78458bf4cc0e33a7faa1ab9904ebd66c8a8c820d802b53c9d273b45b3dac667 +F src/btree.c f14e415fcfd0b52b4e4ebd193ba5fadac5e8252c30f023389af682813af44025 F src/btree.h 989ef3c33413549e3e148f3dcb46c030f317dac130dc86809ba6b9aa4b16c72a F src/btreeInt.h 5c8b8749805787313ecf49eb5be3ced1e94bbf8ef54bb01470ce6bd0d5185c67 F src/build.c 5566b570435d3511a0fd57388c124491b1f74e59561f0c1679fabe74c4c54b7a @@ -1689,7 +1689,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 -F test/walsetlk.test 1d5628abc149c2c9d1fc4f5830d2540f02d9efad0ed815407d54035d23cd5df9 +F test/walsetlk.test 11f7fe792fdce54cf09874dab824e0627f2eedecfb9f7983e325606ec5184e0c F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747 @@ -1864,7 +1864,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 3cfc675e2e917b69108feb3a75728b573abe8e44f0890a7d20d307b0b6784c0e 99749d4fd4930ccf15227f67c732266af9e09dd3cabdc0834fb450ef98196441 -R a2fb9be328819586780eac9a007a3fb6 +P ac4ee69664278a828e0a64c5be3b96fdb6eb6acc95646a9425c667aea328791c +R 22b4478e3cf3c244a4ab3e6943ce3c12 U dan -Z 26b45dc1c0a43ede219cdbbfa3466d04 +Z e85493d3ac63dab3b3e9ea5cdd9d6a6e diff --git a/manifest.uuid b/manifest.uuid index 6fa7b45d5b..6f07e8c3df 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ac4ee69664278a828e0a64c5be3b96fdb6eb6acc95646a9425c667aea328791c \ No newline at end of file +49e4dc72f7a4b28e4b49d7b91030bc986aea3ff44dac38cb6e68305800cd1de5 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 3fe0e1c3ce..f269b3deee 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3434,8 +3434,8 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){ pBt->btsFlags &= ~BTS_INITIALLY_EMPTY; if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY; - sqlite3PagerWalDb(pPager, p->db); do { + sqlite3PagerWalDb(pPager, p->db); #ifdef SQLITE_ENABLE_SETLK_TIMEOUT /* If transitioning from no transaction directly to a write transaction, diff --git a/test/walsetlk.test b/test/walsetlk.test index b44412d9b1..66513ad2dc 100644 --- a/test/walsetlk.test +++ b/test/walsetlk.test @@ -78,7 +78,6 @@ db2 close #------------------------------------------------------------------------- do_multiclient_test tn { - do_test 2.$tn.1 { sql1 { PRAGMA journal_mode = wal; @@ -175,11 +174,25 @@ do_multiclient_test tn { do_test 2.$tn.14 { set us [lindex [time { catch {db eval "PRAGMA wal_checkpoint=RESTART"} }] 0] - puts $us expr $us>1000000 && $us<4000000 } {1} } +#------------------------------------------------------------------------- +reset_db +sqlite3 db2 test.db +db2 timeout 1000 +do_execsql_test 3.0 { + PRAGMA journal_mode = wal; + CREATE TABLE x1(x, y); + BEGIN; + INSERT INTO x1 VALUES(1, 2); +} {wal} + +do_test 3.1 { + list [catch { db2 eval {BEGIN EXCLUSIVE} } msg] $msg +} {1 {database is locked}} + finish_test