diff --git a/manifest b/manifest index 05c6df0f67..a2b2430236 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\snew\sthread-testing\scode\sand\sfix\slocking\sunder\sLinux\sthreads.\s\sTicket\s#530.\s(CVS\s1137) -D 2003-12-19T02:52:06 +C A\sbetter\sfix\sfor\sticket\s#530\s-\sone\sthat\sis\slikely\sto\swork\son\sunix\nimplementations\sin\saddition\sto\slinux.\s\sAlso\smore\stests\sfor\smulti-thread\nlocking\sadded.\s(CVS\s1138) +D 2003-12-19T08:40:23 F Makefile.in 5cb273b7d0e945d47ee8b9ad1c2a04ce79927d2d F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -38,7 +38,7 @@ F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8 F src/insert.c 01f66866f35c986eab4a57373ca689a3255ef2df F src/main.c 3dd3cae00bade294011da5a3cf9ff660a610c545 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565 -F src/os.c 000b62b95cad6e3518cb7b71ba9376be192b19dc +F src/os.c 3460bc83541eb276a69723d8babb533559b09344 F src/os.h 729395fefcca4b81ae056aa9ff67b72bb40dd9e0 F src/pager.c ca24fced1ca4c2b8ea519d5fe8ec69a2d846276f F src/pager.h 5da62c83443f26b1792cfd72c96c422f91aadd31 @@ -130,7 +130,7 @@ F test/tableapi.test d881e787779a175238b72f55b5e50d3a85ab47a6 F test/tclsqlite.test f141303e0f2e9a616b551813e2b21bd38c5dca50 F test/temptable.test c82bd6f800f10e8cf96921af6315e5f1c21e2692 F test/tester.tcl 2671536d3650c29e7c105219f277568b0884cb58 -F test/thread1.test e98de6574910978017a621d0851fda13e257763d +F test/thread1.test 0c1fcc2f9bdd887225e56f48db8ddfbb3d0794ba F test/trans.test 75e7a171b5d2d94ee56766459113e2ad0e5f809d F test/trigger1.test 3fe06daecf8334df840025e154e95fd4727600d7 F test/trigger2.test 0767ab30cb5a2c8402c8524f3d566b410b6f5263 @@ -179,7 +179,7 @@ F www/speed.tcl 2f6b1155b99d39adb185f900456d1d592c4832b3 F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1 -P 80b1e277123c07b2db7441a9e600dd69ef55a0da -R ea1fab6d3d994f942c20af002987010c +P b36a4bb61094d539273c21a9e4042384f10a7806 +R de39b8252b64bbe001153a824a71610f U drh -Z b3907cc74f1a3c0fe5cfc79f0eafa427 +Z 22268d4d15b83af3c4ce1b4c3335ae45 diff --git a/manifest.uuid b/manifest.uuid index aa294d8158..ba2ecc6085 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b36a4bb61094d539273c21a9e4042384f10a7806 \ No newline at end of file +7dddbeb586504de30c64a1e61614da447f18c8ba \ No newline at end of file diff --git a/src/os.c b/src/os.c index 60928161f2..d68a12f156 100644 --- a/src/os.c +++ b/src/os.c @@ -168,14 +168,15 @@ static unsigned int elapse; /* ** An instance of the following structure serves as the key used -** to locate a particular lockInfo structure given its inode. +** to locate a particular lockInfo structure given its inode. Note +** that we have to include the process ID as part of the key. On some +** threading implementations (ex: linux), each thread has a separate +** process ID. */ -struct inodeKey { +struct lockKey { dev_t dev; /* Device number */ ino_t ino; /* Inode number */ -#ifdef SQLITE_UNIX_THREADS - pthread_t thread_id; /* Which thread are we */ -#endif + pid_t pid; /* Process ID */ }; /* @@ -185,13 +186,13 @@ struct inodeKey { ** object keeps a count of the number of OsFiles pointing to it. */ struct lockInfo { - struct inodeKey key; /* The lookup key */ + struct lockKey key; /* The lookup key */ int cnt; /* 0: unlocked. -1: write lock. 1...: read lock. */ int nRef; /* Number of pointers to this structure */ }; /* -** This hash table maps inodes (in the form of inodeKey structures) into +** This hash table maps inodes (in the form of lockKey structures) into ** pointers to lockInfo structures. */ static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; @@ -203,7 +204,7 @@ static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 }; */ static struct lockInfo *findLockInfo(int fd){ int rc; - struct inodeKey key; + struct lockKey key; struct stat statbuf; struct lockInfo *pInfo; rc = fstat(fd, &statbuf); @@ -211,9 +212,7 @@ static struct lockInfo *findLockInfo(int fd){ memset(&key, 0, sizeof(key)); key.dev = statbuf.st_dev; key.ino = statbuf.st_ino; -#ifdef SQLITE_UNIX_THREADS - key.thread_id = pthread_self(); -#endif + key.pid = getpid(); pInfo = (struct lockInfo*)sqliteHashFind(&lockHash, &key, sizeof(key)); if( pInfo==0 ){ struct lockInfo *pOld; diff --git a/test/thread1.test b/test/thread1.test index 8dd1bb7f2a..598ba4c555 100644 --- a/test/thread1.test +++ b/test/thread1.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script is multithreading behavior # -# $Id: thread1.test,v 1.1 2003/12/19 02:52:09 drh Exp $ +# $Id: thread1.test,v 1.2 2003/12/19 08:40:24 drh Exp $ set testdir [file dirname $argv0] @@ -38,7 +38,15 @@ do_test thread1-1.1 { } {8 64} # Interleave two threads on read access. Then make sure a third -# thread can write the database. +# thread can write the database. In other words: +# +# read-lock A +# read-lock B +# unlock A +# unlock B +# write-lock C +# +# At one point, the write-lock of C would fail on Linux. # do_test thread1-1.2 { thread_create A test.db @@ -82,7 +90,69 @@ do_test thread1-1.11 { thread_finalize C thread_result C } SQLITE_OK +do_test thread1-1.12 { + catchsql {SELECT name FROM sqlite_master} + execsql {SELECT name FROM sqlite_master} +} {t1 t2} +# Under this scenario: +# +# read-lock A +# read-lock B +# unlock A +# write-lock C +# +# Make sure the write-lock fails with SQLITE_BUSY +# +do_test thread1-2.1 { + thread_halt * + thread_create A test.db + thread_compile A {SELECT a FROM t1} + thread_step A + thread_result A +} SQLITE_ROW +do_test thread1-2.2 { + thread_create B test.db + thread_compile B {SELECT b FROM t1} + thread_step B + thread_result B +} SQLITE_ROW +do_test thread1-2.3 { + thread_create C test.db + thread_compile C {INSERT INTO t2 VALUES(98,99)} + thread_step C + thread_result C +} SQLITE_BUSY +do_test thread1-2.4 { + execsql {SELECT * FROM t2} +} {} +do_test thread1-2.5 { + thread_finalize A + thread_result A +} SQLITE_OK +do_test thread1-2.6 { + thread_step C + thread_result C +} SQLITE_BUSY +do_test thread1-2.7 { + execsql {SELECT * FROM t2} +} {} +do_test thread1-2.8 { + thread_finalize B + thread_result B +} SQLITE_OK +do_test thread1-2.9 { + thread_step C + thread_result C +} SQLITE_DONE +do_test thread1-2.10 { + execsql {SELECT * FROM t2} +} {98 99} +do_test thread1-2.11 { + thread_finalize C + thread_result C +} SQLITE_OK + thread_halt * finish_test