aboutsummaryrefslogtreecommitdiff
path: root/src/os_unix.c
diff options
context:
space:
mode:
authordan <dan@noemail.net>2010-06-16 10:55:42 +0000
committerdan <dan@noemail.net>2010-06-16 10:55:42 +0000
commitb0ac3e3a17bfd02e19c4e1b4463406768614cd5e (patch)
tree58b7f53a2cbd17156021d7fe780ffeadb734f13a /src/os_unix.c
parenta4a9095ec032c8fd0435e756b3ce6055d9374a6c (diff)
downloadsqlite-b0ac3e3a17bfd02e19c4e1b4463406768614cd5e.tar.gz
sqlite-b0ac3e3a17bfd02e19c4e1b4463406768614cd5e.zip
Fix a memory leak that can occur in os_unix.c if an IO error occurs within the xUnlock method.
FossilOrigin-Name: 6c5c04eea1f0e8d61883ee8675c249fbf895dc01
Diffstat (limited to 'src/os_unix.c')
-rw-r--r--src/os_unix.c70
1 files changed, 36 insertions, 34 deletions
diff --git a/src/os_unix.c b/src/os_unix.c
index 9dbd3d3aa..574f48d18 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -736,17 +736,49 @@ 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;
@@ -1153,36 +1185,6 @@ end_lock:
}
/*
-** 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();