1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-10 01:02:56 +03:00

Improvements to the way that OOM errors are processed.

FossilOrigin-Name: c3ef03478a5788c855b3aef385d43ae7f494f440
This commit is contained in:
drh
2016-02-05 01:55:27 +00:00
parent e514f651d0
commit 4a642b6060
30 changed files with 166 additions and 125 deletions

View File

@@ -608,10 +608,8 @@ void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){
#ifndef SQLITE_OMIT_LOOKASIDE
if( db ){
LookasideSlot *pBuf;
if( db->mallocFailed ){
return 0;
}
if( db->lookaside.bEnabled ){
if( db->lookaside.bDisable==0 ){
assert( db->mallocFailed==0 );
if( n>db->lookaside.sz ){
db->lookaside.anStat[1]++;
}else if( (pBuf = db->lookaside.pFree)==0 ){
@@ -625,7 +623,10 @@ void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){
}
return (void*)pBuf;
}
}else if( db->mallocFailed ){
return 0;
}
}
#else
if( db && db->mallocFailed ){
@@ -637,10 +638,10 @@ void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){
static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){
void *p = sqlite3Malloc(n);
if( !p && db ){
db->mallocFailed = 1;
sqlite3OomFault(db);
}
sqlite3MemdebugSetType(p,
(db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP);
(db && db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP);
return p;
}
@@ -671,10 +672,10 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
pNew = sqlite3_realloc64(p, n);
if( !pNew ){
db->mallocFailed = 1;
sqlite3OomFault(db);
}
sqlite3MemdebugSetType(pNew,
(db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
(db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
}
}
return pNew;
@@ -736,11 +737,43 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
*pz = sqlite3DbStrDup(db, zNew);
}
/*
** Call this routine to record the fact that an OOM (out-of-memory) error
** has happened. This routine will set db->mallocFailed, and also
** temporarily disable the lookaside memory allocator and interrupt
** any running VDBEs.
*/
void sqlite3OomFault(sqlite3 *db){
if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
db->mallocFailed = 1;
if( db->nVdbeExec>0 ){
db->u1.isInterrupted = 1;
}
db->lookaside.bDisable++;
}
}
/*
** This routine reactivates the memory allocator and clears the
** db->mallocFailed flag as necessary.
**
** The memory allocator is not restarted if there are running
** VDBEs.
*/
void sqlite3OomClear(sqlite3 *db){
if( db->mallocFailed && db->nVdbeExec==0 ){
db->mallocFailed = 0;
db->u1.isInterrupted = 0;
assert( db->lookaside.bDisable>0 );
db->lookaside.bDisable--;
}
}
/*
** Take actions at the end of an API call to indicate an OOM error
*/
static SQLITE_NOINLINE int apiOomError(sqlite3 *db){
db->mallocFailed = 0;
sqlite3OomClear(db);
sqlite3Error(db, SQLITE_NOMEM);
return SQLITE_NOMEM;
}