From 7fee0bfad2234d0cd3b32cae84ad60c8bbddeaf2 Mon Sep 17 00:00:00 2001 From: dan Date: Tue, 3 Jul 2018 20:17:27 +0000 Subject: [PATCH] Test that a race condition can cause a "BEGIN EXCLUSIVE" to return SQLITE_BUSY_SNAPSHOT in wal mode. FossilOrigin-Name: 5a12db75d1da65daa92413a6b5892309e9d9479bb3610764e1015abe5bf28dbe --- manifest | 11 ++--- manifest.uuid | 2 +- test/walprotocol2.test | 97 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 test/walprotocol2.test diff --git a/manifest b/manifest index f66a1393eb..2357a1bfd4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sin\sthe\sxInverse\scallback\sfor\sthe\sbuilt-in\ssum()\swindow\sfunction. -D 2018-07-02T17:45:59.790 +C Test\sthat\sa\srace\scondition\scan\scause\sa\s"BEGIN\sEXCLUSIVE"\sto\sreturn\nSQLITE_BUSY_SNAPSHOT\sin\swal\smode. +D 2018-07-03T20:17:27.649 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6 @@ -1583,6 +1583,7 @@ F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496 F test/waloverwrite.test dad2f26567f1b45174e54fbf9a8dc1cb876a7f03 F test/walpersist.test 8c6b7e3ec1ba91b5e4dc4e0921d6d3f87cd356a6 F test/walprotocol.test a112aba0b79e3adeaa485fed09484b32c654e97df58e454aa8489ac2cd57bf84 +F test/walprotocol2.test ad92f036102f722b2d7f7ca7c1faf72d75f501a50c80a92d7fd87f8b1da6608c F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 @@ -1744,7 +1745,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 693b4350d741391226a33ab6a05eaad61e8ef1590176f01e8aed2a212e2d6419 -R 2a905c5056bd462d63ab558902828293 +P b6563647382634588ebe5c6a3c35c65a321dc1b3732c809d48ce46759b9dd80f +R 85d71bbec8ad4dcf2f8e9507c907b291 U dan -Z e86ae3bb9d5c5564eb7cd669366300ff +Z 38cb85199c9d8fc14bf46fba2bfb3f49 diff --git a/manifest.uuid b/manifest.uuid index 88034b238c..e6f611aeb3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b6563647382634588ebe5c6a3c35c65a321dc1b3732c809d48ce46759b9dd80f \ No newline at end of file +5a12db75d1da65daa92413a6b5892309e9d9479bb3610764e1015abe5bf28dbe \ No newline at end of file diff --git a/test/walprotocol2.test b/test/walprotocol2.test new file mode 100644 index 0000000000..ea1c9a2f7d --- /dev/null +++ b/test/walprotocol2.test @@ -0,0 +1,97 @@ +# 2018 July 4 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/lock_common.tcl +source $testdir/wal_common.tcl +ifcapable !wal {finish_test ; return } + +set testprefix walprotocol2 + +#------------------------------------------------------------------------- +# When recovering the contents of a WAL file, a process obtains the WRITER +# lock, then locks all other bytes before commencing recovery. If it fails +# to lock all other bytes (because some other process is holding a read +# lock) it should retry up to 100 times. Then return SQLITE_PROTOCOL to the +# caller. Test this (test case 1.3). +# +# Also test the effect of hitting an SQLITE_BUSY while attempting to obtain +# the WRITER lock (should be the same). Test case 1.4. +# +do_execsql_test 1.0 { + PRAGMA journal_mode = wal; + CREATE TABLE x(y); + INSERT INTO x VALUES('z'); +} {wal} + +db close + +proc lock_callback {method filename handle lock} { + # puts "$method $filename $handle $lock" +} +testvfs T +T filter xShmLock +T script lock_callback + +sqlite3 db test.db -vfs T +sqlite3 db2 test.db -vfs T + +do_execsql_test 2.0 { + SELECT * FROM x; +} {z} +do_execsql_test -db db2 2.1 { + SELECT * FROM x; +} {z} + +#--------------------------------------------------------------- +# Attempt a "BEGIN EXCLUSIVE" using connection handle [db]. This +# causes SQLite to open a read transaction, then a write transaction. +# Rig the xShmLock() callback so that just before the EXCLUSIVE lock +# for the write transaction is taken, connection [db2] jumps in and +# modifies the database. This causes the "BEGIN EXCLUSIVE" to throw +# an SQLITE_BUSY_SNAPSHOT error. +# +proc lock_callback {method filename handle lock} { + if {$lock=="0 1 lock exclusive"} { + proc lock_callback {method filename handle lock} {} + db2 eval { INSERT INTO x VALUES('y') } + } +} +do_catchsql_test 2.2 { + BEGIN EXCLUSIVE; +} {1 {database is locked}} +do_test 2.3 { + sqlite3_extended_errcode db +} {SQLITE_BUSY_SNAPSHOT} + +#--------------------------------------------------------------- +# Same again, but with a busy-handler. This time, following the +# SQLITE_BUSY_SNAPSHOT error the busy-handler is invoked and then the +# whole thing retried from the beginning. This time it succeeds. +# +proc lock_callback {method filename handle lock} { + if {$lock=="0 1 lock exclusive"} { + proc lock_callback {method filename handle lock} {} + db2 eval { INSERT INTO x VALUES('x') } + } +} +db timeout 10 +do_catchsql_test 2.4 { + BEGIN EXCLUSIVE; +} {0 {}} +do_execsql_test 2.5 { + SELECT * FROM x; + COMMIT; +} {z y x} + +finish_test -- 2.47.2