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:
drh 2013-05-15 16:08:33 +00:00
parent d5dd3305a1
commit 2ab2d55f01
3 changed files with 58 additions and 22 deletions

View File

@ -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

View File

@ -1 +1 @@
d484eaf8d6dfaf2c1065b93b2a52a6db91c09fa4
65ff754e3521aa8ee9135d235166cac2a8f57ebd

View File

@ -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