Include the ThreadData structure in internal malloc() testing. Also fixes for revealed bugs. (CVS 2974)
FossilOrigin-Name: c7b9d50d0a975912776aaa2b870308652f77e1e6
This commit is contained in:
+12
-2
@@ -1782,7 +1782,12 @@ ThreadData *sqlite3UnixThreadSpecificData(int allocateFlag){
|
||||
pTsd = pthread_getspecific(key);
|
||||
if( allocateFlag>0 ){
|
||||
if( pTsd==0 ){
|
||||
pTsd = sqlite3OsMalloc(sizeof(zeroData));
|
||||
if( !sqlite3TestMallocFail() ){
|
||||
pTsd = sqlite3OsMalloc(sizeof(zeroData));
|
||||
}
|
||||
#ifdef SQLITE_MEMDEBUG
|
||||
sqlite3_isFail = 0;
|
||||
#endif
|
||||
if( pTsd ){
|
||||
*pTsd = zeroData;
|
||||
pthread_setspecific(key, pTsd);
|
||||
@@ -1801,7 +1806,12 @@ ThreadData *sqlite3UnixThreadSpecificData(int allocateFlag){
|
||||
static ThreadData *pTsd = 0;
|
||||
if( allocateFlag>0 ){
|
||||
if( pTsd==0 ){
|
||||
pTsd = sqlite3OsMalloc( sizeof(zeroData) );
|
||||
if( !sqlite3TestMallocFail() ){
|
||||
pTsd = sqlite3OsMalloc( sizeof(zeroData) );
|
||||
}
|
||||
#ifdef SQLITE_MEMDEBUG
|
||||
sqlite3_isFail = 0;
|
||||
#endif
|
||||
if( pTsd ){
|
||||
*pTsd = zeroData;
|
||||
TSD_COUNTER(+1);
|
||||
|
||||
+2
-1
@@ -18,7 +18,7 @@
|
||||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.244 2006/01/18 17:25:46 drh Exp $
|
||||
** @(#) $Id: pager.c,v 1.245 2006/01/18 18:22:43 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "sqliteInt.h"
|
||||
@@ -1999,6 +1999,7 @@ int sqlite3pager_close(Pager *pPager){
|
||||
** so that ThreadData.nAlloc can be set.
|
||||
*/
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
assert( pPager );
|
||||
assert( pTsd && pTsd->nAlloc );
|
||||
#endif
|
||||
|
||||
|
||||
+8
-2
@@ -13,7 +13,7 @@
|
||||
** interface, and routines that contribute to loading the database schema
|
||||
** from disk.
|
||||
**
|
||||
** $Id: prepare.c,v 1.26 2006/01/18 16:51:35 danielk1977 Exp $
|
||||
** $Id: prepare.c,v 1.27 2006/01/18 18:22:43 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -520,6 +520,9 @@ int sqlite3_prepare(
|
||||
memset(&sParse, 0, sizeof(sParse));
|
||||
sParse.db = db;
|
||||
sParse.pTsd = sqlite3ThreadData();
|
||||
if( !sParse.pTsd ){
|
||||
goto prepare_out;
|
||||
}
|
||||
sParse.pTsd->nRef++;
|
||||
sqlite3RunParser(&sParse, zSql, &zErrMsg);
|
||||
|
||||
@@ -554,6 +557,7 @@ int sqlite3_prepare(
|
||||
}
|
||||
#endif
|
||||
|
||||
prepare_out:
|
||||
if( sqlite3SafetyOff(db) ){
|
||||
rc = SQLITE_MISUSE;
|
||||
}
|
||||
@@ -570,7 +574,9 @@ int sqlite3_prepare(
|
||||
sqlite3Error(db, rc, 0);
|
||||
}
|
||||
|
||||
sParse.pTsd->nRef--;
|
||||
if( sParse.pTsd ){
|
||||
sParse.pTsd->nRef--;
|
||||
}
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
sqlite3ReleaseThreadData();
|
||||
return rc;
|
||||
|
||||
+3
-1
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.474 2006/01/18 16:51:35 danielk1977 Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.475 2006/01/18 18:22:43 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@@ -1759,7 +1759,9 @@ void sqlite3FailedMalloc();
|
||||
#ifdef SQLITE_MEMDEBUG
|
||||
void sqlite3MallocDisallow();
|
||||
void sqlite3MallocAllow();
|
||||
int sqlite3TestMallocFail();
|
||||
#else
|
||||
#define sqlite3TestMallocFail() 0
|
||||
#define sqlite3MallocDisallow()
|
||||
#define sqlite3MallocAllow()
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test1.c,v 1.196 2006/01/18 16:51:35 danielk1977 Exp $
|
||||
** $Id: test1.c,v 1.197 2006/01/18 18:22:43 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
@@ -911,7 +911,7 @@ static int sqlite_malloc_outstanding(
|
||||
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
if( objc==2 ){
|
||||
ThreadData *pTd = sqlite3ThreadData();
|
||||
ThreadData const *pTd = sqlite3ThreadDataReadOnly();
|
||||
const char *zArg = Tcl_GetString(objv[1]);
|
||||
if( 0==strcmp(zArg, "-bytes") ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(pTd->nAlloc));
|
||||
|
||||
+41
-33
@@ -14,7 +14,7 @@
|
||||
** This file contains functions for allocating memory, comparing
|
||||
** strings, and stuff like that.
|
||||
**
|
||||
** $Id: util.c,v 1.177 2006/01/18 17:25:46 drh Exp $
|
||||
** $Id: util.c,v 1.178 2006/01/18 18:22:43 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -72,7 +72,10 @@
|
||||
** value indicates no limit.
|
||||
*/
|
||||
void sqlite3_soft_heap_limit(int n){
|
||||
sqlite3ThreadData()->nSoftHeapLimit = n;
|
||||
ThreadData *pTd = sqlite3ThreadData();
|
||||
if( pTd ){
|
||||
pTd->nSoftHeapLimit = n;
|
||||
}
|
||||
sqlite3ReleaseThreadData();
|
||||
}
|
||||
|
||||
@@ -207,8 +210,7 @@ int sqlite3_iLine = 0; /* Line number for debug info */
|
||||
** Check for a simulated memory allocation failure. Return true if
|
||||
** the failure should be simulated. Return false to proceed as normal.
|
||||
*/
|
||||
static int failMalloc(){
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
int sqlite3TestMallocFail(){
|
||||
if( sqlite3_isFail ){
|
||||
return 1;
|
||||
}
|
||||
@@ -316,7 +318,6 @@ static void *getOsPointer(void *p)
|
||||
** of allocations.
|
||||
*/
|
||||
static void linkAlloc(void *p){
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
void **pp = (void **)p;
|
||||
pp[0] = 0;
|
||||
pp[1] = sqlite3_pFirst;
|
||||
@@ -332,7 +333,6 @@ static void linkAlloc(void *p){
|
||||
*/
|
||||
static void unlinkAlloc(void *p)
|
||||
{
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
void **pp = (void **)p;
|
||||
if( p==sqlite3_pFirst ){
|
||||
assert(!pp[0]);
|
||||
@@ -365,7 +365,6 @@ static void relinkAlloc(void *p)
|
||||
if( pp[0] ){
|
||||
((void **)(pp[0]))[1] = p;
|
||||
}else{
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
sqlite3_pFirst = p;
|
||||
}
|
||||
if( pp[1] ){
|
||||
@@ -397,7 +396,6 @@ static void relinkAlloc(void *p)
|
||||
#include <tcl.h>
|
||||
int sqlite3OutstandingMallocs(Tcl_Interp *interp){
|
||||
void *p;
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
Tcl_Obj *pRes = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pRes);
|
||||
|
||||
@@ -445,11 +443,11 @@ int sqlite3OutstandingMallocs(Tcl_Interp *interp){
|
||||
*/
|
||||
static void * OSMALLOC(int n){
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
ThreadData const *pTsd = sqlite3ThreadDataReadOnly();
|
||||
sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, pTsd->nAlloc);
|
||||
#endif
|
||||
assert( !sqlite3_mallocDisallowed );
|
||||
if( !failMalloc() ){
|
||||
if( !sqlite3TestMallocFail() ){
|
||||
u32 *p;
|
||||
p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD);
|
||||
assert(p);
|
||||
@@ -488,10 +486,13 @@ static void OSFREE(void *pFree){
|
||||
static void * OSREALLOC(void *pRealloc, int n){
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
if( !pTsd ){
|
||||
return 0;
|
||||
}
|
||||
sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, pTsd->nAlloc);
|
||||
#endif
|
||||
assert( !sqlite3_mallocDisallowed );
|
||||
if( !failMalloc() ){
|
||||
if( !sqlite3TestMallocFail() ){
|
||||
u32 *p = (u32 *)getOsPointer(pRealloc);
|
||||
checkGuards(p);
|
||||
p = sqlite3OsRealloc(p, n + TESTALLOC_OVERHEAD);
|
||||
@@ -535,18 +536,21 @@ static void OSMALLOC_FAILED(){
|
||||
** a no-op
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
static void handleSoftLimit(int n){
|
||||
static int handleSoftLimit(int n){
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
pTsd->nAlloc += n;
|
||||
assert( pTsd->nAlloc>=0 );
|
||||
if( n>0 && pTsd->nSoftHeapLimit>0 ){
|
||||
while( pTsd->nAlloc>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) );
|
||||
}else if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){
|
||||
sqlite3ReleaseThreadData();
|
||||
if( pTsd ){
|
||||
pTsd->nAlloc += n;
|
||||
assert( pTsd->nAlloc>=0 );
|
||||
if( n>0 && pTsd->nSoftHeapLimit>0 ){
|
||||
while( pTsd->nAlloc>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) );
|
||||
}else if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){
|
||||
sqlite3ReleaseThreadData();
|
||||
}
|
||||
}
|
||||
return (pTsd ? 0 : 1);
|
||||
}
|
||||
#else
|
||||
#define handleSoftLimit(x)
|
||||
#define handleSoftLimit(x) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -556,8 +560,7 @@ static void handleSoftLimit(int n){
|
||||
*/
|
||||
void *sqlite3MallocRaw(int n){
|
||||
void *p = 0;
|
||||
if( n>0 && !sqlite3MallocFailed() ){
|
||||
handleSoftLimit(n);
|
||||
if( n>0 && !sqlite3MallocFailed() && !handleSoftLimit(n) ){
|
||||
while( !(p = OSMALLOC(n)) && sqlite3_release_memory(n) );
|
||||
if( !p ){
|
||||
/* If the allocation failed, call handleSoftLimit() again, this time
|
||||
@@ -587,17 +590,18 @@ void *sqlite3Realloc(void *p, int n){
|
||||
return sqlite3Malloc(n);
|
||||
}else{
|
||||
void *np = 0;
|
||||
handleSoftLimit(n - OSSIZEOF(p));
|
||||
while( !(np = OSREALLOC(p, n)) && sqlite3_release_memory(n) );
|
||||
if( !np ){
|
||||
/* If the allocation failed, call handleSoftLimit() again, this time
|
||||
** with the additive inverse of the argument passed to
|
||||
** handleSoftLimit() above. This is so the ThreadData.nAlloc variable is
|
||||
** still correct after a malloc() failure.
|
||||
*/
|
||||
handleSoftLimit(OSSIZEOF(p) - n);
|
||||
sqlite3FailedMalloc();
|
||||
OSMALLOC_FAILED();
|
||||
if( !handleSoftLimit(n - OSSIZEOF(p)) ){
|
||||
while( !(np = OSREALLOC(p, n)) && sqlite3_release_memory(n) );
|
||||
if( !np ){
|
||||
/* If the allocation failed, call handleSoftLimit() again, this time
|
||||
** with the additive inverse of the argument passed to
|
||||
** handleSoftLimit() above. This is so the ThreadData.nAlloc variable is
|
||||
** still correct after a malloc() failure.
|
||||
*/
|
||||
handleSoftLimit(OSSIZEOF(p) - n);
|
||||
sqlite3FailedMalloc();
|
||||
OSMALLOC_FAILED();
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
@@ -1322,7 +1326,11 @@ void *sqlite3TextToPtr(const char *z){
|
||||
** Return a pointer to the ThreadData associated with the calling thread.
|
||||
*/
|
||||
ThreadData *sqlite3ThreadData(){
|
||||
return (ThreadData*)sqlite3OsThreadSpecificData(1);
|
||||
ThreadData *p = (ThreadData*)sqlite3OsThreadSpecificData(1);
|
||||
if( !p ){
|
||||
sqlite3FailedMalloc();
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+7
-2
@@ -43,7 +43,7 @@
|
||||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.532 2006/01/18 16:51:36 danielk1977 Exp $
|
||||
** $Id: vdbe.c,v 1.533 2006/01/18 18:22:43 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -408,6 +408,9 @@ int sqlite3VdbeExec(
|
||||
Mem *pStackLimit;
|
||||
#endif
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
if( !pTsd ){
|
||||
goto no_mem;
|
||||
}
|
||||
|
||||
if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
|
||||
pTsd->nRef++;
|
||||
@@ -4615,7 +4618,9 @@ vdbe_halt:
|
||||
}
|
||||
sqlite3VdbeHalt(p);
|
||||
p->pTos = pTos;
|
||||
pTsd->nRef--;
|
||||
if( pTsd ){
|
||||
pTsd->nRef--;
|
||||
}
|
||||
return rc;
|
||||
|
||||
/* Jump to here if a malloc() fails. It's hard to get a malloc()
|
||||
|
||||
+2
-1
@@ -242,7 +242,8 @@ int sqlite3_step(sqlite3_stmt *pStmt){
|
||||
#endif
|
||||
|
||||
sqlite3Error(p->db, rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
|
||||
return sqlite3ApiExit(p->db, rc);
|
||||
p->rc = sqlite3ApiExit(p->db, p->rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user