From: drh Date: Wed, 15 Jun 2005 17:47:55 +0000 (+0000) Subject: Changes to the unix OS layer aimed at finding and fixing tickets X-Git-Tag: version-3.6.10~3642 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2b4b5962c44b65d4aff224e54f3bfef452c432a8;p=thirdparty%2Fsqlite.git Changes to the unix OS layer aimed at finding and fixing tickets #1272 and #1285. (CVS 2517) FossilOrigin-Name: 006dda3119f025d703da4e0215c378206e20cfd0 --- diff --git a/manifest b/manifest index cd873d02c8..873edcb986 100644 --- a/manifest +++ b/manifest @@ -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 diff --git a/manifest.uuid b/manifest.uuid index ab1bc54dd8..c2414090e7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -833c016023e9e17c226fdd722dcb10bc51ab6f9e \ No newline at end of file +006dda3119f025d703da4e0215c378206e20cfd0 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 9c361a1717..ebf9deb9fe 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -57,24 +57,35 @@ #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. +** Include code that is common to all os_*.c files */ -#if defined(THREADSAFE) && THREADSAFE -# include -# define SQLITE_UNIX_THREADS 1 -#endif - +#include "os_common.h" /* -** Include code that is common to all os_*.c files +** The threadid macro resolves to the thread-id or to 0. Used for +** testing and debugging only. */ -#include "os_common.h" +#ifdef SQLITE_UNIX_THREADS +#define threadid pthread_self() +#else +#define threadid 0 +#endif -#if defined(THREADSAFE) && THREADSAFE && defined(__linux__) -#define getpid pthread_self +/* +** 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; diff --git a/src/os_unix.h b/src/os_unix.h index 4ea0aee362..5fdfc2ff4c 100644 --- a/src/os_unix.h +++ b/src/os_unix.h @@ -51,6 +51,17 @@ #include #include +/* +** 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 +# 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 }; /*