diff options
author | danielk1977 <danielk1977@noemail.net> | 2007-09-01 09:02:53 +0000 |
---|---|---|
committer | danielk1977 <danielk1977@noemail.net> | 2007-09-01 09:02:53 +0000 |
commit | ca0c89715e462ad7190c22c1ba30c85d077263f0 (patch) | |
tree | 0d8a87d18da3f03f45031f0ce55120fb670362b8 /src | |
parent | 95c8a54c7d4488b5bdd6fb73196bf1463e7556e9 (diff) | |
download | sqlite-ca0c89715e462ad7190c22c1ba30c85d077263f0.tar.gz sqlite-ca0c89715e462ad7190c22c1ba30c85d077263f0.zip |
Fix a problem handling a malloc() failure in printf.c. Also some other things to improve test coverage. (CVS 4361)
FossilOrigin-Name: 595bfe72f053bc6ecb58bb9044a4cdc53d30b404
Diffstat (limited to 'src')
-rw-r--r-- | src/mem1.c | 66 | ||||
-rw-r--r-- | src/mem2.c | 161 | ||||
-rw-r--r-- | src/printf.c | 7 | ||||
-rw-r--r-- | src/test1.c | 4 | ||||
-rw-r--r-- | src/test6.c | 72 |
5 files changed, 166 insertions, 144 deletions
diff --git a/src/mem1.c b/src/mem1.c index abaafe1ec..16001a009 100644 --- a/src/mem1.c +++ b/src/mem1.c @@ -12,7 +12,7 @@ ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** -** $Id: mem1.c,v 1.8 2007/08/24 03:51:34 drh Exp $ +** $Id: mem1.c,v 1.9 2007/09/01 09:02:54 danielk1977 Exp $ */ /* @@ -70,16 +70,22 @@ static struct { } mem; - /* -** Return the amount of memory currently checked out. +** Enter the mutex mem.mutex. Allocate it if it is not already allocated. */ -sqlite3_int64 sqlite3_memory_used(void){ - sqlite3_int64 n; +static void enterMem(void){ if( mem.mutex==0 ){ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); } sqlite3_mutex_enter(mem.mutex); +} + +/* +** Return the amount of memory currently checked out. +*/ +sqlite3_int64 sqlite3_memory_used(void){ + sqlite3_int64 n; + enterMutex(); n = mem.nowUsed; sqlite3_mutex_leave(mem.mutex); return n; @@ -92,10 +98,7 @@ sqlite3_int64 sqlite3_memory_used(void){ */ sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ sqlite3_int64 n; - if( mem.mutex==0 ){ - mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); - } - sqlite3_mutex_enter(mem.mutex); + enterMutex(); n = mem.mxUsed; if( resetFlag ){ mem.mxUsed = mem.nowUsed; @@ -112,10 +115,7 @@ int sqlite3_memory_alarm( void *pArg, sqlite3_int64 iThreshold ){ - if( mem.mutex==0 ){ - mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); - } - sqlite3_mutex_enter(mem.mutex); + enterMutex(); mem.alarmCallback = xCallback; mem.alarmArg = pArg; mem.alarmThreshold = iThreshold; @@ -145,31 +145,27 @@ static void sqlite3MemsysAlarm(int nByte){ ** Allocate nBytes of memory */ void *sqlite3_malloc(int nBytes){ - sqlite3_int64 *p; - if( nBytes<=0 ){ - return 0; - } - if( mem.mutex==0 ){ - mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); - } - sqlite3_mutex_enter(mem.mutex); - if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){ - sqlite3MemsysAlarm(nBytes); - } - p = malloc(nBytes+8); - if( p==0 ){ - sqlite3MemsysAlarm(nBytes); + sqlite3_int64 *p = 0; + if( nBytes>0 ){ + enterMutex(); + if( mem.alarmCallback!=0 && mem.nowUsed+nBytes>=mem.alarmThreshold ){ + sqlite3MemsysAlarm(nBytes); + } p = malloc(nBytes+8); - } - if( p ){ - p[0] = nBytes; - p++; - mem.nowUsed += nBytes; - if( mem.nowUsed>mem.mxUsed ){ - mem.mxUsed = mem.nowUsed; + if( p==0 ){ + sqlite3MemsysAlarm(nBytes); + p = malloc(nBytes+8); } + if( p ){ + p[0] = nBytes; + p++; + mem.nowUsed += nBytes; + if( mem.nowUsed>mem.mxUsed ){ + mem.mxUsed = mem.nowUsed; + } + } + sqlite3_mutex_leave(mem.mutex); } - sqlite3_mutex_leave(mem.mutex); return (void*)p; } diff --git a/src/mem2.c b/src/mem2.c index afaf01030..830c5dc43 100644 --- a/src/mem2.c +++ b/src/mem2.c @@ -12,7 +12,7 @@ ** This file contains the C functions that implement a memory ** allocation subsystem for use by SQLite. ** -** $Id: mem2.c,v 1.12 2007/08/30 15:46:07 danielk1977 Exp $ +** $Id: mem2.c,v 1.13 2007/09/01 09:02:54 danielk1977 Exp $ */ /* @@ -153,14 +153,21 @@ static struct { /* -** Return the amount of memory currently checked out. +** Enter the mutex mem.mutex. Allocate it if it is not already allocated. */ -sqlite3_int64 sqlite3_memory_used(void){ - sqlite3_int64 n; +static void enterMem(void){ if( mem.mutex==0 ){ mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); } sqlite3_mutex_enter(mem.mutex); +} + +/* +** Return the amount of memory currently checked out. +*/ +sqlite3_int64 sqlite3_memory_used(void){ + sqlite3_int64 n; + enterMem(); n = mem.nowUsed; sqlite3_mutex_leave(mem.mutex); return n; @@ -173,10 +180,7 @@ sqlite3_int64 sqlite3_memory_used(void){ */ sqlite3_int64 sqlite3_memory_highwater(int resetFlag){ sqlite3_int64 n; - if( mem.mutex==0 ){ - mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); - } - sqlite3_mutex_enter(mem.mutex); + enterMem(); n = mem.mxUsed; if( resetFlag ){ mem.mxUsed = mem.nowUsed; @@ -193,10 +197,7 @@ int sqlite3_memory_alarm( void *pArg, sqlite3_int64 iThreshold ){ - if( mem.mutex==0 ){ - mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); - } - sqlite3_mutex_enter(mem.mutex); + enterMem(); mem.alarmCallback = xCallback; mem.alarmArg = pArg; mem.alarmThreshold = iThreshold; @@ -260,82 +261,77 @@ void *sqlite3_malloc(int nByte){ void **pBt; char *z; int *pInt; - void *p; + void *p = 0; int totalSize; - if( nByte<=0 ){ - mem.iNextIsBenign = 0; - return 0; - } - if( mem.mutex==0 ){ - mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); - } - sqlite3_mutex_enter(mem.mutex); - assert( mem.disallow==0 ); - if( mem.alarmCallback!=0 && mem.nowUsed+nByte>=mem.alarmThreshold ){ - sqlite3MemsysAlarm(nByte); - } - nByte = (nByte+3)&~3; - totalSize = nByte + sizeof(*pHdr) + sizeof(int) + - mem.nBacktrace*sizeof(void*) + mem.nTitle; - if( mem.iFail>0 ){ - if( mem.iFail==1 ){ - p = 0; - mem.iFail = mem.iReset; - if( mem.iFailCnt==0 ){ - sqlite3MemsysFailed(); /* A place to set a breakpoint */ - } - mem.iFailCnt++; - if( mem.iNextIsBenign ){ - mem.iBenignFailCnt++; - } - }else{ - p = malloc(totalSize); - mem.iFail--; - } - }else{ - p = malloc(totalSize); - if( p==0 ){ + if( nByte>0 ){ + enterMem(); + assert( mem.disallow==0 ); + if( mem.alarmCallback!=0 && mem.nowUsed+nByte>=mem.alarmThreshold ){ sqlite3MemsysAlarm(nByte); - p = malloc(totalSize); - } - } - if( p ){ - z = p; - pBt = (void**)&z[mem.nTitle]; - pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace]; - pHdr->pNext = 0; - pHdr->pPrev = mem.pLast; - if( mem.pLast ){ - mem.pLast->pNext = pHdr; - }else{ - mem.pFirst = pHdr; } - mem.pLast = pHdr; - pHdr->iForeGuard = FOREGUARD; - pHdr->nBacktraceSlots = mem.nBacktrace; - pHdr->nTitle = mem.nTitle; - if( mem.nBacktrace ){ - void *aAddr[40]; - pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1; - memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*)); + nByte = (nByte+3)&~3; + totalSize = nByte + sizeof(*pHdr) + sizeof(int) + + mem.nBacktrace*sizeof(void*) + mem.nTitle; + if( mem.iFail>0 ){ + if( mem.iFail==1 ){ + p = 0; + mem.iFail = mem.iReset; + if( mem.iFailCnt==0 ){ + sqlite3MemsysFailed(); /* A place to set a breakpoint */ + } + mem.iFailCnt++; + if( mem.iNextIsBenign ){ + mem.iBenignFailCnt++; + } + }else{ + p = malloc(totalSize); + mem.iFail--; + } }else{ - pHdr->nBacktrace = 0; - } - if( mem.nTitle ){ - memcpy(z, mem.zTitle, mem.nTitle); + p = malloc(totalSize); + if( p==0 ){ + sqlite3MemsysAlarm(nByte); + p = malloc(totalSize); + } } - pHdr->iSize = nByte; - pInt = (int*)&pHdr[1]; - pInt[nByte/sizeof(int)] = REARGUARD; - memset(pInt, 0x65, nByte); - mem.nowUsed += nByte; - if( mem.nowUsed>mem.mxUsed ){ - mem.mxUsed = mem.nowUsed; + if( p ){ + z = p; + pBt = (void**)&z[mem.nTitle]; + pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace]; + pHdr->pNext = 0; + pHdr->pPrev = mem.pLast; + if( mem.pLast ){ + mem.pLast->pNext = pHdr; + }else{ + mem.pFirst = pHdr; + } + mem.pLast = pHdr; + pHdr->iForeGuard = FOREGUARD; + pHdr->nBacktraceSlots = mem.nBacktrace; + pHdr->nTitle = mem.nTitle; + if( mem.nBacktrace ){ + void *aAddr[40]; + pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1; + memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*)); + }else{ + pHdr->nBacktrace = 0; + } + if( mem.nTitle ){ + memcpy(z, mem.zTitle, mem.nTitle); + } + pHdr->iSize = nByte; + pInt = (int*)&pHdr[1]; + pInt[nByte/sizeof(int)] = REARGUARD; + memset(pInt, 0x65, nByte); + mem.nowUsed += nByte; + if( mem.nowUsed>mem.mxUsed ){ + mem.mxUsed = mem.nowUsed; + } + p = (void*)pInt; } - p = (void*)pInt; + sqlite3_mutex_leave(mem.mutex); } - sqlite3_mutex_leave(mem.mutex); mem.iNextIsBenign = 0; return p; } @@ -427,10 +423,7 @@ void sqlite3_memdebug_backtrace(int depth){ */ void sqlite3_memdebug_settitle(const char *zTitle){ int n = strlen(zTitle) + 1; - if( mem.mutex==0 ){ - mem.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); - } - sqlite3_mutex_enter(mem.mutex); + enterMem(); if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1; memcpy(mem.zTitle, zTitle, n); mem.zTitle[n] = 0; diff --git a/src/printf.c b/src/printf.c index 109e3ad47..bea91e211 100644 --- a/src/printf.c +++ b/src/printf.c @@ -741,7 +741,7 @@ static void mout(void *arg, const char *zNewText, int nNewChar){ pM->zText = pM->xRealloc(0, nAlloc); if( pM->zText==0 ){ pM->nAlloc = 0; - pM->iMallocFailed = 0; + pM->iMallocFailed = 1; return; }else if( pM->nChar ){ memcpy(pM->zText, pM->zBase, pM->nChar); @@ -752,7 +752,7 @@ static void mout(void *arg, const char *zNewText, int nNewChar){ if( zNew ){ pM->zText = zNew; }else{ - pM->iMallocFailed = 0; + pM->iMallocFailed = 1; pM->xRealloc(pM->zText, 0); pM->zText = 0; pM->nAlloc = 0; @@ -789,7 +789,8 @@ static char *base_vprintf( sM.xRealloc = xRealloc; sM.iMallocFailed = 0; vxprintf(mout, &sM, useInternal, zFormat, ap); - if( xRealloc ){ + assert(sM.iMallocFailed==0 || sM.zText==0); + if( xRealloc && !sM.iMallocFailed ){ if( sM.zText==sM.zBase ){ sM.zText = xRealloc(0, sM.nChar+1); if( sM.zText ){ diff --git a/src/test1.c b/src/test1.c index 2802a991b..d98dbed23 100644 --- a/src/test1.c +++ b/src/test1.c @@ -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.272 2007/08/31 17:42:48 danielk1977 Exp $ +** $Id: test1.c,v 1.273 2007/09/01 09:02:54 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -437,7 +437,7 @@ static int test_mprintf_z( char *zResult = 0; int i; - for(i=2; i<argc; i++){ + for(i=2; i<argc && (i==2 || zResult); i++){ zResult = sqlite3MPrintf(0, "%z%s%s", zResult, argv[1], argv[i]); } Tcl_AppendResult(interp, zResult, 0); diff --git a/src/test6.c b/src/test6.c index 8045509bd..b35130370 100644 --- a/src/test6.c +++ b/src/test6.c @@ -698,33 +698,18 @@ static int processDevSymArgs( } /* -** tclcmd: sqlite_crashparams ?OPTIONS? DELAY CRASHFILE -** -** This procedure implements a TCL command that enables crash testing -** in testfixture. Once enabled, crash testing cannot be disabled. -** -** Available options are "-characteristics" and "-sectorsize". Both require -** an argument. For -sectorsize, this is the simulated sector size in -** bytes. For -characteristics, the argument must be a list of io-capability -** flags to simulate. Valid flags are "atomic", "atomic512", "atomic1K", -** "atomic2K", "atomic4K", "atomic8K", "atomic16K", "atomic32K", -** "atomic64K", "sequential" and "safe_append". -** -** Example: -** -** sqlite_crashparams -sect 1024 -char {atomic sequential} ./test.db 1 +** tclcmd: sqlite_crash_enable ENABLE ** +** Parameter ENABLE must be a boolean value. If true, then the "crash" +** vfs is added to the system. If false, it is removed. */ -static int crashParamsObjCmd( +static int crashEnableCmd( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ - int iDelay; - const char *zCrashFile; - int nCrashFile, iDc, iSectorSize; - + int isEnable; static sqlite3_vfs crashVfs = { 1, /* iVersion */ 0, /* szOsFile */ @@ -747,6 +732,18 @@ static int crashParamsObjCmd( cfCurrentTime /* xCurrentTime */ }; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "ENABLE"); + return TCL_ERROR; + } + + if( Tcl_GetBooleanFromObj(interp, objv[1], &isEnable) ){ + return TCL_ERROR; + } + + if( (isEnable && crashVfs.pAppData) || (!isEnable && !crashVfs.pAppData) ){ + return TCL_OK; + } if( crashVfs.pAppData==0 ){ sqlite3_vfs *pOriginalVfs = sqlite3_vfs_find(0); @@ -754,8 +751,42 @@ static int crashParamsObjCmd( crashVfs.pAppData = (void *)pOriginalVfs; crashVfs.szOsFile = sizeof(CrashFile) + pOriginalVfs->szOsFile; sqlite3_vfs_register(&crashVfs, 0); + }else{ + crashVfs.pAppData = 0; + sqlite3_vfs_unregister(&crashVfs); } + return TCL_OK; +} + +/* +** tclcmd: sqlite_crashparams ?OPTIONS? DELAY CRASHFILE +** +** This procedure implements a TCL command that enables crash testing +** in testfixture. Once enabled, crash testing cannot be disabled. +** +** Available options are "-characteristics" and "-sectorsize". Both require +** an argument. For -sectorsize, this is the simulated sector size in +** bytes. For -characteristics, the argument must be a list of io-capability +** flags to simulate. Valid flags are "atomic", "atomic512", "atomic1K", +** "atomic2K", "atomic4K", "atomic8K", "atomic16K", "atomic32K", +** "atomic64K", "sequential" and "safe_append". +** +** Example: +** +** sqlite_crashparams -sect 1024 -char {atomic sequential} ./test.db 1 +** +*/ +static int crashParamsObjCmd( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + int iDelay; + const char *zCrashFile; + int nCrashFile, iDc, iSectorSize; + iDc = -1; iSectorSize = -1; @@ -826,6 +857,7 @@ static int devSymObjCmd( */ int Sqlitetest6_Init(Tcl_Interp *interp){ #ifndef SQLITE_OMIT_DISKIO + Tcl_CreateObjCommand(interp, "sqlite3_crash_enable", crashEnableCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0); Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0); #endif |