Hello,

In attachement, there's a diff/patch against os_unix.c
in version 3.2.5.
Its allows threads to access successively to a DB handle
and remove the heavy restriction of the SQLITE_MISUSE.
In case of simultaneous access, threads get SQLITE_BUSY
until the OsFile is unlocked.

I test it a bit, it works well with my code and my bad
unix threaded file locks.
Can anybody test it too?

Best regards,

Mon, Sep 05, 2005 at 02:18:41PM -0400: D. Richard Hipp wrote:
> On Mon, 2005-09-05 at 19:58 +0200, René Tegel wrote:
> 
> > As far as i can tell now the windows version of 3.2.5 seems not affected.
> > 
> 
> The restriction that a DB handle can only be used from a single
> thread is currently only enforced on Unix, because Unix boxes
> are the only place where using DB handles in multiple threads is
> a problem.

--
Guillaume FOUGNIES
Eulerian Technologies
--- ../../sqlite-3.2.5/src/os_unix.c    2005-08-25 14:48:33.000000000 +0200
+++ os_unix.c   2005-09-07 20:17:38.000000000 +0200
@@ -82,7 +82,8 @@
 */
 #ifdef SQLITE_UNIX_THREADS
 # define SET_THREADID(X)   X->tid = pthread_self()
-# define CHECK_THREADID(X) (!pthread_equal(X->tid, pthread_self()))
+# define CHECK_THREADID(X) ( threadsOverrideEachOthersLocks>0 && \
+                               check_threadid(X) )
 #else
 # define SET_THREADID(X)
 # define CHECK_THREADID(X) 0
@@ -275,6 +276,26 @@ struct threadTestData {
   int result;            /* Result of the locking operation */
 };
 
+/*
+** Check if the thread is allowed to use the OsFile
+**
+** If another thread opened the OsFile and this OsFile
+** is now lock clear, the new thread is allowed to work
+** with. Its tid is set.
+** This routine is be protected by the global mutex.
+*/
+static int check_threadid(OsFile *id) {
+  if ( pthread_equal(id->tid, pthread_self()) ) {
+    return 0;
+  }
+  if ( id->pLock->locktype == NO_LOCK ) {
+    SET_THREADID(id);
+    return 0;
+  }
+  return 1;
+}
+
+
 #ifdef SQLITE_LOCK_TRACE
 /*
 ** Print out information about all locking operations.
@@ -914,9 +935,14 @@ int sqlite3OsCheckReservedLock(OsFile *i
   int r = 0;
 
   assert( id->isOpen );
-  if( CHECK_THREADID(id) ) return SQLITE_MISUSE;
   sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads 
*/
 
+#ifdef SQLITE_UNIX_THREADS
+  if( CHECK_THREADID(id) ) {
+    r = 1;
+  }
+#endif
+
   /* Check if a thread in this process holds such a lock */
   if( id->pLock->locktype>SHARED_LOCK ){
     r = 1;
@@ -1032,7 +1058,6 @@ int sqlite3OsLock(OsFile *id, int lockty
   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
@@ -1053,6 +1078,13 @@ int sqlite3OsLock(OsFile *id, int lockty
   */
   sqlite3OsEnterMutex();
 
+#ifdef SQLITE_UNIX_THREADS
+  if( CHECK_THREADID(id) ){
+    rc = SQLITE_BUSY;
+    goto end_lock;
+  }
+#endif
+
   /* If some thread using this PID has a lock via a different OsFile*
   ** handle that precludes the requested lock, return BUSY.
   */
@@ -1188,13 +1220,20 @@ int sqlite3OsUnlock(OsFile *id, int lock
   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 ){
     return SQLITE_OK;
   }
   sqlite3OsEnterMutex();
+
+#ifdef SQLITE_UNIX_THREADS
+  if( CHECK_THREADID(id) ){
+    /* This should never happen */
+    rc = SQLITE_IOERR;
+  }
+#endif
+
   pLock = id->pLock;
   assert( pLock->cnt!=0 );
   if( id->locktype>SHARED_LOCK ){
@@ -1265,7 +1304,6 @@ int sqlite3OsUnlock(OsFile *id, int lock
 */
 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;

Reply via email to