]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Rework mutexes on the SHM implemention for os_unix to avoid a deadlock during
authordrh <drh@noemail.net>
Sat, 1 May 2010 17:50:37 +0000 (17:50 +0000)
committerdrh <drh@noemail.net>
Sat, 1 May 2010 17:50:37 +0000 (17:50 +0000)
WAL recovery.

FossilOrigin-Name: 1a0f69bef2c489e81a3d4b910b426972e9ed4054

manifest
manifest.uuid
src/os_unix.c

index d6e1251d4a21bf01462ab096e1453184c32797df..75db7fed56890b8e44820050868382a623a62d55 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,8 @@
-C Support\scompile-time\soption\sSQLITE_OMIT_WAL,\sfor\sbuilding\swithout\sWAL\ssupport.
-D 2010-05-01T16:40:20
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+C Rework\smutexes\son\sthe\sSHM\simplemention\sfor\sos_unix\sto\savoid\sa\sdeadlock\sduring\nWAL\srecovery.
+D 2010-05-01T17:50:38
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in d83a0ffef3dcbfb08b410a6c6dd6c009ec9167fb
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -150,7 +153,7 @@ F src/os.c 8bc63cf91e9802e2b807198e54e50227fa889306
 F src/os.h 534b082c3cb349ad05fa6fa0b06087e022af282c
 F src/os_common.h 0d6ee583b6ee3185eb9d951f890c6dd03021a08d
 F src/os_os2.c 8ad77a418630d7dee91d1bb04f79c2096301d3a0
-F src/os_unix.c 27ec47f27987b9f25bc55df5e458f7f380730f66
+F src/os_unix.c d402146bd3731575ff399d2ebcdc0867034e8451
 F src/os_win.c a8fc01d8483be472e495793c01064fd87e56a5c1
 F src/pager.c e9c7fe979b32a3c5bf4216d8fbe1cf8beff8a1b8
 F src/pager.h 934b598583a9d936bb13c37d62a2fe68ac48781c
@@ -808,7 +811,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P dcabc90ca588281fa7a290972ec8af6816932489
-R e813455665cf7f3ad3b5157515fc2fe7
-U dan
-Z 955de6008d5a15476ae5c3900eb59d71
+P 9b230c43dfa112e3e1589f9775926807bd36b36e
+R 70dfb91700ac677788e5556f2fcdd9f6
+U drh
+Z aec6f98e0ebcce7f7132104408636399
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.6 (GNU/Linux)
+
+iD8DBQFL3GnyoxKgR168RlERAm3bAJwJDWmdlrwEHnjKELzYU8/fifSwAQCeNiz2
+E59QAYMayqNW9OBp4QF0LdQ=
+=o6hV
+-----END PGP SIGNATURE-----
index c4a52f55ba338690315f2cc3cb408eddf1ce0181..c88f378a4b0fafd288e3e3157bb887952adad109 100644 (file)
@@ -1 +1 @@
-9b230c43dfa112e3e1589f9775926807bd36b36e
\ No newline at end of file
+1a0f69bef2c489e81a3d4b910b426972e9ed4054
\ No newline at end of file
index b2c22c3652d125027b541279918eb3cb408cdbfb..caf22effe6ace5194f4509d6e2c46f1ec5a0b5b1 100644 (file)
@@ -4594,7 +4594,6 @@ struct unixShmFile {
   struct unixFileId fid;     /* Unique file identifier */
   sqlite3_mutex *mutex;      /* Mutex to access this object */
   sqlite3_mutex *mutexBuf;   /* Mutex to access zBuf[] */
-  sqlite3_mutex *mutexRecov; /* The RECOVER mutex */
   char *zFilename;           /* Name of the file */
   int h;                     /* Open file descriptor */
   int szMap;                 /* Size of the mapping of file into memory */
@@ -4633,7 +4632,6 @@ struct unixShm {
   u8 readLock;               /* Which of the two read-lock states to use */
   u8 hasMutex;               /* True if holding the unixShmFile mutex */
   u8 hasMutexBuf;            /* True if holding pFile->mutexBuf */
-  u8 hasMutexRecov;          /* True if holding pFile->mutexRecov */
   u8 sharedMask;             /* Mask of shared locks held */
   u8 exclMask;               /* Mask of exclusive locks held */
 #ifdef SQLITE_DEBUG
@@ -4909,7 +4907,6 @@ static void unixShmPurge(void){
     if( p->nRef==0 ){
       if( p->mutex ) sqlite3_mutex_free(p->mutex);
       if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
-      if( p->mutexRecov ) sqlite3_mutex_free(p->mutexRecov);
       if( p->h>=0 ) close(p->h);
       *pp = p->pNext;
       sqlite3_free(p);
@@ -4979,11 +4976,6 @@ static int unixShmOpen(
       rc = SQLITE_NOMEM;
       goto shm_open_err;
     }
-    pFile->mutexRecov = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
-    if( pFile->mutexRecov==0 ){
-      rc = SQLITE_NOMEM;
-      goto shm_open_err;
-    }
 
     pFile->h = open(zName, O_RDWR|O_CREAT, 0664);
     if( pFile->h<0 ){
@@ -5124,8 +5116,19 @@ static int unixShmSize(
 ** whatever mapping size is convenient.
 **
 ** *ppBuf is made to point to the memory which is a mapping of the
-** underlying storage.  This segment is locked.  unixShmRelease()
-** must be called to release the lock.
+** underlying storage.  A mutex is acquired to prevent other threads
+** from running while *ppBuf is in use in order to prevent other threads
+** remapping *ppBuf out from under this thread.  The unixShmRelease()
+** call will release the mutex.  However, if the lock state is CHECKPOINT,
+** the mutex is not acquired because CHECKPOINT will never remap the
+** buffer.  RECOVER might remap, though, so CHECKPOINT will acquire
+** the mutex if and when it promotes to RECOVER.
+**
+** RECOVER needs to be atomic.  The same mutex that prevents *ppBuf from
+** being remapped also prevents more than one thread from being in
+** RECOVER at a time.  But, RECOVER sometimes wants to remap itself.
+** To prevent RECOVER from losing its lock while remapping, the
+** mutex is not released by unixShmRelease() when in RECOVER.
 **
 ** *pNewMapSize is set to the size of the mapping.
 **
@@ -5142,7 +5145,7 @@ static int unixShmGet(
   unixShmFile *pFile = p->pFile;
   int rc = SQLITE_OK;
 
-  if( p->lockState!=SQLITE_SHM_CHECKPOINT ){
+  if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
     sqlite3_mutex_enter(pFile->mutexBuf);
     p->hasMutexBuf = 1;
   }
@@ -5170,10 +5173,16 @@ static int unixShmGet(
 /*
 ** Release the lock held on the shared memory segment to that other
 ** threads are free to resize it if necessary.
+**
+** If the lock is not currently held, this routine is a harmless no-op.
+**
+** If the shared-memory object is in lock state RECOVER, then we do not
+** really want to release the lock, so in that case too, this routine
+** is a no-op.
 */
 static int unixShmRelease(sqlite3_shm *pSharedMem){
   unixShm *p = (unixShm*)pSharedMem;
-  if( p->hasMutexBuf ){
+  if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
     unixShmFile *pFile = p->pFile;
     sqlite3_mutex_leave(pFile->mutexBuf);
     p->hasMutexBuf = 0;
@@ -5235,6 +5244,11 @@ static int unixShmLock(
 
   OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n",
             p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock]));
+  
+  if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
+    sqlite3_mutex_enter(pFile->mutexBuf);
+    p->hasMutexBuf = 1;
+  }
   sqlite3_mutex_enter(pFile->mutex);
   switch( desiredLock ){
     case SQLITE_SHM_UNLOCK: {
@@ -5268,7 +5282,6 @@ static int unixShmLock(
       }else{
         assert( p->lockState==SQLITE_SHM_RECOVER );
         unixShmUnlock(pFile, p, UNIX_SHM_MUTEX);
-        sqlite3_mutex_leave(pFile->mutexRecov);
         p->lockState = p->readLock;
         rc = SQLITE_OK;
       }
@@ -5289,7 +5302,6 @@ static int unixShmLock(
            || p->lockState==SQLITE_SHM_RECOVER );
       if( p->lockState==SQLITE_SHM_RECOVER ){
         unixShmUnlock(pFile, p, UNIX_SHM_MUTEX);
-        sqlite3_mutex_leave(pFile->mutexRecov);
         p->lockState = SQLITE_SHM_CHECKPOINT;
         rc = SQLITE_OK;
       }
@@ -5312,9 +5324,7 @@ static int unixShmLock(
       assert( p->lockState==SQLITE_SHM_READ
            || p->lockState==SQLITE_SHM_READ_FULL
            || p->lockState==SQLITE_SHM_CHECKPOINT );
-      sqlite3_mutex_leave(pFile->mutex);
-      sqlite3_mutex_enter(pFile->mutexRecov);
-      sqlite3_mutex_enter(pFile->mutex);
+      assert( sqlite3_mutex_held(pFile->mutexBuf) );
       rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_MUTEX);
       if( rc==SQLITE_OK ){
         p->lockState = SQLITE_SHM_RECOVER;