]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Changes to the unix OS layer aimed at finding and fixing tickets
authordrh <drh@noemail.net>
Wed, 15 Jun 2005 17:47:55 +0000 (17:47 +0000)
committerdrh <drh@noemail.net>
Wed, 15 Jun 2005 17:47:55 +0000 (17:47 +0000)
#1272 and #1285. (CVS 2517)

FossilOrigin-Name: 006dda3119f025d703da4e0215c378206e20cfd0

manifest
manifest.uuid
src/os_unix.c
src/os_unix.h

index cd873d02c883181d1359761ccc253be0f83dde38..873edcb9861487115d279ebe8b0e134a6d7a0117 100644 (file)
--- 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
index ab1bc54dd8306c2d05b1cb375e3eede6cc23e98f..c2414090e7d2497fc6f98d6784fa8a9f82c96c5e 100644 (file)
@@ -1 +1 @@
-833c016023e9e17c226fdd722dcb10bc51ab6f9e
\ No newline at end of file
+006dda3119f025d703da4e0215c378206e20cfd0
\ No newline at end of file
index 9c361a17170609c51f4d6f6ff8d2d351c33549dc..ebf9deb9fee17a6802258ce915667a83971ea8bb 100644 (file)
 #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 <pthread.h>
-# 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;
index 4ea0aee362d6cc395889cd0b1e7a6944fdae675b..5fdfc2ff4ce17cb63f0378bc0fd41afc2dcbaf3c 100644 (file)
 #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
 };
 
 /*