Fix the sharedA.test module so that it does not attempt to run TCL callbacks
on a different thread from where the interpreter was originally created. FossilOrigin-Name: 65ff754e3521aa8ee9135d235166cac2a8f57ebd
This commit is contained in:
parent
d5dd3305a1
commit
2ab2d55f01
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
||||
C Do\snot\srun\ssharedA.test\sif\sthe\ssystem\sis\snot\sthreadsafe.
|
||||
D 2013-05-15T15:53:52.221
|
||||
C Fix\sthe\ssharedA.test\smodule\sso\sthat\sit\sdoes\snot\sattempt\sto\srun\sTCL\scallbacks\non\sa\sdifferent\sthread\sfrom\swhere\sthe\sinterpreter\swas\soriginally\screated.
|
||||
D 2013-05-15T16:08:33.601
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in ce81671efd6223d19d4c8c6b88ac2c4134427111
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -738,7 +738,7 @@ F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
|
||||
F test/shared7.test 960760bc8d03e1419e70dea69cf41db62853616e
|
||||
F test/shared8.test b27befbefbe7f4517f1d6b7ff8f64a41ec74165d
|
||||
F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21
|
||||
F test/sharedA.test 8eddeda2407bdcd335ec8b8ba731aefc0e3e8232
|
||||
F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
|
||||
F test/shared_err.test 0079c05c97d88cfa03989b7c20a8b266983087aa
|
||||
F test/sharedlock.test ffa0a3c4ac192145b310f1254f8afca4d553eabf
|
||||
F test/shell1.test 4a2f57952719972c6f862134463f8712e953c038
|
||||
@ -1064,7 +1064,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||
P 47dd65a890955f333d431e275f3f4d95d34a5ba5
|
||||
R 7b8246f3bd54a0ac6d93356e2396ef91
|
||||
U dan
|
||||
Z d923d1c201be4d3e0bbb63e5d84a5ca9
|
||||
P d484eaf8d6dfaf2c1065b93b2a52a6db91c09fa4
|
||||
R 2b3d38cfaeff54ce7cad59c19d675f6e
|
||||
U drh
|
||||
Z adae8d677b3886690161b439bdcd47db
|
||||
|
@ -1 +1 @@
|
||||
d484eaf8d6dfaf2c1065b93b2a52a6db91c09fa4
|
||||
65ff754e3521aa8ee9135d235166cac2a8f57ebd
|
@ -89,11 +89,31 @@ do_test 1.3 {
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# sqlite3RollbackAll() loops through all attached b-trees and rolls
|
||||
# back each one separately. Then if the SQLITE_InternChanges flag is
|
||||
# set, it resets the schema. Both of the above steps must be done
|
||||
# while holding a mutex, otherwise another thread might slip in and
|
||||
# try to use the new schema with the old data.
|
||||
#
|
||||
# The following sequence of tests attempt to verify that the actions
|
||||
# taken by sqlite3RollbackAll() are thread-atomic (that they cannot be
|
||||
# interrupted by a separate thread.)
|
||||
#
|
||||
# Note that a TCL interpreter can only be used within the thread in which
|
||||
# it was originally created (because it uses thread-local-storage).
|
||||
# The tvfs callbacks must therefore only run on the main thread.
|
||||
# There is some trickery in the read_callback procedure to ensure that
|
||||
# this is the case.
|
||||
#
|
||||
testvfs tvfs
|
||||
tvfs filter xRead
|
||||
tvfs script read_callback
|
||||
proc read_callback {args} { }
|
||||
|
||||
# Set up two databases and two database connections.
|
||||
#
|
||||
# db1: main(test.db), two(test2.db)
|
||||
# db2: main(test.db)
|
||||
#
|
||||
# The cache for test.db is shared between db1 and db2.
|
||||
#
|
||||
do_test 2.1 {
|
||||
forcedelete test.db test.db2
|
||||
sqlite3 db1 test.db -vfs tvfs
|
||||
@ -112,12 +132,12 @@ do_test 2.1 {
|
||||
db2 eval { SELECT * FROM t1 }
|
||||
} {1 2 3}
|
||||
|
||||
# Create a prepared statement on db2 that will attempt a schema change
|
||||
# in test.db. Meanwhile, start a transaction on db1 that changes
|
||||
# the schema of test.db and that creates a rollback journal on test2.db
|
||||
#
|
||||
do_test 2.2 {
|
||||
set ::STMT [sqlite3_prepare db2 "CREATE INDEX i1 ON t1(x)" -1 tail]
|
||||
set {} {}
|
||||
} {}
|
||||
|
||||
do_test 2.3 {
|
||||
db1 eval {
|
||||
BEGIN;
|
||||
CREATE INDEX i1 ON t1(x);
|
||||
@ -125,21 +145,38 @@ do_test 2.3 {
|
||||
}
|
||||
} {}
|
||||
|
||||
set ::bFired 0
|
||||
# Set up a callback that will cause db2 to try to execute its
|
||||
# schema change when db1 accesses the journal file of test2.db.
|
||||
#
|
||||
# This callback will be invoked after the content of test.db has
|
||||
# be rolled back but before the schema has been reset. If the
|
||||
# sqlite3RollbackAll() operation is not thread-atomic, then the
|
||||
# db2 statement in the callback will see old content with the newer
|
||||
# schema, which is wrong.
|
||||
#
|
||||
tvfs filter xRead
|
||||
tvfs script read_callback
|
||||
unset -nocomplain ::some_time_laster
|
||||
unset -nocomplain ::thread_result
|
||||
proc read_callback {call file args} {
|
||||
if { $::bFired==0 && [string match *test.db2-journal $file] } {
|
||||
if {[string match *test.db2-journal $file]} {
|
||||
tvfs filter {} ;# Ensure that tvfs callbacks to do run on the
|
||||
# child thread
|
||||
sqlthread spawn ::thread_result [subst -nocommands {
|
||||
sqlite3_step $::STMT
|
||||
set rc [sqlite3_finalize $::STMT]
|
||||
}]
|
||||
after 1000 { set ::bFired 1 }
|
||||
vwait ::bFired
|
||||
after 1000 { set ::some_time_later 1 }
|
||||
vwait ::some_time_later
|
||||
}
|
||||
}
|
||||
do_test 2.4 { db1 eval ROLLBACK } {}
|
||||
do_test 2.3 { db1 eval ROLLBACK } {}
|
||||
|
||||
# Verify that the db2 statement invoked by the callback detected the
|
||||
# schema change.
|
||||
#
|
||||
if {[info exists ::thread_result]==0} { vwait ::thread_result }
|
||||
do_test 2.5 {
|
||||
do_test 2.4 {
|
||||
list $::thread_result [sqlite3_errmsg db2]
|
||||
} {SQLITE_SCHEMA {database schema has changed}}
|
||||
|
||||
@ -149,4 +186,3 @@ tvfs delete
|
||||
|
||||
sqlite3_enable_shared_cache $::enable_shared_cache
|
||||
finish_test
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user