/ Check-in [56c8af14]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add a mode to the sqlite3_test_control() interface to register hooks called at the beginning and end of "benign malloc failure" blocks. This allows malloc() failure testing to be done using public APIs only. (CVS 5254)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 56c8af1452dfdc8da858a2411bd6f3663a8a9326
User & Date: danielk1977 2008-06-20 14:59:51
Context
2008-06-20
15:24
Change the SRT_Subroutine mode into SRT_Coroutine. Use co-routines in the INSERT processing logic. (CVS 5255) check-in: 6b9d92fc user: drh tags: trunk
14:59
Add a mode to the sqlite3_test_control() interface to register hooks called at the beginning and end of "benign malloc failure" blocks. This allows malloc() failure testing to be done using public APIs only. (CVS 5254) check-in: 56c8af14 user: danielk1977 tags: trunk
11:05
Move (almost all) malloc failure test logic from fault.c to test_malloc.c. (CVS 5253) check-in: 4ae21e34 user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/bitvec.c.

    28     28   ** Clear operations are exceedingly rare.  There are usually between
    29     29   ** 5 and 500 set operations per Bitvec object, though the number of sets can
    30     30   ** sometimes grow into tens of thousands or larger.  The size of the
    31     31   ** Bitvec object is the number of pages in the database file at the
    32     32   ** start of a transaction, and is thus usually less than a few thousand,
    33     33   ** but can be as large as 2 billion for a really big database.
    34     34   **
    35         -** @(#) $Id: bitvec.c,v 1.5 2008/05/13 13:27:34 drh Exp $
           35  +** @(#) $Id: bitvec.c,v 1.6 2008/06/20 14:59:51 danielk1977 Exp $
    36     36   */
    37     37   #include "sqliteInt.h"
    38     38   
    39     39   #define BITVEC_SZ        512
    40     40   /* Round the union size down to the nearest pointer boundary, since that's how 
    41     41   ** it will be aligned within the Bitvec struct. */
    42     42   #define BITVEC_USIZE     (((BITVEC_SZ-12)/sizeof(Bitvec*))*sizeof(Bitvec*))
................................................................................
   136    136       p->u.aBitmap[i/8] |= 1 << (i&7);
   137    137       return SQLITE_OK;
   138    138     }
   139    139     if( p->iDivisor ){
   140    140       u32 bin = (i-1)/p->iDivisor;
   141    141       i = (i-1)%p->iDivisor + 1;
   142    142       if( p->u.apSub[bin]==0 ){
   143         -      sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC);
          143  +      sqlite3BeginBenignMalloc();
   144    144         p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
   145         -      sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC);
          145  +      sqlite3EndBenignMalloc();
   146    146         if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM;
   147    147       }
   148    148       return sqlite3BitvecSet(p->u.apSub[bin], i);
   149    149     }
   150    150     h = BITVEC_HASH(i);
   151    151     while( p->u.aHash[h] ){
   152    152       if( p->u.aHash[h]==i ) return SQLITE_OK;

Changes to src/fault.c.

     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   **
           13  +** $Id: fault.c,v 1.9 2008/06/20 14:59:51 danielk1977 Exp $
           14  +*/
           15  +
           16  +/*
    13     17   ** This file contains code to support the concept of "benign" 
    14         -** malloc failures. 
           18  +** malloc failures (when the xMalloc() or xRealloc() method of the
           19  +** sqlite3_mem_methods structure fails to allocate a block of memory
           20  +** and returns 0). 
    15     21   **
    16         -** $Id: fault.c,v 1.8 2008/06/20 11:05:38 danielk1977 Exp $
           22  +** Most malloc failures are non-benign. After they occur, SQLite
           23  +** abandons the current operation and returns an error code (usually
           24  +** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily
           25  +** fatal. For example, if a malloc fails while resizing a hash table, this 
           26  +** is completely recoverable simply by not carrying out the resize. The 
           27  +** hash table will continue to function normally.  So a malloc failure 
           28  +** during a hash table resize is a benign fault.
    17     29   */
    18     30   
    19     31   #include "sqliteInt.h"
    20     32   
    21     33   #ifndef SQLITE_OMIT_BUILTIN_TEST
    22     34   
    23     35   /*
    24         -** If zero, malloc() failures are non-benign. If non-zero, benign.
           36  +** Global variables.
    25     37   */
    26         -static int memfault_is_benign = 0;
           38  +static struct BenignMallocHooks {
           39  +  void (*xBenignBegin)(void);
           40  +  void (*xBenignEnd)(void);
           41  +} hooks;
    27     42   
    28     43   /*
    29         -** Return true if a malloc failures are currently considered to be
    30         -** benign. A benign fault does not affect the operation of sqlite.
    31         -** By constrast a non-benign fault causes sqlite to fail the current 
    32         -** operation and return SQLITE_NOMEM to the user.
           44  +** Register hooks to call when sqlite3BeginBenignMalloc() and
           45  +** sqlite3EndBenignMalloc() are called, respectively.
    33     46   */
    34         -int sqlite3FaultIsBenign(void){
    35         -  return memfault_is_benign;
           47  +void sqlite3BenignMallocHooks(
           48  +  void (*xBenignBegin)(void),
           49  +  void (*xBenignEnd)(void)
           50  +){
           51  +  hooks.xBenignBegin = xBenignBegin;
           52  +  hooks.xBenignEnd = xBenignEnd;
    36     53   }
    37     54   
    38         -/* 
    39         -** After this routine causes subsequent malloc faults to be either 
    40         -** benign or hard (not benign), according to the "enable" parameter.
    41         -**
    42         -** Most faults are hard.  In other words, most faults cause
    43         -** an error to be propagated back up to the application interface.
    44         -** However, sometimes a fault is easily recoverable.  For example,
    45         -** if a malloc fails while resizing a hash table, this is completely
    46         -** recoverable simply by not carrying out the resize.  The hash table
    47         -** will continue to function normally.  So a malloc failure during
    48         -** a hash table resize is a benign fault.  
           55  +/*
           56  +** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
           57  +** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
           58  +** indicates that subsequent malloc failures are non-benign.
    49     59   */
    50         -void sqlite3FaultBeginBenign(int id){
    51         -  memfault_is_benign++;
           60  +void sqlite3BeginBenignMalloc(void){
           61  +  if( hooks.xBenignBegin ){
           62  +    hooks.xBenignBegin();
           63  +  }
    52     64   }
    53         -void sqlite3FaultEndBenign(int id){
    54         -  memfault_is_benign--;
           65  +void sqlite3EndBenignMalloc(void){
           66  +  if( hooks.xBenignEnd ){
           67  +    hooks.xBenignEnd();
           68  +  }
    55     69   }
    56     70   
    57     71   #endif   /* #ifndef SQLITE_OMIT_BUILTIN_TEST */
    58     72   

Changes to src/hash.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This is the implementation of generic hash-tables
    13     13   ** used in SQLite.
    14     14   **
    15         -** $Id: hash.c,v 1.29 2008/06/15 02:51:47 drh Exp $
           15  +** $Id: hash.c,v 1.30 2008/06/20 14:59:51 danielk1977 Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include <assert.h>
    19     19   
    20     20   /* Turn bulk memory into a hash table object by initializing the
    21     21   ** fields of the Hash structure.
    22     22   **
................................................................................
   229    229   #endif
   230    230   
   231    231     /* There is a call to sqlite3_malloc() inside rehash(). If there is
   232    232     ** already an allocation at pH->ht, then if this malloc() fails it
   233    233     ** is benign (since failing to resize a hash table is a performance
   234    234     ** hit only, not a fatal error).
   235    235     */
   236         -  if( pH->htsize>0 ) sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC);
          236  +  if( pH->htsize>0 ) sqlite3BeginBenignMalloc();
   237    237     new_ht = (struct _ht *)sqlite3MallocZero( new_size*sizeof(struct _ht) );
   238         -  if( pH->htsize>0 ) sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC);
          238  +  if( pH->htsize>0 ) sqlite3EndBenignMalloc();
   239    239   
   240    240     if( new_ht==0 ) return;
   241    241     sqlite3_free(pH->ht);
   242    242     pH->ht = new_ht;
   243    243     pH->htsize = new_size;
   244    244     xHash = hashFunction(pH->keyClass);
   245    245     for(elem=pH->first, pH->first=0; elem; elem = next_elem){

Changes to src/main.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Main file for the SQLite library.  The routines in this file
    13     13   ** implement the programmer interface to the library.  Routines in
    14     14   ** other files are for internal use by SQLite and should not be
    15     15   ** accessed by users of the library.
    16     16   **
    17         -** $Id: main.c,v 1.454 2008/06/20 11:05:38 danielk1977 Exp $
           17  +** $Id: main.c,v 1.455 2008/06/20 14:59:51 danielk1977 Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include <ctype.h>
    21     21   
    22     22   #ifdef SQLITE_ENABLE_FTS3
    23     23   # include "fts3.h"
    24     24   #endif
................................................................................
   406    406   /*
   407    407   ** Rollback all database files.
   408    408   */
   409    409   void sqlite3RollbackAll(sqlite3 *db){
   410    410     int i;
   411    411     int inTrans = 0;
   412    412     assert( sqlite3_mutex_held(db->mutex) );
   413         -  sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC);
          413  +  sqlite3BeginBenignMalloc();
   414    414     for(i=0; i<db->nDb; i++){
   415    415       if( db->aDb[i].pBt ){
   416    416         if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){
   417    417           inTrans = 1;
   418    418         }
   419    419         sqlite3BtreeRollback(db->aDb[i].pBt);
   420    420         db->aDb[i].inTrans = 0;
   421    421       }
   422    422     }
   423    423     sqlite3VtabRollback(db);
   424         -  sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC);
          424  +  sqlite3EndBenignMalloc();
   425    425   
   426    426     if( db->flags&SQLITE_InternChanges ){
   427    427       sqlite3ExpirePreparedStatements(db);
   428    428       sqlite3ResetInternalSchema(db, 0);
   429    429     }
   430    430   
   431    431     /* If one has been configured, invoke the rollback-hook callback */
................................................................................
  1759   1759   */
  1760   1760   int sqlite3_test_control(int op, ...){
  1761   1761     int rc = 0;
  1762   1762   #ifndef SQLITE_OMIT_BUILTIN_TEST
  1763   1763     va_list ap;
  1764   1764     va_start(ap, op);
  1765   1765     switch( op ){
  1766         -#if 0
  1767         -    /*
  1768         -    ** sqlite3_test_control(FAULT_CONFIG, fault_id, nDelay, nRepeat)
  1769         -    **
  1770         -    ** Configure a fault injector.  The specific fault injector is
  1771         -    ** identified by the fault_id argument.  (ex: SQLITE_FAULTINJECTOR_MALLOC)
  1772         -    ** The fault will occur after a delay of nDelay calls.  The fault
  1773         -    ** will repeat nRepeat times.
  1774         -    */
  1775         -    case SQLITE_TESTCTRL_FAULT_CONFIG: {
  1776         -      int id = va_arg(ap, int);
  1777         -      int nDelay = va_arg(ap, int);
  1778         -      int nRepeat = va_arg(ap, int);
  1779         -      sqlite3FaultConfig(id, nDelay, nRepeat);
  1780         -      break;
  1781         -    }
  1782         -
  1783         -    /*
  1784         -    ** sqlite3_test_control(FAULT_FAILURES, fault_id)
  1785         -    **
  1786         -    ** Return the number of faults (both hard and benign faults) that have
  1787         -    ** occurred since the injector identified by fault_id) was last configured.
  1788         -    */
  1789         -    case SQLITE_TESTCTRL_FAULT_FAILURES: {
  1790         -      int id = va_arg(ap, int);
  1791         -      rc = sqlite3FaultFailures(id);
  1792         -      break;
  1793         -    }
  1794         -
  1795         -    /*
  1796         -    ** sqlite3_test_control(FAULT_BENIGN_FAILURES, fault_id)
  1797         -    **
  1798         -    ** Return the number of benign faults that have occurred since the
  1799         -    ** injector identified by fault_id was last configured.
  1800         -    */
  1801         -    case SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES: {
  1802         -      int id = va_arg(ap, int);
  1803         -      rc = sqlite3FaultBenignFailures(id);
  1804         -      break;
  1805         -    }
  1806         -
  1807         -    /*
  1808         -    ** sqlite3_test_control(FAULT_PENDING, fault_id)
  1809         -    **
  1810         -    ** Return the number of successes that will occur before the next
  1811         -    ** scheduled failure on fault injector fault_id.
  1812         -    ** If no failures are scheduled, return -1.
  1813         -    */
  1814         -    case SQLITE_TESTCTRL_FAULT_PENDING: {
  1815         -      int id = va_arg(ap, int);
  1816         -      rc = sqlite3FaultPending(id);
  1817         -      break;
  1818         -    }
  1819         -
  1820         -    /*
  1821         -    ** sqlite3_test_control(FAULT_INSTALL, isInstall)
  1822         -    **
  1823         -    ** If the argument is non-zero, install the fault-simulation malloc layer
  1824         -    ** as a wrapper around the currently installed implementation.
  1825         -    */
  1826         -    case SQLITE_TESTCTRL_FAULT_INSTALL: {
  1827         -      int isInstall = va_arg(ap, int);
  1828         -      rc = sqlite3FaultsimInstall(isInstall);
  1829         -      break;
  1830         -    }
  1831         -#endif
  1832   1766   
  1833   1767       /*
  1834   1768       ** Save the current state of the PRNG.
  1835   1769       */
  1836   1770       case SQLITE_TESTCTRL_PRNG_SAVE: {
  1837   1771         sqlite3PrngSaveState();
  1838   1772         break;
................................................................................
  1868   1802       */
  1869   1803       case SQLITE_TESTCTRL_BITVEC_TEST: {
  1870   1804         int sz = va_arg(ap, int);
  1871   1805         int *aProg = va_arg(ap, int*);
  1872   1806         rc = sqlite3BitvecBuiltinTest(sz, aProg);
  1873   1807         break;
  1874   1808       }
         1809  +
         1810  +    /*
         1811  +    **  sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
         1812  +    **
         1813  +    ** Register hooks to call to indicate which malloc() failures 
         1814  +    ** are benign.
         1815  +    */
         1816  +    case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: {
         1817  +      void (*xBenignBegin)(void);
         1818  +      void (*xBenignEnd)(void);
         1819  +      xBenignBegin = va_arg(ap, void(*)(void));
         1820  +      xBenignEnd = va_arg(ap, void(*)(void));
         1821  +      sqlite3BenignMallocHooks(xBenignBegin, xBenignEnd);
         1822  +      break;
         1823  +    }
  1875   1824     }
  1876   1825     va_end(ap);
  1877   1826   #endif /* SQLITE_OMIT_BUILTIN_TEST */
  1878   1827     return rc;
  1879   1828   }

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.459 2008/06/18 17:09:10 danielk1977 Exp $
           21  +** @(#) $Id: pager.c,v 1.460 2008/06/20 14:59:51 danielk1977 Exp $
    22     22   */
    23     23   #ifndef SQLITE_OMIT_DISKIO
    24     24   #include "sqliteInt.h"
    25     25   #include <assert.h>
    26     26   #include <string.h>
    27     27   
    28     28   /*
................................................................................
   684    684   #ifdef SQLITE_MALLOC_SOFT_LIMIT
   685    685     if( N*sizeof(aHash[0])>SQLITE_MALLOC_SOFT_LIMIT ){
   686    686       N = SQLITE_MALLOC_SOFT_LIMIT/sizeof(aHash[0]);
   687    687     }
   688    688     if( N==pPager->nHash ) return;
   689    689   #endif
   690    690     pagerLeave(pPager);
   691         -  if( pPager->aHash!=0 ) sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC);
          691  +  if( pPager->aHash!=0 ) sqlite3BeginBenignMalloc();
   692    692     aHash = sqlite3MallocZero( sizeof(aHash[0])*N );
   693         -  if( pPager->aHash!=0 ) sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC);
          693  +  if( pPager->aHash!=0 ) sqlite3EndBenignMalloc();
   694    694     pagerEnter(pPager);
   695    695     if( aHash==0 ){
   696    696       /* Failure to rehash is not an error.  It is only a performance hit. */
   697    697       return;
   698    698     }
   699    699     sqlite3_free(pPager->aHash);
   700    700     pPager->nHash = N;
................................................................................
  1371   1371   ** Execute a rollback if a transaction is active and unlock the 
  1372   1372   ** database file. If the pager has already entered the error state, 
  1373   1373   ** do not attempt the rollback.
  1374   1374   */
  1375   1375   static void pagerUnlockAndRollback(Pager *p){
  1376   1376     /* assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); */
  1377   1377     if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){
  1378         -    sqlite3FaultBeginBenign(-1);
         1378  +    sqlite3BeginBenignMalloc();
  1379   1379       sqlite3PagerRollback(p);
  1380         -    sqlite3FaultEndBenign(-1);
         1380  +    sqlite3EndBenignMalloc();
  1381   1381     }
  1382   1382     pager_unlock(p);
  1383   1383   #if 0
  1384   1384     assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) );
  1385   1385     assert( p->errCode || !p->stmtOpen || p->exclusiveMode );
  1386   1386   #endif
  1387   1387   }
................................................................................
  2763   2763         pPager->pNext->pPrev = pPager->pPrev;
  2764   2764       }
  2765   2765       sqlite3_mutex_leave(mutex);
  2766   2766     }
  2767   2767   #endif
  2768   2768   
  2769   2769     disable_simulated_io_errors();
  2770         -  sqlite3FaultBeginBenign(-1);
         2770  +  sqlite3BeginBenignMalloc();
  2771   2771     pPager->errCode = 0;
  2772   2772     pPager->exclusiveMode = 0;
  2773   2773     pager_reset(pPager);
  2774   2774     pagerUnlockAndRollback(pPager);
  2775   2775     enable_simulated_io_errors();
  2776         -  sqlite3FaultEndBenign(-1);
         2776  +  sqlite3EndBenignMalloc();
  2777   2777     PAGERTRACE2("CLOSE %d\n", PAGERID(pPager));
  2778   2778     IOTRACE(("CLOSE %p\n", pPager))
  2779   2779     if( pPager->journalOpen ){
  2780   2780       sqlite3OsClose(pPager->jfd);
  2781   2781     }
  2782   2782     sqlite3BitvecDestroy(pPager->pInJournal);
  2783   2783     if( pPager->stmtOpen ){

Changes to src/sqlite.h.in.

    26     26   ** on how SQLite interfaces are suppose to operate.
    27     27   **
    28     28   ** The name of this file under configuration management is "sqlite.h.in".
    29     29   ** The makefile makes some minor changes to this file (such as inserting
    30     30   ** the version number) and changes its name to "sqlite3.h" as
    31     31   ** part of the build process.
    32     32   **
    33         -** @(#) $Id: sqlite.h.in,v 1.341 2008/06/19 18:17:50 danielk1977 Exp $
           33  +** @(#) $Id: sqlite.h.in,v 1.342 2008/06/20 14:59:51 danielk1977 Exp $
    34     34   */
    35     35   #ifndef _SQLITE3_H_
    36     36   #define _SQLITE3_H_
    37     37   #include <stdarg.h>     /* Needed for the definition of va_list */
    38     38   
    39     39   /*
    40     40   ** Make sure we can call this stuff from C++.
................................................................................
  6048   6048   ** as the first argument to [sqlite3_test_control()].
  6049   6049   **
  6050   6050   ** These parameters and their meanings are subject to change
  6051   6051   ** without notice.  These values are for testing purposes only.
  6052   6052   ** Applications should not use any of these parameters or the
  6053   6053   ** [sqlite3_test_control()] interface.
  6054   6054   */
  6055         -#define SQLITE_TESTCTRL_FAULT_CONFIG             1
  6056         -#define SQLITE_TESTCTRL_FAULT_FAILURES           2
  6057         -#define SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES    3
  6058         -#define SQLITE_TESTCTRL_FAULT_PENDING            4
  6059   6055   #define SQLITE_TESTCTRL_PRNG_SAVE                5
  6060   6056   #define SQLITE_TESTCTRL_PRNG_RESTORE             6
  6061   6057   #define SQLITE_TESTCTRL_PRNG_RESET               7
  6062   6058   #define SQLITE_TESTCTRL_BITVEC_TEST              8
  6063   6059   #define SQLITE_TESTCTRL_FAULT_INSTALL            9
         6060  +#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10
  6064   6061   
  6065   6062   /*
  6066   6063   ** CAPI3REF: SQLite Runtime Status {F17200}
  6067   6064   **
  6068   6065   ** This interface is used to retrieve run-time status information
  6069   6066   ** about the preformance of SQLite, and optionally to reset various
  6070   6067   ** highwater marks.  The first argument is an integer code for

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.719 2008/06/20 11:05:38 danielk1977 Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.720 2008/06/20 14:59:51 danielk1977 Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** Include the configuration header output by 'configure' if we're using the
    21     21   ** autoconf-based build
................................................................................
  2204   2204   
  2205   2205   /*
  2206   2206   ** The interface to the code in fault.c used for identifying "benign"
  2207   2207   ** malloc failures. This is only present if SQLITE_OMIT_BUILTIN_TEST
  2208   2208   ** is not defined.
  2209   2209   */
  2210   2210   #ifndef SQLITE_OMIT_BUILTIN_TEST
  2211         -  void sqlite3FaultBeginBenign(int);
  2212         -  void sqlite3FaultEndBenign(int);
  2213         -  int sqlite3FaultIsBenign(void);
         2211  +  void sqlite3BeginBenignMalloc(void);
         2212  +  void sqlite3EndBenignMalloc(void);
  2214   2213   #else
  2215         -  #define sqlite3FaultBeginBenign()
         2214  +  #define sqlite3BeginBenignMalloc()
  2216   2215     #define sqlite3FaultEndBenign()
  2217   2216   #endif
  2218   2217   
  2219   2218   #define IN_INDEX_ROWID           1
  2220   2219   #define IN_INDEX_EPH             2
  2221   2220   #define IN_INDEX_INDEX           3
  2222   2221   int sqlite3FindInIndex(Parse *, Expr *, int);

Changes to src/test8.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Code for testing the virtual table interfaces.  This code
    13     13   ** is not included in the SQLite library.  It is used for automated
    14     14   ** testing of the SQLite library.
    15     15   **
    16         -** $Id: test8.c,v 1.65 2008/06/16 14:19:58 danielk1977 Exp $
           16  +** $Id: test8.c,v 1.66 2008/06/20 14:59:51 danielk1977 Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "tcl.h"
    20     20   #include <stdlib.h>
    21     21   #include <string.h>
    22     22   
    23     23   #ifndef SQLITE_OMIT_VIRTUALTABLE
................................................................................
  1061   1061     echo_vtab *pVtab = (echo_vtab*)tab;
  1062   1062     int rc;
  1063   1063   
  1064   1064     /* Ticket #3083 - Only call xCommit if we have previously started
  1065   1065     ** a transaction */
  1066   1066     assert( pVtab->inTransaction );
  1067   1067   
  1068         -  sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC);
         1068  +  sqlite3BeginBenignMalloc();
  1069   1069     rc = echoTransactionCall(tab, "xCommit");
  1070         -  sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC);
         1070  +  sqlite3EndBenignMalloc();
  1071   1071     pVtab->inTransaction = 0;
  1072   1072     return rc;
  1073   1073   }
  1074   1074   static int echoRollback(sqlite3_vtab *tab){
  1075   1075     int rc;
  1076   1076     echo_vtab *pVtab = (echo_vtab*)tab;
  1077   1077   

Changes to src/test_malloc.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   **
    13     13   ** This file contains code used to implement test interfaces to the
    14     14   ** memory allocation subsystem.
    15     15   **
    16         -** $Id: test_malloc.c,v 1.27 2008/06/20 11:05:38 danielk1977 Exp $
           16  +** $Id: test_malloc.c,v 1.28 2008/06/20 14:59:51 danielk1977 Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "tcl.h"
    20     20   #include <stdlib.h>
    21     21   #include <string.h>
    22     22   #include <assert.h>
    23     23   
................................................................................
    28     28   static struct MemFault {
    29     29     int iCountdown;         /* Number of pending successes before a failure */
    30     30     int nRepeat;            /* Number of times to repeat the failure */
    31     31     int nBenign;            /* Number of benign failures seen since last config */
    32     32     int nFail;              /* Number of failures seen since last config */
    33     33     u8 enable;              /* True if enabled */
    34     34     int isInstalled;        /* True if the fault simulation layer is installed */
           35  +  int isBenignMode;       /* True if malloc failures are considered benign */
    35     36     sqlite3_mem_methods m;  /* 'Real' malloc implementation */
    36     37   } memfault;
    37     38   
    38     39   /*
    39     40   ** This routine exists as a place to set a breakpoint that will
    40     41   ** fire on any simulated malloc() failure.
    41     42   */
................................................................................
    54     55     }
    55     56     if( memfault.iCountdown>0 ){
    56     57       memfault.iCountdown--;
    57     58       return 0;
    58     59     }
    59     60     sqlite3Fault();
    60     61     memfault.nFail++;
    61         -  if( sqlite3FaultIsBenign()>0 ){
           62  +  if( memfault.isBenignMode>0 ){
    62     63       memfault.nBenign++;
    63     64     }
    64     65     memfault.nRepeat--;
    65     66     if( memfault.nRepeat<=0 ){
    66     67       memfault.enable = 0;
    67     68     }
    68     69     return 1;  
................................................................................
   157    158     if( memfault.enable ){
   158    159       return memfault.iCountdown;
   159    160     }else{
   160    161       return -1;
   161    162     }
   162    163   }
   163    164   
          165  +
          166  +static void faultsimBeginBenign(void){
          167  +  memfault.isBenignMode++;
          168  +}
          169  +static void faultsimEndBenign(void){
          170  +  memfault.isBenignMode--;
          171  +}
          172  +
   164    173   /*
   165    174   ** Add or remove the fault-simulation layer using sqlite3_config(). If
   166    175   ** the argument is non-zero, the 
   167    176   */
   168    177   static int faultsimInstall(int install){
   169    178     static struct sqlite3_mem_methods m = {
   170    179       faultsimMalloc,                   /* xMalloc */
................................................................................
   181    190     install = (install ? 1 : 0);
   182    191     assert(memfault.isInstalled==1 || memfault.isInstalled==0);
   183    192   
   184    193     if( install==memfault.isInstalled ){
   185    194       return SQLITE_ERROR;
   186    195     }
   187    196   
   188         -  rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
   189         -  assert(memfault.m.xMalloc);
   190         -  if( rc==SQLITE_OK ){
   191         -    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
          197  +  if( install ){
          198  +    rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
          199  +    assert(memfault.m.xMalloc);
          200  +    if( rc==SQLITE_OK ){
          201  +      rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
          202  +    }
          203  +    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 
          204  +        faultsimBeginBenign, faultsimEndBenign
          205  +    );
          206  +  }else{
          207  +    assert(memfault.m.xMalloc);
          208  +    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
          209  +    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0);
   192    210     }
   193    211   
   194    212     if( rc==SQLITE_OK ){
   195    213       memfault.isInstalled = 1;
   196    214     }
   197    215     return rc;
   198    216   }
................................................................................
  1008   1026        { "sqlite3_memdebug_pending",   test_memdebug_pending         },
  1009   1027        { "sqlite3_memdebug_settitle",  test_memdebug_settitle        },
  1010   1028        { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count },
  1011   1029        { "sqlite3_memdebug_log",       test_memdebug_log             },
  1012   1030        { "sqlite3_config_scratch",     test_config_scratch           },
  1013   1031        { "sqlite3_config_pagecache",   test_config_pagecache         },
  1014   1032        { "sqlite3_status",             test_status                   },
  1015         -
  1016   1033        { "install_malloc_faultsim",    test_install_malloc_faultsim  },
  1017   1034     };
  1018   1035     int i;
  1019   1036     for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
  1020   1037       Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
  1021   1038     }
  1022   1039     return TCL_OK;
  1023   1040   }
  1024   1041   #endif

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.749 2008/06/15 02:51:48 drh Exp $
           46  +** $Id: vdbe.c,v 1.750 2008/06/20 14:59:51 danielk1977 Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include <ctype.h>
    50     50   #include "vdbeInt.h"
    51     51   
    52     52   /*
    53     53   ** The following global variable is incremented every time a cursor
................................................................................
   566    566     p->rc = SQLITE_OK;
   567    567     assert( p->explain==0 );
   568    568     p->pResultSet = 0;
   569    569     db->busyHandler.nBusy = 0;
   570    570     CHECK_FOR_INTERRUPT;
   571    571     sqlite3VdbeIOTraceSql(p);
   572    572   #ifdef SQLITE_DEBUG
   573         -  sqlite3FaultBeginBenign(-1);
          573  +  sqlite3BeginBenignMalloc();
   574    574     if( p->pc==0 
   575    575      && ((p->db->flags & SQLITE_VdbeListing) || fileExists(db, "vdbe_explain"))
   576    576     ){
   577    577       int i;
   578    578       printf("VDBE Program Listing:\n");
   579    579       sqlite3VdbePrintSql(p);
   580    580       for(i=0; i<p->nOp; i++){
   581    581         sqlite3VdbePrintOp(stdout, i, &p->aOp[i]);
   582    582       }
   583    583     }
   584    584     if( fileExists(db, "vdbe_trace") ){
   585    585       p->trace = stdout;
   586    586     }
   587         -  sqlite3FaultEndBenign(-1);
          587  +  sqlite3EndBenignMalloc();
   588    588   #endif
   589    589     for(pc=p->pc; rc==SQLITE_OK; pc++){
   590    590       assert( pc>=0 && pc<p->nOp );
   591    591       if( db->mallocFailed ) goto no_mem;
   592    592   #ifdef VDBE_PROFILE
   593    593       origPc = pc;
   594    594       start = sqlite3Hwtime();
................................................................................
   602    602         if( pc==0 ){
   603    603           printf("VDBE Execution Trace:\n");
   604    604           sqlite3VdbePrintSql(p);
   605    605         }
   606    606         sqlite3VdbePrintOp(p->trace, pc, pOp);
   607    607       }
   608    608       if( p->trace==0 && pc==0 ){
   609         -      sqlite3FaultBeginBenign(-1);
          609  +      sqlite3BeginBenignMalloc();
   610    610         if( fileExists(db, "vdbe_sqltrace") ){
   611    611           sqlite3VdbePrintSql(p);
   612    612         }
   613         -      sqlite3FaultEndBenign(-1);
          613  +      sqlite3EndBenignMalloc();
   614    614       }
   615    615   #endif
   616    616         
   617    617   
   618    618       /* Check to see if we need to simulate an interrupt.  This only happens
   619    619       ** if we have a special test build.
   620    620       */

Changes to src/vdbeaux.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains code used for creating, destroying, and populating
    13     13   ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
    14     14   ** to version 2.8.7, all this code was combined into the vdbe.c source file.
    15     15   ** But that file was getting too big so this subroutines were split out.
    16     16   **
    17         -** $Id: vdbeaux.c,v 1.388 2008/06/18 15:34:10 drh Exp $
           17  +** $Id: vdbeaux.c,v 1.389 2008/06/20 14:59:51 danielk1977 Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include <ctype.h>
    21     21   #include "vdbeInt.h"
    22     22   
    23     23   
    24     24   
................................................................................
  1384   1384       ** calls to sqlite3BtreeCommitPhaseTwo() are only closing files and
  1385   1385       ** deleting or truncating journals. If something goes wrong while
  1386   1386       ** this is happening we don't really care. The integrity of the
  1387   1387       ** transaction is already guaranteed, but some stray 'cold' journals
  1388   1388       ** may be lying around. Returning an error code won't help matters.
  1389   1389       */
  1390   1390       disable_simulated_io_errors();
  1391         -    sqlite3FaultBeginBenign(SQLITE_FAULTINJECTOR_MALLOC);
         1391  +    sqlite3BeginBenignMalloc();
  1392   1392       for(i=0; i<db->nDb; i++){ 
  1393   1393         Btree *pBt = db->aDb[i].pBt;
  1394   1394         if( pBt ){
  1395   1395           sqlite3BtreeCommitPhaseTwo(pBt);
  1396   1396         }
  1397   1397       }
  1398         -    sqlite3FaultEndBenign(SQLITE_FAULTINJECTOR_MALLOC);
         1398  +    sqlite3EndBenignMalloc();
  1399   1399       enable_simulated_io_errors();
  1400   1400   
  1401   1401       sqlite3VtabCommit(db);
  1402   1402     }
  1403   1403   #endif
  1404   1404   
  1405   1405     return rc;