1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

If blocking locks are enabled, avoid using the busy handler when blocked by another process running recovery.

FossilOrigin-Name: a35236757ab57c4c9b34e47c5dbc10d8f1220f8152955f5303cf9c3902ee169b
This commit is contained in:
dan
2025-05-30 20:52:18 +00:00
parent 88ed38ca6d
commit ded1959120
7 changed files with 123 additions and 19 deletions

View File

@@ -1,5 +1,5 @@
C Avoid\sinvoking\sthe\sbusy-handler\sif\sa\sblocking\slock\stimes\sout\swhile\sattempting\sto\sopen\sa\ssnapshot\stransaction.
D 2025-05-30T18:23:03.081
C If\sblocking\slocks\sare\senabled,\savoid\susing\sthe\sbusy\shandler\swhen\sblocked\sby\sanother\sprocess\srunning\srecovery.
D 2025-05-30T20:52:18.193
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -726,7 +726,7 @@ F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
F src/backup.c 5c97e8023aab1ce14a42387eb3ae00ba5a0644569e3476f38661fa6f824c3523
F src/bitvec.c 782cc29b42b47e7ec6348eb0aaf9ffe60063f498387e7249f458d445af4b53e9
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c 138e6b0df717244ba4591af5ba3cfb3f5032ea09a2f8449997329051155366c0
F src/btree.c da98489a981c347cc3a3982ea2810bbb583511a73cc34762547f30dbb4cda7f0
F src/btree.h 18e5e7b2124c23426a283523e5f31a4bff029131b795bb82391f9d2f3136fc50
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
F src/build.c 67c1db4c5e89a8519fe9b6dafc287f6bc3627696b5b8536dc5e06db570d8c05f
@@ -770,10 +770,10 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63
F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06
F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a
F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107
F src/os_unix.c 410185df4900817c218c0efdb8064b3481af88cb3f7cea7392f820b6eebc7889
F src/os_unix.c 8d9b9efbf337b5d59dbb259b7a8ca745f68d4f15495dbe17737b3c325c226363
F src/os_win.c b39f31fb0b137d67091d21880f0fded6b1c3c8c59b9e24e42844a1c0070437d4
F src/os_win.h 4c247cdb6d407c75186c94a1e84d5a22cbae4adcec93fcae8d2bc1f956fd1f19
F src/pager.c 9fbb541b46125dfa8914827575e6bb4d15048caa008073b1709112d495d7983b
F src/pager.c 23c0f17deb892da6b32fef1f465507df7ab5cd01d774288cb43695658a649259
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
F src/parse.y e426d7323311554c75b0aebc426d0fe3c88d9777ffefed236f343ad9e661dc4c
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
@@ -866,7 +866,7 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/vtab.c 828221bdbeaaa6d62126ee6d07fd4ec0d09dcaea846f87ad01944d8b7e548859
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c bcf40795a09b699ad7e42624dd6282b13335164fbabcd5a98a717758cebef451
F src/wal.c 78da33510b8cb1b096fb5ae9954be910998d2477ddb623e56f5df84e56b5814d
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
F src/where.c 45a3b496248a0b36d91ce34da3278d54f8fa20e9d3fbd36d45a42051d1118137
@@ -2036,6 +2036,7 @@ F test/walseh1.test bae700eb99519b6d5cd3f893c04759accc5a59c391d4189fe4dd6995a533
F test/walsetlk.test 9079cd8ef82570b8cf0067f31e049a72bec353fb2d5f0cc88f1736dc42ba9704
F test/walsetlk2.test 9097083633cdf55bf1098b694fb8651d0356d38fef28b869481d18029d7ceaf4
F test/walsetlk3.test 1b82bd92dea7e58f498b4399b0b3d26773dd8ac5c74205ce4a23c207cb8e85fe
F test/walsetlk_recover.test f653e7c85f77ba51828ba64d2d98f42f4afaf26bbd82ac60fbf1c6c8063e370f
F test/walsetlk_snapshot.test 6376fc8a76da4571eb35cf4aef06105f716c5e52f991cefec44b9c7015aadf1e
F test/walshared.test 42e3808582504878af237ea02c42ca793e8a0efaa19df7df26ac573370dbc7a3
F test/walslow.test 0c51843836c9dcf40a5ac05aa781bfb977b396ee2c872d92bd48b79d5dd9aa23
@@ -2208,11 +2209,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P 2e486f8fd011d28fdd7e59ff34f7f04374019932eb160a8c4de56a5ce01e5782
R 271c081be49b44d7c0913e445ea8afea
T *branch * setlk-snapshot-fix
T *sym-setlk-snapshot-fix *
T -sym-trunk *
P fe11f85fd3283bb7002f43bd8b796e9e7b67f6d1a92eb676be06b46d1458fc1d
R 23bc39f2089ecb41cbb93275af5fee9c
U dan
Z 6fb6c5ab6f440154ac0955e521c66539
Z d039c7225445fc871711c264f1609f48
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
fe11f85fd3283bb7002f43bd8b796e9e7b67f6d1a92eb676be06b46d1458fc1d
a35236757ab57c4c9b34e47c5dbc10d8f1220f8152955f5303cf9c3902ee169b

View File

@@ -3697,11 +3697,10 @@ static SQLITE_NOINLINE int btreeBeginTrans(
(void)sqlite3PagerWalWriteLock(pPager, 0);
unlockBtreeIfUnused(pBt);
}
#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_ENABLE_SNAPSHOT)
#if defined(SQLITE_ENABLE_SETLK_TIMEOUT)
if( rc==SQLITE_BUSY_TIMEOUT ){
/* If a blocking lock timed out, break out of the loop here so that
** the busy-handler is not invoked. This can only happen when opening
** a transaction on a snapshot. */
** the busy-handler is not invoked. */
break;
}
#endif

View File

@@ -5043,13 +5043,14 @@ static int unixShmLock(
** occur later in the above list than the lock being obtained may be
** held.
**
** It is not permitted to block on the RECOVER lock.
** It is not permitted to block on the RECOVER lock if any other
** locks are held.
*/
#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && defined(SQLITE_DEBUG)
{
u16 lockMask = (p->exclMask|p->sharedMask);
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
(ofst!=2) /* not RECOVER */
(ofst!=2 || lockMask==0) /* not RECOVER */
&& (ofst!=1 || lockMask==0 || lockMask==2)
&& (ofst!=0 || lockMask<3)
&& (ofst<3 || lockMask<(1<<ofst))

View File

@@ -700,6 +700,9 @@ struct Pager {
Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
char *zWal; /* File name for write-ahead log */
#endif
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
sqlite3 *dbWal;
#endif
};
/*
@@ -7581,6 +7584,11 @@ static int pagerOpenWal(Pager *pPager){
pPager->fd, pPager->zWal, pPager->exclusiveMode,
pPager->journalSizeLimit, &pPager->pWal
);
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
if( rc==SQLITE_OK ){
sqlite3WalDb(pPager->pWal, pPager->dbWal);
}
#endif
}
pagerFixMaplimit(pPager);
@@ -7700,6 +7708,7 @@ int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
** blocking locks are required.
*/
void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
pPager->dbWal = db;
if( pagerUseWal(pPager) ){
sqlite3WalDb(pPager->pWal, db);
}

View File

@@ -3062,7 +3062,6 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
rc = walIndexReadHdr(pWal, pChanged);
}
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
walDisableBlocking(pWal);
if( rc==SQLITE_BUSY_TIMEOUT ){
rc = SQLITE_BUSY;
*pCnt |= WAL_RETRY_BLOCKED_MASK;
@@ -3077,6 +3076,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
** WAL_RETRY this routine will be called again and will probably be
** right on the second iteration.
*/
walEnableBlocking(pWal);
if( pWal->apWiData[0]==0 ){
/* This branch is taken when the xShmMap() method returns SQLITE_BUSY.
** We assume this is a transient condition, so return WAL_RETRY. The
@@ -3093,6 +3093,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int *pCnt){
rc = SQLITE_BUSY_RECOVERY;
}
}
walDisableBlocking(pWal);
if( rc!=SQLITE_OK ){
return rc;
}

View File

@@ -0,0 +1,96 @@
# 2025 May 30
#
# 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.
#
#***********************************************************************
#
# TESTRUNNER: slow
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix walsetlk_recover
ifcapable !wal {finish_test ; return }
ifcapable !setlk_timeout {finish_test ; return }
ifcapable !snapshot {finish_test; return}
do_execsql_test 1.0 {
PRAGMA journal_mode = wal;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 VALUES(3, 4);
INSERT INTO t1 VALUES(5, 6);
} {wal}
db_save_and_close
db_restore
testfixture_nb myvar {
testvfs tvfs -fullshm 1
sqlite3 db test.db -vfs tvfs
tvfs script vfs_callback
tvfs filter xRead
set ::done 0
proc vfs_callback {method file args} {
if {$::done==0 && [string match *wal $file]} {
after 4000
set ::done 1
}
return "SQLITE_OK"
}
db eval {
SELECT * FROM t1
}
db close
}
# Give the [testfixture_nb] command time to start
after 1000
testvfs tvfs -fullshm 1
sqlite3 db test.db -vfs tvfs
tvfs script sleep_callback
tvfs filter xSleep
set ::sleep_count 0
proc sleep_callback {args} {
incr ::sleep_count
}
sqlite3 db test.db -vfs tvfs
sqlite3_setlk_timeout db 500
set tm [lindex [time {
catch {
db eval {SELECT * FROM t1}
} msg
}] 0]
do_test 1.2 { set ::msg } {database is locked}
do_test 1.3.($::tm) { expr $::tm>400000 && $::tm<1000000 } 1
vwait myvar
do_execsql_test 1.4 {
SELECT * FROM t1
} {1 2 3 4 5 6}
db close
tvfs delete
do_test 1.5 {
set ::sleep_count
} 0
finish_test