mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Take extra precautions to ensure access to unixInodeInfo.pUnused is protected
by all necessary mutexes. FossilOrigin-Name: 8b1e0010b9e0b548a90087f4d25843d2b40f7e9551722ac587fa925d37b510c2
This commit is contained in:
12
manifest
12
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Fix\san\sincorrect\scomment\son\sthe\sunix-nolock\sVFS\sobject.\s\sNo\sfunctional\ncode\schanges.
|
C Take\sextra\sprecautions\sto\sensure\saccess\sto\sunixInodeInfo.pUnused\sis\sprotected\nby\sall\snecessary\smutexes.
|
||||||
D 2018-08-13T11:32:07.332
|
D 2018-08-13T20:46:18.212
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6
|
F Makefile.in 0a3a6c81e6fcb969ff9106e882f0a08547014ba463cb6beca4c4efaecc924ee6
|
||||||
@@ -482,7 +482,7 @@ F src/os.c 8aeb0b0f40f8f5b0da03fe49706695adaf42d2f516ab95abc72e86c245e119de
|
|||||||
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
|
F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
|
||||||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||||
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||||
F src/os_unix.c 4723f4d963c032b5162dd6de79c314c2f67bccfeea2e458aaefa0f3049877f2e
|
F src/os_unix.c 443f6331828b9d0d05f9528a2ae30d927ab988a951ea783dc85538dc9109d489
|
||||||
F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971
|
F src/os_win.c 070cdbb400097c6cda54aa005356095afdc2f3ee691d17192c54724ef146a971
|
||||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||||
F src/pager.c 76d29b8a960dcb8b67210f095899d91e4a90673a6674ea58cfd1115b705a7fb9
|
F src/pager.c 76d29b8a960dcb8b67210f095899d91e4a90673a6674ea58cfd1115b705a7fb9
|
||||||
@@ -1754,7 +1754,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 4195a3f8b5d2c2ec63771890c5aa7b5e2de60b9fa2273652730239b8577ae418
|
P 90f7c193b42f0d8120a8e429bdea5e1cec5d3f45b901db8fc5a5c2ca3e69cba8
|
||||||
R dc8601ab971a0e9f35b0830adc99e5ec
|
R de3b1179403c76c7e851316aaadc94be
|
||||||
U drh
|
U drh
|
||||||
Z 8549fb1e42f4bc7f9d102f40d2b9a827
|
Z 4ac850f8e532f34d7b8e835a0f2cfeb4
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
90f7c193b42f0d8120a8e429bdea5e1cec5d3f45b901db8fc5a5c2ca3e69cba8
|
8b1e0010b9e0b548a90087f4d25843d2b40f7e9551722ac587fa925d37b510c2
|
||||||
@@ -702,12 +702,25 @@ static int robust_open(const char *z, int f, mode_t m){
|
|||||||
** unixEnterMutex()
|
** unixEnterMutex()
|
||||||
** assert( unixMutexHeld() );
|
** assert( unixMutexHeld() );
|
||||||
** unixEnterLeave()
|
** unixEnterLeave()
|
||||||
|
**
|
||||||
|
** To prevent deadlock, the global unixBigLock must must be acquired
|
||||||
|
** before the unixInodeInfo.pLockMutex mutex, if both are held. It is
|
||||||
|
** OK to get the pLockMutex without holding unixBigLock first, but if
|
||||||
|
** that happens, the unixBigLock mutex must not be acquired until after
|
||||||
|
** pLockMutex is released.
|
||||||
|
**
|
||||||
|
** OK: enter(unixBigLock), enter(pLockInfo)
|
||||||
|
** OK: enter(unixBigLock)
|
||||||
|
** OK: enter(pLockInfo)
|
||||||
|
** ERROR: enter(pLockInfo), enter(unixBigLock)
|
||||||
*/
|
*/
|
||||||
static sqlite3_mutex *unixBigLock = 0;
|
static sqlite3_mutex *unixBigLock = 0;
|
||||||
static void unixEnterMutex(void){
|
static void unixEnterMutex(void){
|
||||||
|
assert( sqlite3_mutex_notheld(unixBigLock) ); /* Not a recursive mutex */
|
||||||
sqlite3_mutex_enter(unixBigLock);
|
sqlite3_mutex_enter(unixBigLock);
|
||||||
}
|
}
|
||||||
static void unixLeaveMutex(void){
|
static void unixLeaveMutex(void){
|
||||||
|
assert( sqlite3_mutex_held(unixBigLock) );
|
||||||
sqlite3_mutex_leave(unixBigLock);
|
sqlite3_mutex_leave(unixBigLock);
|
||||||
}
|
}
|
||||||
#ifdef SQLITE_DEBUG
|
#ifdef SQLITE_DEBUG
|
||||||
@@ -1111,7 +1124,7 @@ struct unixFileId {
|
|||||||
**
|
**
|
||||||
** Mutex rules:
|
** Mutex rules:
|
||||||
**
|
**
|
||||||
** (1) The pLockMutex mutex must be held in order to read or write
|
** (1) Only the pLockMutex mutex must be held in order to read or write
|
||||||
** any of the locking fields:
|
** any of the locking fields:
|
||||||
** nShared, nLock, eFileLock, or bProcessLock
|
** nShared, nLock, eFileLock, or bProcessLock
|
||||||
**
|
**
|
||||||
@@ -1119,8 +1132,16 @@ struct unixFileId {
|
|||||||
** be read (but not written) without holding any mutex:
|
** be read (but not written) without holding any mutex:
|
||||||
** fileId, pLockMutex
|
** fileId, pLockMutex
|
||||||
**
|
**
|
||||||
** (3) With the exceptions above, all the fields may only be read
|
** (3) The pUnused field may only be changed while holding bo the
|
||||||
|
** pLockMutex and the bigUnixLock mutex. But it may be read
|
||||||
|
** while holding either.
|
||||||
|
**
|
||||||
|
** (4) With the exceptions above, all the fields may only be read
|
||||||
** or written while holding the global unixBigLock mutex.
|
** or written while holding the global unixBigLock mutex.
|
||||||
|
**
|
||||||
|
** Deadlock prevention: The global unixBigLock mutex may not
|
||||||
|
** be acquired while holding the pLockMutex mutex. If both unixBigLock
|
||||||
|
** and pLockMutex are needed, then unixBigLock must be acquired first.
|
||||||
*/
|
*/
|
||||||
struct unixInodeInfo {
|
struct unixInodeInfo {
|
||||||
struct unixFileId fileId; /* The lookup key */
|
struct unixFileId fileId; /* The lookup key */
|
||||||
@@ -1129,9 +1150,9 @@ struct unixInodeInfo {
|
|||||||
int nLock; /* Number of outstanding file locks */
|
int nLock; /* Number of outstanding file locks */
|
||||||
unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
|
unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
|
||||||
unsigned char bProcessLock; /* An exclusive process lock is held */
|
unsigned char bProcessLock; /* An exclusive process lock is held */
|
||||||
|
UnixUnusedFd *pUnused; /* Unused file descriptors to close */
|
||||||
int nRef; /* Number of pointers to this structure */
|
int nRef; /* Number of pointers to this structure */
|
||||||
unixShmNode *pShmNode; /* Shared memory associated with this inode */
|
unixShmNode *pShmNode; /* Shared memory associated with this inode */
|
||||||
UnixUnusedFd *pUnused; /* Unused file descriptors to close */
|
|
||||||
unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
|
unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
|
||||||
unixInodeInfo *pPrev; /* .... doubly linked */
|
unixInodeInfo *pPrev; /* .... doubly linked */
|
||||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||||
@@ -1147,7 +1168,21 @@ struct unixInodeInfo {
|
|||||||
** A lists of all unixInodeInfo objects.
|
** A lists of all unixInodeInfo objects.
|
||||||
*/
|
*/
|
||||||
static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
|
static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
|
||||||
static unsigned int nUnusedFd = 0; /* Total unused file descriptors */
|
|
||||||
|
#ifdef SQLITE_DEBUG
|
||||||
|
/*
|
||||||
|
** True if the inode mutex is held, or not. Used only within assert()
|
||||||
|
** to help verify correct mutex usage.
|
||||||
|
*/
|
||||||
|
int unixFileMutexHeld(unixFile *pFile){
|
||||||
|
assert( pFile->pInode );
|
||||||
|
return sqlite3_mutex_held(pFile->pInode->pLockMutex);
|
||||||
|
}
|
||||||
|
int unixFileMutexNotheld(unixFile *pFile){
|
||||||
|
assert( pFile->pInode );
|
||||||
|
return sqlite3_mutex_notheld(pFile->pInode->pLockMutex);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
**
|
**
|
||||||
@@ -1253,13 +1288,16 @@ static void closePendingFds(unixFile *pFile){
|
|||||||
unixInodeInfo *pInode = pFile->pInode;
|
unixInodeInfo *pInode = pFile->pInode;
|
||||||
UnixUnusedFd *p;
|
UnixUnusedFd *p;
|
||||||
UnixUnusedFd *pNext;
|
UnixUnusedFd *pNext;
|
||||||
|
assert( unixMutexHeld() );
|
||||||
|
assert( unixFileMutexNotheld(pFile) );
|
||||||
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
||||||
for(p=pInode->pUnused; p; p=pNext){
|
for(p=pInode->pUnused; p; p=pNext){
|
||||||
pNext = p->pNext;
|
pNext = p->pNext;
|
||||||
robust_close(pFile, p->fd, __LINE__);
|
robust_close(pFile, p->fd, __LINE__);
|
||||||
sqlite3_free(p);
|
sqlite3_free(p);
|
||||||
nUnusedFd--;
|
|
||||||
}
|
}
|
||||||
pInode->pUnused = 0;
|
pInode->pUnused = 0;
|
||||||
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1271,6 +1309,7 @@ static void closePendingFds(unixFile *pFile){
|
|||||||
static void releaseInodeInfo(unixFile *pFile){
|
static void releaseInodeInfo(unixFile *pFile){
|
||||||
unixInodeInfo *pInode = pFile->pInode;
|
unixInodeInfo *pInode = pFile->pInode;
|
||||||
assert( unixMutexHeld() );
|
assert( unixMutexHeld() );
|
||||||
|
assert( unixFileMutexNotheld(pFile) );
|
||||||
if( ALWAYS(pInode) ){
|
if( ALWAYS(pInode) ){
|
||||||
pInode->nRef--;
|
pInode->nRef--;
|
||||||
if( pInode->nRef==0 ){
|
if( pInode->nRef==0 ){
|
||||||
@@ -1291,7 +1330,6 @@ static void releaseInodeInfo(unixFile *pFile){
|
|||||||
sqlite3_free(pInode);
|
sqlite3_free(pInode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert( inodeList!=0 || nUnusedFd==0 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1361,7 +1399,6 @@ static int findInodeInfo(
|
|||||||
#else
|
#else
|
||||||
fileId.ino = (u64)statbuf.st_ino;
|
fileId.ino = (u64)statbuf.st_ino;
|
||||||
#endif
|
#endif
|
||||||
assert( inodeList!=0 || nUnusedFd==0 );
|
|
||||||
pInode = inodeList;
|
pInode = inodeList;
|
||||||
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
|
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
|
||||||
pInode = pInode->pNext;
|
pInode = pInode->pNext;
|
||||||
@@ -1826,11 +1863,14 @@ end_lock:
|
|||||||
static void setPendingFd(unixFile *pFile){
|
static void setPendingFd(unixFile *pFile){
|
||||||
unixInodeInfo *pInode = pFile->pInode;
|
unixInodeInfo *pInode = pFile->pInode;
|
||||||
UnixUnusedFd *p = pFile->pPreallocatedUnused;
|
UnixUnusedFd *p = pFile->pPreallocatedUnused;
|
||||||
|
assert( unixMutexHeld() );
|
||||||
|
assert( unixFileMutexNotheld(pFile) );
|
||||||
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
||||||
p->pNext = pInode->pUnused;
|
p->pNext = pInode->pUnused;
|
||||||
pInode->pUnused = p;
|
pInode->pUnused = p;
|
||||||
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
||||||
pFile->h = -1;
|
pFile->h = -1;
|
||||||
pFile->pPreallocatedUnused = 0;
|
pFile->pPreallocatedUnused = 0;
|
||||||
nUnusedFd++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1851,6 +1891,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
|||||||
unixInodeInfo *pInode;
|
unixInodeInfo *pInode;
|
||||||
struct flock lock;
|
struct flock lock;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
|
int wantToClosePending = 0; /* True to try to close file old descriptors */
|
||||||
|
|
||||||
assert( pFile );
|
assert( pFile );
|
||||||
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
|
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
|
||||||
@@ -1988,14 +2029,21 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
|||||||
*/
|
*/
|
||||||
pInode->nLock--;
|
pInode->nLock--;
|
||||||
assert( pInode->nLock>=0 );
|
assert( pInode->nLock>=0 );
|
||||||
if( pInode->nLock==0 ){
|
if( pInode->nLock==0 && pInode->pUnused!=0 ){
|
||||||
closePendingFds(pFile);
|
wantToClosePending = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end_unlock:
|
end_unlock:
|
||||||
sqlite3_mutex_leave(pInode->pLockMutex);
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
||||||
if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
|
if( rc==SQLITE_OK ){
|
||||||
|
pFile->eFileLock = eFileLock;
|
||||||
|
if( wantToClosePending ){
|
||||||
|
unixEnterMutex();
|
||||||
|
if( pInode->nLock==0 ) closePendingFds(pFile);
|
||||||
|
unixLeaveMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2068,6 +2116,7 @@ static int unixClose(sqlite3_file *id){
|
|||||||
unixFile *pFile = (unixFile *)id;
|
unixFile *pFile = (unixFile *)id;
|
||||||
verifyDbFile(pFile);
|
verifyDbFile(pFile);
|
||||||
unixUnlock(id, NO_LOCK);
|
unixUnlock(id, NO_LOCK);
|
||||||
|
assert( unixFileMutexNotheld(pFile) );
|
||||||
unixEnterMutex();
|
unixEnterMutex();
|
||||||
|
|
||||||
/* unixFile.pInode is always valid here. Otherwise, a different close
|
/* unixFile.pInode is always valid here. Otherwise, a different close
|
||||||
@@ -2679,6 +2728,7 @@ static int semXClose(sqlite3_file *id) {
|
|||||||
unixFile *pFile = (unixFile*)id;
|
unixFile *pFile = (unixFile*)id;
|
||||||
semXUnlock(id, NO_LOCK);
|
semXUnlock(id, NO_LOCK);
|
||||||
assert( pFile );
|
assert( pFile );
|
||||||
|
assert( unixFileMutexNotheld(pFile) );
|
||||||
unixEnterMutex();
|
unixEnterMutex();
|
||||||
releaseInodeInfo(pFile);
|
releaseInodeInfo(pFile);
|
||||||
unixLeaveMutex();
|
unixLeaveMutex();
|
||||||
@@ -3036,6 +3086,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
|
|||||||
unixInodeInfo *pInode;
|
unixInodeInfo *pInode;
|
||||||
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
|
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
|
||||||
int skipShared = 0;
|
int skipShared = 0;
|
||||||
|
int wantToClosePending = 0;
|
||||||
#ifdef SQLITE_TEST
|
#ifdef SQLITE_TEST
|
||||||
int h = pFile->h;
|
int h = pFile->h;
|
||||||
#endif
|
#endif
|
||||||
@@ -3119,14 +3170,19 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
|
|||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
pInode->nLock--;
|
pInode->nLock--;
|
||||||
assert( pInode->nLock>=0 );
|
assert( pInode->nLock>=0 );
|
||||||
if( pInode->nLock==0 ){
|
if( pInode->nLock==0 && pInode->pUnused!=0 ) wantToClosePending = 1;
|
||||||
closePendingFds(pFile);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_mutex_leave(pInode->pLockMutex);
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
||||||
if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
|
if( rc==SQLITE_OK ){
|
||||||
|
pFile->eFileLock = eFileLock;
|
||||||
|
if( wantToClosePending ){
|
||||||
|
unixEnterMutex();
|
||||||
|
if( pInode->nLock==0 ) closePendingFds(pFile);
|
||||||
|
unixLeaveMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3138,6 +3194,7 @@ static int afpClose(sqlite3_file *id) {
|
|||||||
unixFile *pFile = (unixFile*)id;
|
unixFile *pFile = (unixFile*)id;
|
||||||
assert( id!=0 );
|
assert( id!=0 );
|
||||||
afpUnlock(id, NO_LOCK);
|
afpUnlock(id, NO_LOCK);
|
||||||
|
assert( unixFileMutexNotheld(pFile) );
|
||||||
unixEnterMutex();
|
unixEnterMutex();
|
||||||
if( pFile->pInode && pFile->pInode->nLock ){
|
if( pFile->pInode && pFile->pInode->nLock ){
|
||||||
/* If there are outstanding locks, do not actually close the file just
|
/* If there are outstanding locks, do not actually close the file just
|
||||||
@@ -4451,6 +4508,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
|
|||||||
/* Check to see if a unixShmNode object already exists. Reuse an existing
|
/* Check to see if a unixShmNode object already exists. Reuse an existing
|
||||||
** one if present. Create a new one if necessary.
|
** one if present. Create a new one if necessary.
|
||||||
*/
|
*/
|
||||||
|
assert( unixFileMutexNotheld(pDbFd) );
|
||||||
unixEnterMutex();
|
unixEnterMutex();
|
||||||
pInode = pDbFd->pInode;
|
pInode = pDbFd->pInode;
|
||||||
pShmNode = pInode->pShmNode;
|
pShmNode = pInode->pShmNode;
|
||||||
@@ -4833,6 +4891,7 @@ static void unixShmBarrier(
|
|||||||
){
|
){
|
||||||
UNUSED_PARAMETER(fd);
|
UNUSED_PARAMETER(fd);
|
||||||
sqlite3MemoryBarrier(); /* compiler-defined memory barrier */
|
sqlite3MemoryBarrier(); /* compiler-defined memory barrier */
|
||||||
|
assert( unixFileMutexNotheld((unixFile*)fd) );
|
||||||
unixEnterMutex(); /* Also mutex, for redundancy */
|
unixEnterMutex(); /* Also mutex, for redundancy */
|
||||||
unixLeaveMutex();
|
unixLeaveMutex();
|
||||||
}
|
}
|
||||||
@@ -4874,6 +4933,7 @@ static int unixShmUnmap(
|
|||||||
|
|
||||||
/* If pShmNode->nRef has reached 0, then close the underlying
|
/* If pShmNode->nRef has reached 0, then close the underlying
|
||||||
** shared-memory file, too */
|
** shared-memory file, too */
|
||||||
|
assert( unixFileMutexNotheld(pDbFd) );
|
||||||
unixEnterMutex();
|
unixEnterMutex();
|
||||||
assert( pShmNode->nRef>0 );
|
assert( pShmNode->nRef>0 );
|
||||||
pShmNode->nRef--;
|
pShmNode->nRef--;
|
||||||
@@ -5696,7 +5756,7 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
|
|||||||
**
|
**
|
||||||
** Even if a subsequent open() call does succeed, the consequences of
|
** Even if a subsequent open() call does succeed, the consequences of
|
||||||
** not searching for a reusable file descriptor are not dire. */
|
** not searching for a reusable file descriptor are not dire. */
|
||||||
if( nUnusedFd>0 && 0==osStat(zPath, &sStat) ){
|
if( inodeList!=0 && 0==osStat(zPath, &sStat) ){
|
||||||
unixInodeInfo *pInode;
|
unixInodeInfo *pInode;
|
||||||
|
|
||||||
pInode = inodeList;
|
pInode = inodeList;
|
||||||
@@ -5706,12 +5766,14 @@ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
|
|||||||
}
|
}
|
||||||
if( pInode ){
|
if( pInode ){
|
||||||
UnixUnusedFd **pp;
|
UnixUnusedFd **pp;
|
||||||
|
assert( sqlite3_mutex_notheld(pInode->pLockMutex) );
|
||||||
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
||||||
for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
|
for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
|
||||||
pUnused = *pp;
|
pUnused = *pp;
|
||||||
if( pUnused ){
|
if( pUnused ){
|
||||||
nUnusedFd--;
|
|
||||||
*pp = pUnused->pNext;
|
*pp = pUnused->pNext;
|
||||||
}
|
}
|
||||||
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unixLeaveMutex();
|
unixLeaveMutex();
|
||||||
|
|||||||
Reference in New Issue
Block a user