Rework mutexes on the SHM implemention for os_unix to avoid a deadlock during

WAL recovery.

FossilOrigin-Name: 1a0f69bef2c489e81a3d4b910b426972e9ed4054
This commit is contained in:
drh 2010-05-01 17:50:37 +00:00
parent 5cf53537a8
commit 77b95a379c
3 changed files with 45 additions and 25 deletions

View File

@ -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-----

View File

@ -1 +1 @@
9b230c43dfa112e3e1589f9775926807bd36b36e
1a0f69bef2c489e81a3d4b910b426972e9ed4054

View 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;