SQLite version 3.7.4 with TEA.  gcc was run like this:

gcc -DPACKAGE_NAME=\"sqlite\" -DPACKAGE_TARNAME=\"sqlite\" 
-DPACKAGE_VERSION=\"3.7.4\" -DPACKAGE_STRING=\"sqlite\ 3.7.4\" 
-DPACKAGE_BUGREPORT=\"\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 
-DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 
-DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 
-DHAVE_LIMITS_H=1 -DHAVE_SYS_PARAM_H=1 -DUSE_THREAD_ALLOC=1 -D_REENTRANT=1 
-D_THREAD_SAFE=1 -DTCL_THREADS=1 -DSQLITE_THREADSAFE=1 -DMODULE_SCOPE=extern\ 
__attribute__\(\(__visibility__\(\"hidden\"\)\)\) -D_LARGEFILE64_SOURCE=1 
-DTCL_WIDE_INT_TYPE=long\ long -DHAVE_STRUCT_STAT64=1 -DHAVE_OPEN64=1 
-DHAVE_LSEEK64=1 -DHAVE_TYPE_OFF64_T=1 -DUSE_TCL_STUBS=1 -DSQLITE_ENABLE_FTS3=1 
-I"./generic" -I"/home/eas/tcl8.5.9/generic"    -pipe -O0 -g -Wall -fPIC -c 
`echo ./generic/tclsqlite3.c` -o tclsqlite3.o

(All those parameters were auto-generated by 'configure' except -O0,
which I changed from the default -O2.)

$ uname -a
Linux hudson 2.6.32.26-175.fc12.i686 #1 SMP Wed Dec 1 21:52:04 UTC 2010 i686 
athlon i386 GNU/Linux

I register a Tcl busy handler that fails to be called when a connection 
attempts to escalate its lock status.  This may also indicate a bug 
in the C API as well.

Steps to reproduce:

1. Write the following script into a file named 'foo.tcl':

===
#!/usr/bin/tclsh

load sqlite-tea-3070400/libsqlite3.7.4.so

proc ::busy {ntries} {
    puts stderr "[pid] finds the db busy, ntries=$ntries.  try again."
    after 1
    return 0
}

if {[catch {
  puts stderr "[pid] hello, world"
  sqlite3 db /tmp/foo.db
  db busy ::busy
  db eval begin
  db eval {create table if not exists t(a)}
  db eval commit
  db eval begin
  db eval {select count(*) from t}
  db eval {insert into t values(100)}
  after 1000
  db eval commit
  puts stderr "[pid] exits successfully"
}]} {
  puts stderr "[pid] error in script: $::errorInfo"
} 
===

2. Make sure that the 'load' command above will work by changing the path 
name as appropriate.

3. Make sure /tmp is a normal filesystem and the file 'foo.db' does not
exist there, e.g. as the remnant of some previous debugging exercise.

4. Make the script executable:

   $ chmod +x ./foo.tcl

5. Run the script twice in parallel:

   $ ./foo.tcl & ./foo.tcl

Expected result: 

Both scripts indicate that they have completed successfully by 
printing "<PID> exits successfully".  This is because we expect
for the busy handler to be called when the database is locked,
and the busy handler always return 0, indicating that SQLite
should keep retrying until successful.

Actual result:

In almost every test run, neither instance never enters ::busy.  
Instead, I get the following output:

[hudson:~] $ ./foo.tcl & ./foo.tcl
[1] 15308
15309 hello, world
15308 hello, world
15308 error in script: database is locked
    while executing
"db eval {insert into t values(100)}"
15309 exits successfully

I say "almost almost every test run" because if I remove that 
'after 1000' line, sometimes the script fails like this and sometimes 
it doesn't.  Adding the 'after' line increases the failure frequency to 
nearly 100%, probably because the "winning" process is holding a certain 
flavor of lock for longer.

Please let me know if you need more information.

Eric

--
Eric A. Smith

Electricity is actually made up of extremely tiny particles 
called electrons, that you cannot see with the naked eye unless 
you have been drinking.
    -- Dave Barry
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to