1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Fix a memory leak that can occur in os_unix.c if an IO error occurs within the xUnlock method.

FossilOrigin-Name: 6c5c04eea1f0e8d61883ee8675c249fbf895dc01
This commit is contained in:
dan
2010-06-16 10:55:42 +00:00
parent a4a9095ec0
commit b0ac3e3a17
8 changed files with 247 additions and 69 deletions

View File

@@ -735,18 +735,50 @@ struct unixInodeInfo {
*/
static unixInodeInfo *inodeList = 0;
/*
** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
** If all such file descriptors are closed without error, the list is
** cleared and SQLITE_OK returned.
**
** Otherwise, if an error occurs, then successfully closed file descriptor
** entries are removed from the list, and SQLITE_IOERR_CLOSE returned.
** not deleted and SQLITE_IOERR_CLOSE returned.
*/
static int closePendingFds(unixFile *pFile){
int rc = SQLITE_OK;
unixInodeInfo *pInode = pFile->pInode;
UnixUnusedFd *pError = 0;
UnixUnusedFd *p;
UnixUnusedFd *pNext;
for(p=pInode->pUnused; p; p=pNext){
pNext = p->pNext;
if( close(p->fd) ){
pFile->lastErrno = errno;
rc = SQLITE_IOERR_CLOSE;
p->pNext = pError;
pError = p;
}else{
sqlite3_free(p);
}
}
pInode->pUnused = pError;
return rc;
}
/*
** Release a unixInodeInfo structure previously allocated by findInodeInfo().
**
** The mutex entered using the unixEnterMutex() function must be held
** when this function is called.
*/
static void releaseInodeInfo(unixInodeInfo *pInode){
static void releaseInodeInfo(unixFile *pFile){
unixInodeInfo *pInode = pFile->pInode;
assert( unixMutexHeld() );
if( pInode ){
pInode->nRef--;
if( pInode->nRef==0 ){
assert( pInode->pShmNode==0 );
closePendingFds(pFile);
if( pInode->pPrev ){
assert( pInode->pPrev->pNext==pInode );
pInode->pPrev->pNext = pInode->pNext;
@@ -1152,36 +1184,6 @@ end_lock:
return rc;
}
/*
** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
** If all such file descriptors are closed without error, the list is
** cleared and SQLITE_OK returned.
**
** Otherwise, if an error occurs, then successfully closed file descriptor
** entries are removed from the list, and SQLITE_IOERR_CLOSE returned.
** not deleted and SQLITE_IOERR_CLOSE returned.
*/
static int closePendingFds(unixFile *pFile){
int rc = SQLITE_OK;
unixInodeInfo *pInode = pFile->pInode;
UnixUnusedFd *pError = 0;
UnixUnusedFd *p;
UnixUnusedFd *pNext;
for(p=pInode->pUnused; p; p=pNext){
pNext = p->pNext;
if( close(p->fd) ){
pFile->lastErrno = errno;
rc = SQLITE_IOERR_CLOSE;
p->pNext = pError;
pError = p;
}else{
sqlite3_free(p);
}
}
pInode->pUnused = pError;
return rc;
}
/*
** Add the file descriptor used by file handle pFile to the corresponding
** pUnused list.
@@ -1451,7 +1453,7 @@ static int unixClose(sqlite3_file *id){
*/
setPendingFd(pFile);
}
releaseInodeInfo(pFile->pInode);
releaseInodeInfo(pFile);
rc = closeUnixFile(id);
unixLeaveMutex();
}
@@ -2066,7 +2068,7 @@ static int semClose(sqlite3_file *id) {
semUnlock(id, NO_LOCK);
assert( pFile );
unixEnterMutex();
releaseInodeInfo(pFile->pInode);
releaseInodeInfo(pFile);
unixLeaveMutex();
closeUnixFile(id);
}
@@ -2533,7 +2535,7 @@ static int afpClose(sqlite3_file *id) {
*/
setPendingFd(pFile);
}
releaseInodeInfo(pFile->pInode);
releaseInodeInfo(pFile);
sqlite3_free(pFile->lockingContext);
rc = closeUnixFile(id);
unixLeaveMutex();