Changes to the unix OS layer aimed at finding and fixing tickets

#1272 and #1285. (CVS 2517)

FossilOrigin-Name: 006dda3119f025d703da4e0215c378206e20cfd0
This commit is contained in:
drh 2005-06-15 17:47:55 +00:00
parent 8d904f058b
commit 2b4b5962c4
4 changed files with 129 additions and 27 deletions

View File

@ -1,5 +1,5 @@
C Fix\san\sNDEBUG\sversus\sSQLITE_DEBUG\sconfusion\sissue.\s(CVS\s2516)
D 2005-06-14T17:47:58
C Changes\sto\sthe\sunix\sOS\slayer\saimed\sat\sfinding\sand\sfixing\stickets\n#1272\sand\s#1285.\s(CVS\s2517)
D 2005-06-15T17:47:56
F Makefile.in 8129e7f261d405db783676f9ca31e0841768c652
F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -49,8 +49,8 @@ F src/os.h c4b34bd4d6fea51a420f337468b907f4edecb161
F src/os_common.h 0e7f428ba0a6c40a61bc56c4e96f493231301b73
F src/os_test.c 91e5f22dd89491e5e1554820e715805f43fa4ece
F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3
F src/os_unix.c 45540d7ee5095566da6685d584598edee5be857c
F src/os_unix.h 39a393252e69e72b06715c9958df05ddbc4aa971
F src/os_unix.c be8f327f9578a6bd1b1550ac3d083c427dfeb0f3
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
F src/os_win.c fe7b99cfcfb61d9bf54493ddf5857885a657fb89
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c 841a2cdddd4275de36cda26ed9dc54ae942660ce
@ -281,7 +281,7 @@ F www/tclsqlite.tcl 425be741b8ae664f55cb1ef2371aab0a75109cf9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b
P 3d7ee5b92d7e30f90cb7a8b3efd649b36480b61b
R aeb4bbc68944baf149e09bcc056ddc6f
P 833c016023e9e17c226fdd722dcb10bc51ab6f9e
R 4fc1c92527593ea11a80a7f2b02c682c
U drh
Z 07b3bf8c07a105e6c637a65b688c004c
Z 4b9494e47411528806d734eda008aeec

View File

@ -1 +1 @@
833c016023e9e17c226fdd722dcb10bc51ab6f9e
006dda3119f025d703da4e0215c378206e20cfd0

View File

@ -56,25 +56,36 @@
# define fcntl(A,B,C) 0
#endif
/*
** Macros used to determine whether or not to use threads. The
** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for
** Posix threads and SQLITE_W32_THREADS is defined if we are
** synchronizing using Win32 threads.
*/
#if defined(THREADSAFE) && THREADSAFE
# include <pthread.h>
# define SQLITE_UNIX_THREADS 1
#endif
/*
** Include code that is common to all os_*.c files
*/
#include "os_common.h"
#if defined(THREADSAFE) && THREADSAFE && defined(__linux__)
#define getpid pthread_self
/*
** The threadid macro resolves to the thread-id or to 0. Used for
** testing and debugging only.
*/
#ifdef SQLITE_UNIX_THREADS
#define threadid pthread_self()
#else
#define threadid 0
#endif
/*
** Set or check the OsFile.tid field. This field is set when an OsFile
** is first opened. All subsequent uses of the OsFile verify that the
** same thread is operating on the OsFile. Some operating systems do
** not allow locks to be overridden by other threads and that restriction
** means that sqlite3* database handles cannot be moved from one thread
** to another. This logic makes sure a user does not try to do that
** by mistake.
*/
#ifdef SQLITE_UNIX_THREADS
# define SET_THREADID(X) X->tid = pthread_self()
# define CHECK_THREADID(X) (!pthread_equal(X->tid, pthread_self()))
#else
# define SET_THREADID(X)
# define CHECK_THREADID(X) 0
#endif
/*
@ -264,6 +275,65 @@ struct threadTestData {
int result; /* Result of the locking operation */
};
#ifdef SQLITE_LOCK_TRACE
/*
** Print out information about all locking operations.
**
** This routine is used for troubleshooting locks on multithreaded
** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE
** command-line option on the compiler. This code is normally
** turnned off.
*/
static int lockTrace(int fd, int op, struct flock *p){
char *zOpName, *zType;
int s;
int savedErrno;
if( op==F_GETLK ){
zOpName = "GETLK";
}else if( op==F_SETLK ){
zOpName = "SETLK";
}else{
s = fcntl(fd, op, p);
sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
return s;
}
if( p->l_type==F_RDLCK ){
zType = "RDLCK";
}else if( p->l_type==F_WRLCK ){
zType = "WRLCK";
}else if( p->l_type==F_UNLCK ){
zType = "UNLCK";
}else{
assert( 0 );
}
assert( p->l_whence==SEEK_SET );
s = fcntl(fd, op, p);
savedErrno = errno;
sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
(int)p->l_pid, s);
if( s && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
struct flock l2;
l2 = *p;
fcntl(fd, F_GETLK, &l2);
if( l2.l_type==F_RDLCK ){
zType = "RDLCK";
}else if( l2.l_type==F_WRLCK ){
zType = "WRLCK";
}else if( l2.l_type==F_UNLCK ){
zType = "UNLCK";
}else{
assert( 0 );
}
sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
}
errno = savedErrno;
return s;
}
#define fcntl lockTrace
#endif /* SQLITE_LOCK_TRACE */
/*
** The testThreadLockingBehavior() routine launches two separate
** threads on this routine. This routine attempts to lock a file
@ -443,6 +513,7 @@ int sqlite3OsOpenReadWrite(
int rc;
assert( !id->isOpen );
id->dirfd = -1;
SET_THREADID(id);
id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY,
SQLITE_DEFAULT_FILE_PERMISSIONS);
if( id->h<0 ){
@ -494,6 +565,7 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
if( access(zFilename, 0)==0 ){
return SQLITE_CANTOPEN;
}
SET_THREADID(id);
id->dirfd = -1;
id->h = open(zFilename,
O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600);
@ -528,6 +600,7 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
int rc;
assert( !id->isOpen );
SET_THREADID(id);
id->dirfd = -1;
id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
if( id->h<0 ){
@ -572,6 +645,7 @@ int sqlite3OsOpenDirectory(
** open. */
return SQLITE_CANTOPEN;
}
SET_THREADID(id);
assert( id->dirfd<0 );
id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0);
if( id->dirfd<0 ){
@ -839,6 +913,7 @@ int sqlite3OsCheckReservedLock(OsFile *id){
int r = 0;
assert( id->isOpen );
if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */
/* Check if a thread in this process holds such a lock */
@ -956,6 +1031,7 @@ int sqlite3OsLock(OsFile *id, int locktype){
TRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", id->h, locktypeName(locktype),
locktypeName(id->locktype), locktypeName(pLock->locktype), pLock->cnt
,getpid() );
if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
/* If there is already a lock of this type or more restrictive on the
** OsFile, do nothing. Don't use the end_lock: exit path, as
@ -1002,6 +1078,7 @@ int sqlite3OsLock(OsFile *id, int locktype){
}
lock.l_len = 1L;
lock.l_whence = SEEK_SET;
/* A PENDING lock is needed before acquiring a SHARED lock and before
@ -1037,7 +1114,10 @@ int sqlite3OsLock(OsFile *id, int locktype){
lock.l_start = PENDING_BYTE;
lock.l_len = 1L;
lock.l_type = F_UNLCK;
fcntl(id->h, F_SETLK, &lock);
if( fcntl(id->h, F_SETLK, &lock)!=0 ){
rc = SQLITE_IOERR; /* This should never happen */
goto end_lock;
}
if( s ){
rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
}else{
@ -1107,6 +1187,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
assert( id->isOpen );
TRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", id->h, locktype, id->locktype,
id->pLock->locktype, id->pLock->cnt, getpid());
if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
assert( locktype<=SHARED_LOCK );
if( id->locktype<=locktype ){
@ -1131,8 +1212,11 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
lock.l_whence = SEEK_SET;
lock.l_start = PENDING_BYTE;
lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE );
fcntl(id->h, F_SETLK, &lock);
pLock->locktype = SHARED_LOCK;
if( fcntl(id->h, F_SETLK, &lock)==0 ){
pLock->locktype = SHARED_LOCK;
}else{
rc = SQLITE_IOERR; /* This should never happen */
}
}
if( locktype==NO_LOCK ){
struct openCnt *pOpen;
@ -1146,8 +1230,11 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
lock.l_type = F_UNLCK;
lock.l_whence = SEEK_SET;
lock.l_start = lock.l_len = 0L;
fcntl(id->h, F_SETLK, &lock);
pLock->locktype = NO_LOCK;
if( fcntl(id->h, F_SETLK, &lock)==0 ){
pLock->locktype = NO_LOCK;
}else{
rc = SQLITE_IOERR; /* This should never happen */
}
}
/* Decrement the count of locks against this same file. When the
@ -1177,6 +1264,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){
*/
int sqlite3OsClose(OsFile *id){
if( !id->isOpen ) return SQLITE_OK;
if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
sqlite3OsUnlock(id, NO_LOCK);
if( id->dirfd>=0 ) close(id->dirfd);
id->dirfd = -1;

View File

@ -51,6 +51,17 @@
#include <fcntl.h>
#include <unistd.h>
/*
** Macros used to determine whether or not to use threads. The
** SQLITE_UNIX_THREADS macro is defined if we are synchronizing for
** Posix threads and SQLITE_W32_THREADS is defined if we are
** synchronizing using Win32 threads.
*/
#if defined(THREADSAFE) && THREADSAFE
# include <pthread.h>
# define SQLITE_UNIX_THREADS 1
#endif
/*
** The OsFile structure is a operating-system independing representation
** of an open file handle. It is defined differently for each architecture.
@ -70,6 +81,9 @@ struct OsFile {
unsigned char isOpen; /* True if needs to be closed */
unsigned char fullSync; /* Use F_FULLSYNC if available */
int dirfd; /* File descriptor for the directory */
#ifdef SQLITE_UNIX_THREADS
pthread_t tid; /* The thread authorized to use this OsFile */
#endif
};
/*