diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/btree.c | 17 | ||||
-rw-r--r-- | src/complete.c | 7 | ||||
-rw-r--r-- | src/legacy.c | 8 | ||||
-rw-r--r-- | src/main.c | 54 | ||||
-rw-r--r-- | src/os_unix.c | 17 | ||||
-rw-r--r-- | src/pager.c | 16 | ||||
-rw-r--r-- | src/prepare.c | 25 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 | ||||
-rw-r--r-- | src/util.c | 23 | ||||
-rw-r--r-- | src/vdbeapi.c | 15 |
10 files changed, 96 insertions, 90 deletions
diff --git a/src/btree.c b/src/btree.c index 8674e9c6e..7a46d26ec 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.299 2006/01/16 15:14:27 danielk1977 Exp $ +** $Id: btree.c,v 1.300 2006/01/18 15:25:17 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -1662,7 +1662,11 @@ int sqlite3BtreeOpen( sqlite3pager_set_pagesize(pBt->pPager, pBt->pageSize); #ifndef SQLITE_OMIT_SHARED_CACHE - /* Add the new btree to the linked list starting at ThreadData.pBtree */ + /* Add the new btree to the linked list starting at ThreadData.pBtree. + ** There is no chance that a malloc() may fail inside of the + ** sqlite3ThreadData() call, as the ThreadData structure must have already + ** been allocated for pTsdro->useSharedData to be non-zero. + */ if( pTsdro->useSharedData && zFilename && !isMemdb ){ pBt->pNext = pTsdro->pBtree; sqlite3ThreadData()->pBtree = pBt; @@ -1712,14 +1716,19 @@ int sqlite3BtreeClose(Btree *p){ return SQLITE_OK; } - /* Remove the shared-btree from the thread wide list */ - pTsd = sqlite3ThreadData(); + /* Remove the shared-btree from the thread wide list. Call + ** ThreadDataReadOnly() and then cast away the const property of the + ** pointer to avoid allocating thread data if it is not really required. + */ + pTsd = (ThreadData *)sqlite3ThreadDataReadOnly(); if( pTsd->pBtree==pBt ){ + assert( pTsd==sqlite3ThreadData() ); pTsd->pBtree = pBt->pNext; }else{ BtShared *pPrev; for(pPrev=pTsd->pBtree; pPrev && pPrev->pNext!=pBt; pPrev=pPrev->pNext); if( pPrev ){ + assert( pTsd==sqlite3ThreadData() ); pPrev->pNext = pBt->pNext; } } diff --git a/src/complete.c b/src/complete.c index 61a87e57c..536ffadbc 100644 --- a/src/complete.c +++ b/src/complete.c @@ -16,7 +16,7 @@ ** separating it out, the code will be automatically omitted from ** static links that do not use it. ** -** $Id: complete.c,v 1.2 2005/12/12 06:53:04 danielk1977 Exp $ +** $Id: complete.c,v 1.3 2006/01/18 15:25:17 danielk1977 Exp $ */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_COMPLETE @@ -255,12 +255,9 @@ int sqlite3_complete16(const void *zSql){ zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8); if( zSql8 ){ rc = sqlite3_complete(zSql8); - }else if( zSql ){ - rc = SQLITE_NOMEM; - sqlite3MallocClearFailed(); } sqlite3ValueFree(pVal); - return rc; + return sqlite3ApiExit(0, rc); } #endif /* SQLITE_OMIT_UTF16 */ #endif /* SQLITE_OMIT_COMPLETE */ diff --git a/src/legacy.c b/src/legacy.c index b149f5b29..98f37a922 100644 --- a/src/legacy.c +++ b/src/legacy.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: legacy.c,v 1.11 2006/01/11 21:41:22 drh Exp $ +** $Id: legacy.c,v 1.12 2006/01/18 15:25:17 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -121,11 +121,7 @@ exec_out: if( pStmt ) sqlite3_finalize(pStmt); if( azCols ) sqliteFree(azCols); - if( sqlite3ThreadDataReadOnly()->mallocFailed ){ - rc = SQLITE_NOMEM; - sqlite3MallocClearFailed(); - } - + rc = sqlite3ApiExit(0, rc); if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){ *pzErrMsg = malloc(1+strlen(sqlite3_errmsg(db))); if( *pzErrMsg ){ diff --git a/src/main.c b/src/main.c index 77fe0710a..c2822a7e5 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.326 2006/01/18 05:51:58 danielk1977 Exp $ +** $Id: main.c,v 1.327 2006/01/18 15:25:17 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -485,12 +485,7 @@ int sqlite3_create_function( assert( !sqlite3ThreadDataReadOnly()->mallocFailed ); rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal); - if( sqlite3ThreadDataReadOnly()->mallocFailed ){ - sqlite3MallocClearFailed(); - rc = SQLITE_NOMEM; - sqlite3Error(db, SQLITE_NOMEM, 0); - } - return rc; + return sqlite3ApiExit(db, rc); } #ifndef SQLITE_OMIT_UTF16 @@ -512,12 +507,7 @@ int sqlite3_create_function16( rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal); sqliteFree(zFunc8); - if( sqlite3ThreadDataReadOnly()->mallocFailed ){ - sqlite3MallocClearFailed(); - rc = SQLITE_NOMEM; - sqlite3Error(db, SQLITE_NOMEM, 0); - } - return rc; + return sqlite3ApiExit(db, rc); } #endif @@ -727,7 +717,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){ SQLITE_UTF8, SQLITE_STATIC); z = sqlite3_value_text16(db->pErr); } - sqlite3MallocClearFailed(); + sqlite3ApiExit(0, 0); return z; } #endif /* SQLITE_OMIT_UTF16 */ @@ -835,10 +825,7 @@ static int openDatabase( createCollation(db, "BINARY", SQLITE_UTF16, 0,binCollFunc) || (db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0 ){ - /* sqlite3_create_collation() is an external API. So the mallocFailed flag - ** will have been cleared before returning. So set it explicitly here. - */ - sqlite3ThreadData()->mallocFailed = 1; + assert( sqlite3ThreadDataReadOnly()->mallocFailed ); db->magic = SQLITE_MAGIC_CLOSED; goto opendb_out; } @@ -895,8 +882,7 @@ opendb_out: db = 0; } *ppDb = db; - sqlite3MallocClearFailed(); - return rc; + return sqlite3ApiExit(0, rc); } /* @@ -918,7 +904,7 @@ int sqlite3_open16( sqlite3 **ppDb ){ char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */ - int rc = SQLITE_NOMEM; + int rc = SQLITE_OK; sqlite3_value *pVal; assert( zFilename ); @@ -936,13 +922,10 @@ int sqlite3_open16( *ppDb = 0; } } - }else{ - assert( sqlite3ThreadDataReadOnly()->mallocFailed ); - sqlite3MallocClearFailed(); } sqlite3ValueFree(pVal); - return rc; + return sqlite3ApiExit(0, rc); } #endif /* SQLITE_OMIT_UTF16 */ @@ -997,12 +980,7 @@ int sqlite3_create_collation( int rc; assert( !sqlite3ThreadDataReadOnly()->mallocFailed ); rc = createCollation(db, zName, enc, pCtx, xCompare); - if( sqlite3ThreadDataReadOnly()->mallocFailed ){ - sqlite3MallocClearFailed(); - rc = SQLITE_NOMEM; - sqlite3Error(db, rc, 0); - } - return rc; + return sqlite3ApiExit(db, rc); } #ifndef SQLITE_OMIT_UTF16 @@ -1024,12 +1002,7 @@ int sqlite3_create_collation16( rc = createCollation(db, zName8, enc, pCtx, xCompare); sqliteFree(zName8); } - if( sqlite3ThreadDataReadOnly()->mallocFailed ){ - sqlite3MallocClearFailed(); - rc = SQLITE_NOMEM; - sqlite3Error(db, rc, 0); - } - return rc; + return sqlite3ApiExit(db, rc); } #endif /* SQLITE_OMIT_UTF16 */ @@ -1115,6 +1088,9 @@ int sqlite3Corrupt(void){ */ int sqlite3_enable_shared_cache(int enable){ ThreadData *pTd = sqlite3ThreadData(); + if( !pTd ){ + return SQLITE_NOMEM; + } /* It is only legal to call sqlite3_enable_shared_cache() when there ** are no currently open b-trees that were opened by the calling thread. @@ -1138,6 +1114,8 @@ int sqlite3_enable_shared_cache(int enable){ */ void sqlite3_thread_cleanup(void){ ThreadData *pTd = sqlite3ThreadData(); - memset(pTd, 0, sizeof(*pTd)); + if( pTd ){ + memset(pTd, 0, sizeof(*pTd)); + } sqlite3ReleaseThreadData(); } diff --git a/src/os_unix.c b/src/os_unix.c index 35d29ad3c..5257bfd5e 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -1739,6 +1739,19 @@ int sqlite3_tsd_count = 0; # define TSD_COUNTER(N) /* no-op */ #endif +#if 0 && defined(SQLITE_MEMDEBUG) +static void *mallocThreadData(size_t nBytes){ + if( sqlite3_iMallocFail>=0 ){ + sqlite3_iMallocFail--; + if( sqlite3_iMallocFail==0 ){ + return 0; + } + } + return sqlite3OsMalloc(nBytes); +} +#else + #define mallocThreadData(x) sqlite3OsMalloc(x) +#endif /* ** If called with allocateFlag>0, then return a pointer to thread @@ -1778,7 +1791,7 @@ ThreadData *sqlite3UnixThreadSpecificData(int allocateFlag){ pTsd = pthread_getspecific(key); if( allocateFlag>0 ){ if( pTsd==0 ){ - pTsd = sqlite3OsMalloc(sizeof(zeroData)); + pTsd = mallocThreadData(sizeof(zeroData)); if( pTsd ){ *pTsd = zeroData; pthread_setspecific(key, pTsd); @@ -1797,7 +1810,7 @@ ThreadData *sqlite3UnixThreadSpecificData(int allocateFlag){ static ThreadData *pTsd = 0; if( allocateFlag>0 ){ if( pTsd==0 ){ - pTsd = sqlite3OsMalloc( sizeof(zeroData) ); + pTsd = mallocThreadData( sizeof(zeroData) ); if( pTsd ){ *pTsd = zeroData; TSD_COUNTER(+1); diff --git a/src/pager.c b/src/pager.c index 597e6e004..0425a4419 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.241 2006/01/16 15:32:23 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.242 2006/01/18 15:25:17 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -1577,7 +1577,15 @@ int sqlite3pager_open( int noReadlock = (flags & PAGER_NO_READLOCK)!=0; char zTemp[SQLITE_TEMPNAME_SIZE]; #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to + ** malloc() must have already been made by this thread before it gets + ** to this point. This means the ThreadData must have been allocated already + ** so that ThreadData.nAlloc can be set. It would be nice to assert + ** that ThreadData.nAlloc is non-zero, but alas this breaks test cases + ** written to invoke the pager directly. + */ ThreadData *pTsd = sqlite3ThreadData(); + assert( pTsd ); #endif /* If malloc() has already failed return SQLITE_NOMEM. Before even @@ -1985,7 +1993,13 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ int sqlite3pager_close(Pager *pPager){ PgHdr *pPg, *pNext; #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to + ** malloc() must have already been made by this thread before it gets + ** to this point. This means the ThreadData must have been allocated already + ** so that ThreadData.nAlloc can be set. + */ ThreadData *pTsd = sqlite3ThreadData(); + assert( pTsd && pTsd->nAlloc ); #endif switch( pPager->state ){ diff --git a/src/prepare.c b/src/prepare.c index 26dc155b1..cd82f1a31 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.24 2006/01/17 13:21:40 danielk1977 Exp $ +** $Id: prepare.c,v 1.25 2006/01/18 15:25:18 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -570,16 +570,8 @@ int sqlite3_prepare( sqlite3Error(db, rc, 0); } - /* We must check for malloc failure last of all, in case malloc() failed - ** inside of the sqlite3Error() call above or something. - */ - if( sParse.pTsd->mallocFailed ){ - rc = SQLITE_NOMEM; - sqlite3Error(db, rc, 0); - } - sParse.pTsd->nRef--; - sqlite3MallocClearFailed(); + rc = sqlite3ApiExit(db, rc); sqlite3ReleaseThreadData(); return rc; } @@ -599,20 +591,17 @@ int sqlite3_prepare16( ** encoded string to UTF-8, then invoking sqlite3_prepare(). The ** tricky bit is figuring out the pointer to return in *pzTail. */ - char *zSql8 = 0; + char *zSql8; const char *zTail8 = 0; - int rc; + int rc = SQLITE_OK; if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } zSql8 = sqlite3utf16to8(zSql, nBytes); - if( !zSql8 ){ - sqlite3MallocClearFailed(); - sqlite3Error(db, SQLITE_NOMEM, 0); - return SQLITE_NOMEM; + if( zSql8 ){ + rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8); } - rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8); if( zTail8 && pzTail ){ /* If sqlite3_prepare returns a tail pointer, we calculate the @@ -624,6 +613,6 @@ int sqlite3_prepare16( *pzTail = (u8 *)zSql + sqlite3utf16ByteLen(zSql, chars_parsed); } sqliteFree(zSql8); - return rc; + return sqlite3ApiExit(db, rc); } #endif /* SQLITE_OMIT_UTF16 */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2c8ea0844..4bb2c14e5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.472 2006/01/17 16:10:14 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.473 2006/01/18 15:25:18 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1765,6 +1765,7 @@ KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *); int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*)); +int sqlite3ApiExit(sqlite3 *db, int); #ifndef SQLITE_OMIT_SHARED_CACHE void sqlite3TableLock(Parse *, int, int, u8, const char *); @@ -1772,7 +1773,6 @@ int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *, #define sqlite3TableLock(v,w,x,y,z) #endif -void sqlite3MallocClearFailed(); #ifdef SQLITE_MEMDEBUG void sqlite3MallocDisallow(); void sqlite3MallocAllow(); diff --git a/src/util.c b/src/util.c index ab7e1420c..36cf5dc8d 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.173 2006/01/17 15:36:32 danielk1977 Exp $ +** $Id: util.c,v 1.174 2006/01/18 15:25:18 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -1336,15 +1336,28 @@ void sqlite3ReleaseThreadData(){ } /* -** Clear the "mallocFailed" flag. This should be invoked before exiting any -** entry points that may have called sqliteMalloc(). +** This function must be called before exiting any API function (i.e. +** returning control to the user) that has called sqlite3Malloc or +** sqlite3Realloc. +** +** The returned value is normally a copy of the second argument to this +** function. However, if a malloc() failure has occured since the previous +** invocation SQLITE_NOMEM is returned instead. +** +** If the first argument, db, is not NULL and a malloc() error has occured, +** then the connection error-code (the value returned by sqlite3_errcode()) +** is set to SQLITE_NOMEM. */ -void sqlite3MallocClearFailed(){ +int sqlite3ApiExit(sqlite3* db, int rc){ ThreadData *pTd = sqlite3OsThreadSpecificData(0); if( pTd && pTd->mallocFailed ){ pTd->mallocFailed = 0; - sqlite3OsThreadSpecificData(0); + if( db ){ + sqlite3Error(db, SQLITE_NOMEM, 0); + } + return SQLITE_NOMEM; } + return rc; } #ifdef SQLITE_MEMDEBUG diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 5d5ec27f2..c1ae4806a 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -242,8 +242,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){ #endif sqlite3Error(p->db, rc, p->zErrMsg ? "%s" : 0, p->zErrMsg); - sqlite3MallocClearFailed(); - return rc; + return sqlite3ApiExit(p->db, rc); } /* @@ -405,10 +404,8 @@ static void columnMallocFailure(sqlite3_stmt *pStmt) ** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR ** and _finalize() will return NOMEM. */ - if( sqlite3ThreadDataReadOnly()->mallocFailed ){ - ((Vdbe *)pStmt)->rc = SQLITE_NOMEM; - sqlite3MallocClearFailed(); - } + Vdbe *p = (Vdbe *)pStmt; + p->rc = sqlite3ApiExit(0, p->rc); } /**************************** sqlite3_column_ ******************************* @@ -503,7 +500,7 @@ static const void *columnName( /* A malloc may have failed inside of the xFunc() call. If this is the case, ** clear the mallocFailed flag and return NULL. */ - sqlite3MallocClearFailed(); + sqlite3ApiExit(0, 0); return ret; } @@ -634,9 +631,9 @@ static int bindText( if( rc==SQLITE_OK && encoding!=0 ){ rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db)); } - sqlite3MallocClearFailed(); + sqlite3Error(((Vdbe *)pStmt)->db, rc, 0); - return rc; + return sqlite3ApiExit(((Vdbe *)pStmt)->db, rc); } |