aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordanielk1977 <danielk1977@noemail.net>2007-09-01 09:02:53 +0000
committerdanielk1977 <danielk1977@noemail.net>2007-09-01 09:02:53 +0000
commitca0c89715e462ad7190c22c1ba30c85d077263f0 (patch)
tree0d8a87d18da3f03f45031f0ce55120fb670362b8 /src
parent95c8a54c7d4488b5bdd6fb73196bf1463e7556e9 (diff)
downloadsqlite-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.c66
-rw-r--r--src/mem2.c161
-rw-r--r--src/printf.c7
-rw-r--r--src/test1.c4
-rw-r--r--src/test6.c72
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