/ Check-in [d22cd2a5]
Login

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

Overview
Comment:Move the malloc() failure simulation out of malloc.c and into a separate sqlite3_mem_methods interface. Still some related changes to come. (CVS 5250)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d22cd2a59f472f4eaf80aa9f55fbff2514ca428d
User & Date: danielk1977 2008-06-19 18:17:50
Context
2008-06-19
18:39
Unset global TCL variables in the func.test script prior to use to avoid conflicts from other scripts. (CVS 5251) check-in: 9b04e10f user: drh tags: trunk
18:17
Move the malloc() failure simulation out of malloc.c and into a separate sqlite3_mem_methods interface. Still some related changes to come. (CVS 5250) check-in: d22cd2a5 user: danielk1977 tags: trunk
17:54
Documentation and test-script updates. (CVS 5249) check-in: 68d4f795 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/fault.c.

    22     22   ** compiled with -DSQLITE_OMIT_BUILTIN_TEST=1.  There is a very
    23     23   ** small performance hit for leaving the fault injector in the code.
    24     24   ** Commerical products will probably want to omit the fault injector
    25     25   ** from production builds.  But safety-critical systems who work
    26     26   ** under the motto "fly what you test and test what you fly" may
    27     27   ** choose to leave the fault injector enabled even in production.
    28     28   **
    29         -** $Id: fault.c,v 1.6 2008/05/15 19:43:53 drh Exp $
           29  +** $Id: fault.c,v 1.7 2008/06/19 18:17:50 danielk1977 Exp $
    30     30   */
    31     31   #include "sqliteInt.h"
    32     32   
    33         -#ifndef SQLITE_OMIT_BUILTIN_TEST
    34         -
    35     33   /*
    36     34   ** There can be various kinds of faults.  For example, there can be
    37     35   ** a memory allocation failure.  Or an I/O failure.  For each different
    38     36   ** fault type, there is a separate FaultInjector structure to keep track
    39     37   ** of the status of that fault.
    40     38   */
    41         -static struct FaultInjector {
           39  +static struct MemFault {
    42     40     int iCountdown;   /* Number of pending successes before we hit a failure */
    43     41     int nRepeat;      /* Number of times to repeat the failure */
    44     42     int nBenign;      /* Number of benign failures seen since last config */
    45     43     int nFail;        /* Number of failures seen since last config */
    46     44     u8 enable;        /* True if enabled */
    47     45     i16 benign;       /* Positive if next failure will be benign */
    48         -} aFault[SQLITE_FAULTINJECTOR_COUNT];
           46  +
           47  +  int isInstalled;
           48  +  sqlite3_mem_methods m;         /* 'Real' malloc implementation */
           49  +} memfault;
           50  +
           51  +/*
           52  +** This routine exists as a place to set a breakpoint that will
           53  +** fire on any simulated malloc() failure.
           54  +*/
           55  +static void sqlite3Fault(void){
           56  +  static int cnt = 0;
           57  +  cnt++;
           58  +}
           59  +
           60  +/*
           61  +** Check to see if a fault should be simulated.  Return true to simulate
           62  +** the fault.  Return false if the fault should not be simulated.
           63  +*/
           64  +static int faultsimStep(){
           65  +  if( likely(!memfault.enable) ){
           66  +    return 0;
           67  +  }
           68  +  if( memfault.iCountdown>0 ){
           69  +    memfault.iCountdown--;
           70  +    return 0;
           71  +  }
           72  +  sqlite3Fault();
           73  +  memfault.nFail++;
           74  +  if( memfault.benign>0 ){
           75  +    memfault.nBenign++;
           76  +  }
           77  +  memfault.nRepeat--;
           78  +  if( memfault.nRepeat<=0 ){
           79  +    memfault.enable = 0;
           80  +  }
           81  +  return 1;  
           82  +}
           83  +
           84  +static void *faultsimMalloc(int n){
           85  +  void *p = 0;
           86  +  if( !faultsimStep() ){
           87  +    p = memfault.m.xMalloc(n);
           88  +  }
           89  +  return p;
           90  +}
           91  +
           92  +
           93  +static void *faultsimRealloc(void *pOld, int n){
           94  +  void *p = 0;
           95  +  if( !faultsimStep() ){
           96  +    p = memfault.m.xRealloc(pOld, n);
           97  +  }
           98  +  return p;
           99  +}
          100  +
          101  +/* 
          102  +** The following method calls are passed directly through to the underlying
          103  +** malloc system:
          104  +**
          105  +**     xFree
          106  +**     xSize
          107  +**     xRoundup
          108  +**     xInit
          109  +**     xShutdown
          110  +*/
          111  +static void faultsimFree(void *p){
          112  +  memfault.m.xFree(p);
          113  +}
          114  +static int faultsimSize(void *p){
          115  +  return memfault.m.xSize(p);
          116  +}
          117  +static int faultsimRoundup(int n){
          118  +  return memfault.m.xRoundup(n);
          119  +}
          120  +static int faultsimInit(void *p){
          121  +  return memfault.m.xInit(memfault.m.pAppData);
          122  +}
          123  +static void faultsimShutdown(void *p){
          124  +  memfault.m.xShutdown(memfault.m.pAppData);
          125  +}
    49    126   
    50    127   /*
    51    128   ** This routine configures and enables a fault injector.  After
    52         -** calling this routine, aFaultStep() will return false (zero)
          129  +** calling this routine, a FaultStep() will return false (zero)
    53    130   ** nDelay times, then it will return true nRepeat times,
    54    131   ** then it will again begin returning false.
    55    132   */
    56    133   void sqlite3FaultConfig(int id, int nDelay, int nRepeat){
    57         -  assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
    58         -  aFault[id].iCountdown = nDelay;
    59         -  aFault[id].nRepeat = nRepeat;
    60         -  aFault[id].nBenign = 0;
    61         -  aFault[id].nFail = 0;
    62         -  aFault[id].enable = nDelay>=0;
    63         -  aFault[id].benign = 0;
          134  +  memfault.iCountdown = nDelay;
          135  +  memfault.nRepeat = nRepeat;
          136  +  memfault.nBenign = 0;
          137  +  memfault.nFail = 0;
          138  +  memfault.enable = nDelay>=0;
          139  +  memfault.benign = 0;
    64    140   }
    65    141   
    66    142   /*
    67    143   ** Return the number of faults (both hard and benign faults) that have
    68    144   ** occurred since the injector was last configured.
    69    145   */
    70    146   int sqlite3FaultFailures(int id){
    71    147     assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
    72         -  return aFault[id].nFail;
          148  +  return memfault.nFail;
    73    149   }
    74    150   
    75    151   /*
    76    152   ** Return the number of benign faults that have occurred since the
    77    153   ** injector was last configured.
    78    154   */
    79    155   int sqlite3FaultBenignFailures(int id){
    80         -  assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
    81         -  return aFault[id].nBenign;
          156  +  return memfault.nBenign;
    82    157   }
    83    158   
    84    159   /*
    85    160   ** Return the number of successes that will occur before the next failure.
    86    161   ** If no failures are scheduled, return -1.
    87    162   */
    88    163   int sqlite3FaultPending(int id){
    89         -  assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
    90         -  if( aFault[id].enable ){
    91         -    return aFault[id].iCountdown;
          164  +  if( memfault.enable ){
          165  +    return memfault.iCountdown;
    92    166     }else{
    93    167       return -1;
    94    168     }
    95    169   }
    96    170   
    97    171   /* 
    98    172   ** After this routine causes subsequent faults to be either benign
................................................................................
   105    179   ** recoverable simply by not carrying out the resize.  The hash table
   106    180   ** will continue to function normally.  So a malloc failure during
   107    181   ** a hash table resize is a benign fault.  
   108    182   */
   109    183   void sqlite3FaultBeginBenign(int id){
   110    184     if( id<0 ){
   111    185       for(id=0; id<SQLITE_FAULTINJECTOR_COUNT; id++){
   112         -      aFault[id].benign++;
          186  +      memfault.benign++;
   113    187       }
   114    188     }else{
   115    189       assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
   116         -    aFault[id].benign++;
          190  +    memfault.benign++;
   117    191     }
   118    192   }
   119    193   void sqlite3FaultEndBenign(int id){
   120    194     if( id<0 ){
   121    195       for(id=0; id<SQLITE_FAULTINJECTOR_COUNT; id++){
   122         -      assert( aFault[id].benign>0 );
   123         -      aFault[id].benign--;
          196  +      assert( memfault.benign>0 );
          197  +      memfault.benign--;
   124    198       }
   125    199     }else{
   126         -    assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
   127         -    assert( aFault[id].benign>0 );
   128         -    aFault[id].benign--;
          200  +    assert( memfault.benign>0 );
          201  +    memfault.benign--;
   129    202     }
   130    203   }
   131    204   
   132         -/*
   133         -** This routine exists as a place to set a breakpoint that will
   134         -** fire on any simulated fault.
   135         -*/
   136         -static void sqlite3Fault(void){
   137         -  static int cnt = 0;
   138         -  cnt++;
   139         -}
          205  +int sqlite3FaultsimInstall(int install){
          206  +  static struct sqlite3_mem_methods m = {
          207  +    faultsimMalloc,                   /* xMalloc */
          208  +    faultsimFree,                     /* xFree */
          209  +    faultsimRealloc,                  /* xRealloc */
          210  +    faultsimSize,                     /* xSize */
          211  +    faultsimRoundup,                  /* xRoundup */
          212  +    faultsimInit,                     /* xInit */
          213  +    faultsimShutdown,                 /* xShutdown */
          214  +    0                                 /* pAppData */
          215  +  };
          216  +  int rc;
          217  +
          218  +  assert(install==1 || install==0);
          219  +  assert(memfault.isInstalled==1 || memfault.isInstalled==0);
          220  +
          221  +  if( install==memfault.isInstalled ){
          222  +    return SQLITE_ERROR;
          223  +  }
   140    224   
          225  +  rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
          226  +  assert(memfault.m.xMalloc);
          227  +  if( rc==SQLITE_OK ){
          228  +    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
          229  +  }
   141    230   
   142         -/*
   143         -** Check to see if a fault should be simulated.  Return true to simulate
   144         -** the fault.  Return false if the fault should not be simulated.
   145         -*/
   146         -int sqlite3FaultStep(int id){
   147         -  assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
   148         -  if( likely(!aFault[id].enable) ){
   149         -    return 0;
          231  +  if( rc==SQLITE_OK ){
          232  +    memfault.isInstalled = 1;
   150    233     }
   151         -  if( aFault[id].iCountdown>0 ){
   152         -    aFault[id].iCountdown--;
   153         -    return 0;
   154         -  }
   155         -  sqlite3Fault();
   156         -  aFault[id].nFail++;
   157         -  if( aFault[id].benign>0 ){
   158         -    aFault[id].nBenign++;
   159         -  }
   160         -  aFault[id].nRepeat--;
   161         -  if( aFault[id].nRepeat<=0 ){
   162         -    aFault[id].enable = 0;
   163         -  }
   164         -  return 1;  
          234  +  return rc;
   165    235   }
   166    236   
   167         -#endif /* SQLITE_OMIT_BUILTIN_TEST */

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.452 2008/06/19 01:03:18 drh Exp $
           17  +** $Id: main.c,v 1.453 2008/06/19 18:17:50 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
................................................................................
  1811   1811       ** If no failures are scheduled, return -1.
  1812   1812       */
  1813   1813       case SQLITE_TESTCTRL_FAULT_PENDING: {
  1814   1814         int id = va_arg(ap, int);
  1815   1815         rc = sqlite3FaultPending(id);
  1816   1816         break;
  1817   1817       }
         1818  +
         1819  +    /*
         1820  +    ** sqlite3_test_control(FAULT_INSTALL, isInstall)
         1821  +    **
         1822  +    ** If the argument is non-zero, install the fault-simulation malloc layer
         1823  +    ** as a wrapper around the currently installed implementation.
         1824  +    */
         1825  +    case SQLITE_TESTCTRL_FAULT_INSTALL: {
         1826  +      int isInstall = va_arg(ap, int);
         1827  +      rc = sqlite3FaultsimInstall(isInstall);
         1828  +      break;
         1829  +    }
  1818   1830   
  1819   1831       /*
  1820   1832       ** Save the current state of the PRNG.
  1821   1833       */
  1822   1834       case SQLITE_TESTCTRL_PRNG_SAVE: {
  1823   1835         sqlite3PrngSaveState();
  1824   1836         break;

Changes to src/malloc.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   **
    13     13   ** Memory allocation functions used throughout sqlite.
    14     14   **
    15         -** $Id: malloc.c,v 1.21 2008/06/19 00:16:08 drh Exp $
           15  +** $Id: malloc.c,v 1.22 2008/06/19 18:17:50 danielk1977 Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include <stdarg.h>
    19     19   #include <ctype.h>
    20     20   
    21     21   /*
    22     22   ** This routine runs when the memory allocator sees that the
................................................................................
   209    209     sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
   210    210     if( mem0.alarmCallback!=0 ){
   211    211       int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
   212    212       if( nUsed+nFull >= mem0.alarmThreshold ){
   213    213         sqlite3MallocAlarm(nFull);
   214    214       }
   215    215     }
   216         -  if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
   217         -    p = 0;
   218         -  }else{
          216  +  p = sqlite3Config.m.xMalloc(nFull);
          217  +  if( p==0 && mem0.alarmCallback ){
          218  +    sqlite3MallocAlarm(nFull);
   219    219       p = sqlite3Config.m.xMalloc(nFull);
   220         -    if( p==0 ){
   221         -      sqlite3MallocAlarm(nFull);
   222         -      p = malloc(nFull);
   223         -    }
   224    220     }
   225    221     if( p ) sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
   226    222     *pp = p;
   227    223     return nFull;
   228    224   }
   229    225   
   230    226   /*
................................................................................
   275    271   ** routine is intended to get memory to old large transient data
   276    272   ** structures that would not normally fit on the stack of an
   277    273   ** embedded processor.
   278    274   */
   279    275   void *sqlite3ScratchMalloc(int n){
   280    276     void *p;
   281    277     assert( n>0 );
   282         -  if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
   283         -    return 0;
   284         -  }
   285    278   
   286    279   #if SQLITE_THREADSAFE==0 && !defined(NDEBUG)
   287    280     /* Verify that no more than one scratch allocation per thread
   288    281     ** is outstanding at one time.  (This is only checked in the
   289    282     ** single-threaded case since checking in the multi-threaded case
   290    283     ** would be much more complicated.) */
   291    284     assert( scratchAllocOut==0 );
................................................................................
   373    366   ** consumed.  Otherwise, failover to sqlite3Malloc().
   374    367   */
   375    368   void *sqlite3PageMalloc(int n){
   376    369     void *p;
   377    370     assert( n>0 );
   378    371     assert( (n & (n-1))==0 );
   379    372     assert( n>=512 && n<=32768 );
   380         -  if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
   381         -    return 0;
   382         -  }
   383    373   
   384    374     if( sqlite3Config.szPage<n ){
   385    375       goto page_overflow;
   386    376     }else{  
   387    377       sqlite3_mutex_enter(mem0.mutex);
   388    378       if( mem0.nPageFree==0 ){
   389    379         sqlite3_mutex_leave(mem0.mutex);
................................................................................
   483    473       if( nOld==nNew ){
   484    474         pNew = pOld;
   485    475       }else{
   486    476         if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nNew-nOld >= 
   487    477               mem0.alarmThreshold ){
   488    478           sqlite3MallocAlarm(nNew-nOld);
   489    479         }
   490         -      if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
   491         -        pNew = 0;
   492         -      }else{
          480  +      pNew = sqlite3Config.m.xRealloc(pOld, nNew);
          481  +      if( pNew==0 && mem0.alarmCallback ){
          482  +        sqlite3MallocAlarm(nBytes);
   493    483           pNew = sqlite3Config.m.xRealloc(pOld, nNew);
   494         -        if( pNew==0 ){
   495         -          sqlite3MallocAlarm(nBytes);
   496         -          pNew = sqlite3Config.m.xRealloc(pOld, nNew);
   497         -        }
   498    484         }
   499    485         if( pNew ){
   500    486           sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
   501    487         }
   502    488       }
   503    489       sqlite3_mutex_leave(mem0.mutex);
   504    490     }else{

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.340 2008/06/19 17:54:33 drh Exp $
           33  +** @(#) $Id: sqlite.h.in,v 1.341 2008/06/19 18:17:50 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++.
................................................................................
  6056   6056   #define SQLITE_TESTCTRL_FAULT_FAILURES           2
  6057   6057   #define SQLITE_TESTCTRL_FAULT_BENIGN_FAILURES    3
  6058   6058   #define SQLITE_TESTCTRL_FAULT_PENDING            4
  6059   6059   #define SQLITE_TESTCTRL_PRNG_SAVE                5
  6060   6060   #define SQLITE_TESTCTRL_PRNG_RESTORE             6
  6061   6061   #define SQLITE_TESTCTRL_PRNG_RESET               7
  6062   6062   #define SQLITE_TESTCTRL_BITVEC_TEST              8
         6063  +#define SQLITE_TESTCTRL_FAULT_INSTALL            9
  6063   6064   
  6064   6065   /*
  6065   6066   ** CAPI3REF: SQLite Runtime Status {F17200}
  6066   6067   **
  6067   6068   ** This interface is used to retrieve run-time status information
  6068   6069   ** about the preformance of SQLite, and optionally to reset various
  6069   6070   ** 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.717 2008/06/19 01:03:18 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.718 2008/06/19 18:17:50 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
................................................................................
  2211   2211     void sqlite3FaultConfig(int,int,int);
  2212   2212     int sqlite3FaultFailures(int);
  2213   2213     int sqlite3FaultBenignFailures(int);
  2214   2214     int sqlite3FaultPending(int);
  2215   2215     void sqlite3FaultBeginBenign(int);
  2216   2216     void sqlite3FaultEndBenign(int);
  2217   2217     int sqlite3FaultStep(int);
         2218  +  int sqlite3FaultsimInstall(int);
  2218   2219   #else
  2219   2220   # define sqlite3FaultConfig(A,B,C)
  2220   2221   # define sqlite3FaultFailures(A)         0
  2221   2222   # define sqlite3FaultBenignFailures(A)   0
  2222   2223   # define sqlite3FaultPending(A)          (-1)
  2223   2224   # define sqlite3FaultBeginBenign(A)
  2224   2225   # define sqlite3FaultEndBenign(A)

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.25 2008/06/19 00:16:08 drh Exp $
           16  +** $Id: test_malloc.c,v 1.26 2008/06/19 18:17:50 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  +
           24  +const char *sqlite3TestErrorName(int);
    23     25   
    24     26   /*
    25     27   ** Transform pointers to text and back again
    26     28   */
    27     29   static void pointerToText(void *p, char *z){
    28     30     static const char zHex[] = "0123456789abcdef";
    29     31     int i, k;
................................................................................
   775    777     pResult = Tcl_NewObj();
   776    778     Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
   777    779     Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
   778    780     Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
   779    781     Tcl_SetObjResult(interp, pResult);
   780    782     return TCL_OK;
   781    783   }
          784  +
          785  +/*
          786  +** install_malloc_faultsim BOOLEAN
          787  +*/
          788  +static int test_install_malloc_faultsim(
          789  +  void * clientData,
          790  +  Tcl_Interp *interp,
          791  +  int objc,
          792  +  Tcl_Obj *CONST objv[]
          793  +){
          794  +  int rc;
          795  +  int isInstall;
          796  +
          797  +  if( objc!=2 ){
          798  +    Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
          799  +    return TCL_ERROR;
          800  +  }
          801  +  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
          802  +    return TCL_ERROR;
          803  +  }
          804  +  rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, isInstall);
          805  +  Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
          806  +  return TCL_OK;
          807  +}
   782    808   
   783    809   /*
   784    810   ** Register commands with the TCL interpreter.
   785    811   */
   786    812   int Sqlitetest_malloc_Init(Tcl_Interp *interp){
   787    813     static struct {
   788    814        char *zName;
................................................................................
   801    827        { "sqlite3_memdebug_pending",   test_memdebug_pending         },
   802    828        { "sqlite3_memdebug_settitle",  test_memdebug_settitle        },
   803    829        { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count },
   804    830        { "sqlite3_memdebug_log",       test_memdebug_log             },
   805    831        { "sqlite3_config_scratch",     test_config_scratch           },
   806    832        { "sqlite3_config_pagecache",   test_config_pagecache         },
   807    833        { "sqlite3_status",             test_status                   },
          834  +
          835  +     { "install_malloc_faultsim",    test_install_malloc_faultsim  },
   808    836     };
   809    837     int i;
   810    838     for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
   811    839       Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
   812    840     }
   813    841     return TCL_OK;
   814    842   }

Changes to test/malloc.test.

    12     12   # This file attempts to check the behavior of the SQLite library in 
    13     13   # an out-of-memory situation. When compiled with -DSQLITE_DEBUG=1, 
    14     14   # the SQLite library accepts a special command (sqlite3_memdebug_fail N C)
    15     15   # which causes the N-th malloc to fail.  This special feature is used
    16     16   # to see what happens in the library if a malloc were to really fail
    17     17   # due to an out-of-memory situation.
    18     18   #
    19         -# $Id: malloc.test,v 1.61 2008/04/17 14:16:42 drh Exp $
           19  +# $Id: malloc.test,v 1.62 2008/06/19 18:17:50 danielk1977 Exp $
    20     20   
    21     21   set testdir [file dirname $argv0]
    22     22   source $testdir/tester.tcl
           23  +
    23     24   
    24     25   # Only run these tests if memory debugging is turned on.
    25     26   #
    26     27   source $testdir/malloc_common.tcl
    27     28   if {!$MEMDEBUG} {
    28     29      puts "Skipping malloc tests: not compiled with -DSQLITE_MEMDEBUG..."
    29     30      finish_test

Changes to test/malloc2.test.

    12     12   # This file attempts to check that the library can recover from a malloc()
    13     13   # failure when sqlite3_global_recover() is invoked.
    14     14   #
    15     15   # (Later:) The sqlite3_global_recover() interface is now a no-op.
    16     16   # Recovery from malloc() failures is automatic.  But we keep these
    17     17   # tests around because you can never have too many test cases.
    18     18   #
    19         -# $Id: malloc2.test,v 1.12 2008/02/18 22:24:58 drh Exp $
           19  +# $Id: malloc2.test,v 1.13 2008/06/19 18:17:50 danielk1977 Exp $
    20     20   
    21     21   set testdir [file dirname $argv0]
    22     22   source $testdir/tester.tcl
    23     23   source $testdir/malloc_common.tcl
    24     24   
    25     25   # Only run these tests if memory debugging is turned on.
    26     26   #
................................................................................
    33     33   sqlite3_extended_result_codes db 1
    34     34   
    35     35   proc do_malloc2_test {tn args} {
    36     36     array set ::mallocopts $args
    37     37     set sum [allcksum db]
    38     38     save_prng_state
    39     39   
    40         -  for {set ::n 784} {true} {incr ::n} {
           40  +  for {set ::n 1} {true} {incr ::n} {
    41     41   
    42     42       # Run the SQL. Malloc number $::n is set to fail. A malloc() failure
    43     43       # may or may not be reported.
    44     44       restore_prng_state
    45     45       sqlite3_memdebug_fail $::n -repeat 1
    46     46       do_test malloc2-$tn.$::n.2 {
    47     47         set res [catchsql [string trim $::mallocopts(-sql)]]

Changes to test/malloc_common.tcl.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   #
    12     12   # This file contains common code used by many different malloc tests
    13     13   # within the test suite.
    14     14   #
    15         -# $Id: malloc_common.tcl,v 1.16 2008/03/21 16:45:48 drh Exp $
           15  +# $Id: malloc_common.tcl,v 1.17 2008/06/19 18:17:50 danielk1977 Exp $
    16     16   
    17     17   # If we did not compile with malloc testing enabled, then do nothing.
    18     18   #
    19     19   ifcapable builtin_test {
    20     20     set MEMDEBUG 1
    21     21   } else {
    22     22     set MEMDEBUG 0
    23     23     return 0
    24     24   }
    25     25   
           26  +catch {db close}
           27  +sqlite3_shutdown
           28  +catch {install_malloc_faultsim 1} msg
           29  +sqlite3 db test.db
           30  +
    26     31   # Usage: do_malloc_test <test number> <options...>
    27     32   #
    28     33   # The first argument, <test number>, is an integer used to name the
    29     34   # tests executed by this proc. Options are as follows:
    30     35   #
    31     36   #     -tclprep          TCL script to run to prepare test.
    32     37   #     -sqlprep          SQL script to run to prepare test.