aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/btree.c17
-rw-r--r--src/complete.c7
-rw-r--r--src/legacy.c8
-rw-r--r--src/main.c54
-rw-r--r--src/os_unix.c17
-rw-r--r--src/pager.c16
-rw-r--r--src/prepare.c25
-rw-r--r--src/sqliteInt.h4
-rw-r--r--src/util.c23
-rw-r--r--src/vdbeapi.c15
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);
}