1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Fix an obscure race condition that can occur when multiple threads, shared cache and DDL statements are combined. Enhance notify2.test to test this scenario. (CVS 6373)

FossilOrigin-Name: 92ec5975123284aff3a69ee16c397d9e2a844c0b
This commit is contained in:
danielk1977
2009-03-23 17:11:26 +00:00
parent bc73971db6
commit a8bbef84bf
6 changed files with 113 additions and 59 deletions

View File

@ -9,7 +9,7 @@
#
#***********************************************************************
#
# $Id: notify2.test,v 1.2 2009/03/19 07:58:31 danielk1977 Exp $
# $Id: notify2.test,v 1.3 2009/03/23 17:11:27 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -62,6 +62,8 @@ set ThreadProgram {
set lRes [list]
set rc SQLITE_OK
set sql $zSql
while {$rc=="SQLITE_OK" && $zSql ne ""} {
set STMT [$::xPrepare $db $zSql -1 zSql]
while {[set rc [$::xStep $STMT]] eq "SQLITE_ROW"} {
@ -72,22 +74,33 @@ set ThreadProgram {
set rc [sqlite3_finalize $STMT]
}
if {$rc != "SQLITE_OK"} { error "$rc [sqlite3_errmsg $db]" }
if {$rc != "SQLITE_OK"} { error "$rc $sql [sqlite3_errmsg $db]" }
return $lRes
}
proc execsql_retry {db sql} {
set msg "SQLITE_LOCKED blah..."
while { [string match SQLITE_LOCKED* $msg] } {
catch { execsql_blocking $db $sql } msg
}
}
proc select_one {args} {
set n [llength $args]
lindex $args [expr int($n*rand())]
}
# Open a database connection. Attach the two auxillary databases.
set ::DB [sqlite3_open test.db]
execsql_blocking $::DB {
ATTACH 'test2.db' AS aux2;
ATTACH 'test3.db' AS aux3;
proc opendb {} {
# Open a database connection. Attach the two auxillary databases.
set ::DB [sqlite3_open test.db]
execsql_retry $::DB { ATTACH 'test2.db' AS aux2; }
execsql_retry $::DB { ATTACH 'test3.db' AS aux3; }
}
opendb
#after 2000
# This loop runs for ~20 seconds.
#
set iStart [clock_seconds]
@ -108,12 +121,11 @@ set ThreadProgram {
} {
DELETE FROM xxx WHERE a<(SELECT max(a)-100 FROM xxx);
INSERT INTO xxx SELECT NULL, total(a) FROM xxx;
}
# {
# CREATE INDEX IF NOT EXISTS yyy.xxx_i ON xxx(b);
# } {
# DROP INDEX IF EXISTS yyy.xxx_i;
# }
} {
CREATE INDEX IF NOT EXISTS yyy.xxx_i ON xxx(b);
} {
DROP INDEX IF EXISTS yyy.xxx_i;
}
]]
}
@ -128,9 +140,15 @@ set ThreadProgram {
"
} msg]
if {$rc && [string match "SQLITE_LOCKED*" $msg]} {
if {$rc && [string match "SQLITE_LOCKED*" $msg]
|| [string match "SQLITE_SCHEMA*" $msg]
} {
# Hit an SQLITE_LOCKED error. Rollback the current transaction.
execsql_blocking $::DB ROLLBACK
set rc [catch { execsql_blocking $::DB ROLLBACK } msg]
if {$rc && [string match "SQLITE_LOCKED*" $msg]} {
sqlite3_close $::DB
opendb
}
} elseif {$rc} {
# Hit some other kind of error. This is a malfunction.
error $msg
@ -150,7 +168,7 @@ set ThreadProgram {
foreach {iTest xStep xPrepare} {
1 sqlite3_blocking_step sqlite3_blocking_prepare_v2
2 sqlite3_step sqlite3_prepare_v2
2 sqlite3_step sqlite3_nonblocking_prepare_v2
} {
file delete -force test.db test2.db test3.db