Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Move (almost all) malloc failure test logic from fault.c to test_malloc.c. (CVS 5253) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
4ae21e3419ad7e69dd735ca45fdc5a2d |
User & Date: | danielk1977 2008-06-20 11:05:38.000 |
Context
2008-06-20
| ||
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: 56c8af1452 user: danielk1977 tags: trunk) | |
11:05 | Move (almost all) malloc failure test logic from fault.c to test_malloc.c. (CVS 5253) (check-in: 4ae21e3419 user: danielk1977 tags: trunk) | |
00:03 | Patch to memsubsys1.test in order to avoid a segfault in tableapi.test. (CVS 5252) (check-in: 62411a6e60 user: drh tags: trunk) | |
Changes
Changes to src/fault.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2008 Jan 22 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* | < < < < < < > | < < < < < < < < | > < < < < < < < < < < < < < | < < < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < | < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < | < < < < < < < < | < < < < < < < | < < < | < | < < | | < | | < < | | < < < < < < < < | | < < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /* ** 2008 Jan 22 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code to support the concept of "benign" ** malloc failures. ** ** $Id: fault.c,v 1.8 2008/06/20 11:05:38 danielk1977 Exp $ */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_BUILTIN_TEST /* ** If zero, malloc() failures are non-benign. If non-zero, benign. */ static int memfault_is_benign = 0; /* ** Return true if a malloc failures are currently considered to be ** benign. A benign fault does not affect the operation of sqlite. ** By constrast a non-benign fault causes sqlite to fail the current ** operation and return SQLITE_NOMEM to the user. */ int sqlite3FaultIsBenign(void){ return memfault_is_benign; } /* ** After this routine causes subsequent malloc faults to be either ** benign or hard (not benign), according to the "enable" parameter. ** ** Most faults are hard. In other words, most faults cause ** an error to be propagated back up to the application interface. ** However, sometimes a fault is easily recoverable. For example, ** if a malloc fails while resizing a hash table, this is completely ** recoverable simply by not carrying out the resize. The hash table ** will continue to function normally. So a malloc failure during ** a hash table resize is a benign fault. */ void sqlite3FaultBeginBenign(int id){ memfault_is_benign++; } void sqlite3FaultEndBenign(int id){ memfault_is_benign--; } #endif /* #ifndef SQLITE_OMIT_BUILTIN_TEST */ |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.454 2008/06/20 11:05:38 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> #ifdef SQLITE_ENABLE_FTS3 # include "fts3.h" #endif |
︙ | ︙ | |||
1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 | */ int sqlite3_test_control(int op, ...){ int rc = 0; #ifndef SQLITE_OMIT_BUILTIN_TEST va_list ap; va_start(ap, op); switch( op ){ /* ** sqlite3_test_control(FAULT_CONFIG, fault_id, nDelay, nRepeat) ** ** Configure a fault injector. The specific fault injector is ** identified by the fault_id argument. (ex: SQLITE_FAULTINJECTOR_MALLOC) ** The fault will occur after a delay of nDelay calls. The fault ** will repeat nRepeat times. | > | 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 | */ int sqlite3_test_control(int op, ...){ int rc = 0; #ifndef SQLITE_OMIT_BUILTIN_TEST va_list ap; va_start(ap, op); switch( op ){ #if 0 /* ** sqlite3_test_control(FAULT_CONFIG, fault_id, nDelay, nRepeat) ** ** Configure a fault injector. The specific fault injector is ** identified by the fault_id argument. (ex: SQLITE_FAULTINJECTOR_MALLOC) ** The fault will occur after a delay of nDelay calls. The fault ** will repeat nRepeat times. |
︙ | ︙ | |||
1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 | ** as a wrapper around the currently installed implementation. */ case SQLITE_TESTCTRL_FAULT_INSTALL: { int isInstall = va_arg(ap, int); rc = sqlite3FaultsimInstall(isInstall); break; } /* ** Save the current state of the PRNG. */ case SQLITE_TESTCTRL_PRNG_SAVE: { sqlite3PrngSaveState(); break; | > | 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 | ** as a wrapper around the currently installed implementation. */ case SQLITE_TESTCTRL_FAULT_INSTALL: { int isInstall = va_arg(ap, int); rc = sqlite3FaultsimInstall(isInstall); break; } #endif /* ** Save the current state of the PRNG. */ case SQLITE_TESTCTRL_PRNG_SAVE: { sqlite3PrngSaveState(); break; |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.719 2008/06/20 11:05:38 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build |
︙ | ︙ | |||
2199 2200 2201 2202 2203 2204 2205 | /* ** Available fault injectors. Should be numbered beginning with 0. */ #define SQLITE_FAULTINJECTOR_MALLOC 0 #define SQLITE_FAULTINJECTOR_COUNT 1 /* | | | | < < < < | < < < < < | | < < < | 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 | /* ** Available fault injectors. Should be numbered beginning with 0. */ #define SQLITE_FAULTINJECTOR_MALLOC 0 #define SQLITE_FAULTINJECTOR_COUNT 1 /* ** The interface to the code in fault.c used for identifying "benign" ** malloc failures. This is only present if SQLITE_OMIT_BUILTIN_TEST ** is not defined. */ #ifndef SQLITE_OMIT_BUILTIN_TEST void sqlite3FaultBeginBenign(int); void sqlite3FaultEndBenign(int); int sqlite3FaultIsBenign(void); #else #define sqlite3FaultBeginBenign() #define sqlite3FaultEndBenign() #endif #define IN_INDEX_ROWID 1 #define IN_INDEX_EPH 2 #define IN_INDEX_INDEX 3 int sqlite3FindInIndex(Parse *, Expr *, int); #ifdef SQLITE_ENABLE_ATOMIC_WRITE |
︙ | ︙ |
Changes to src/test_malloc.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement test interfaces to the ** memory allocation subsystem. ** | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains code used to implement test interfaces to the ** memory allocation subsystem. ** ** $Id: test_malloc.c,v 1.27 2008/06/20 11:05:38 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> #include <assert.h> /* ** This structure is used to encapsulate the global state variables used ** by malloc() fault simulation. */ static struct MemFault { int iCountdown; /* Number of pending successes before a failure */ int nRepeat; /* Number of times to repeat the failure */ int nBenign; /* Number of benign failures seen since last config */ int nFail; /* Number of failures seen since last config */ u8 enable; /* True if enabled */ int isInstalled; /* True if the fault simulation layer is installed */ sqlite3_mem_methods m; /* 'Real' malloc implementation */ } memfault; /* ** This routine exists as a place to set a breakpoint that will ** fire on any simulated malloc() failure. */ static void sqlite3Fault(void){ static int cnt = 0; cnt++; } /* ** Check to see if a fault should be simulated. Return true to simulate ** the fault. Return false if the fault should not be simulated. */ static int faultsimStep(){ if( likely(!memfault.enable) ){ return 0; } if( memfault.iCountdown>0 ){ memfault.iCountdown--; return 0; } sqlite3Fault(); memfault.nFail++; if( sqlite3FaultIsBenign()>0 ){ memfault.nBenign++; } memfault.nRepeat--; if( memfault.nRepeat<=0 ){ memfault.enable = 0; } return 1; } /* ** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation ** logic. */ static void *faultsimMalloc(int n){ void *p = 0; if( !faultsimStep() ){ p = memfault.m.xMalloc(n); } return p; } /* ** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation ** logic. */ static void *faultsimRealloc(void *pOld, int n){ void *p = 0; if( !faultsimStep() ){ p = memfault.m.xRealloc(pOld, n); } return p; } /* ** The following method calls are passed directly through to the underlying ** malloc system: ** ** xFree ** xSize ** xRoundup ** xInit ** xShutdown */ static void faultsimFree(void *p){ memfault.m.xFree(p); } static int faultsimSize(void *p){ return memfault.m.xSize(p); } static int faultsimRoundup(int n){ return memfault.m.xRoundup(n); } static int faultsimInit(void *p){ return memfault.m.xInit(memfault.m.pAppData); } static void faultsimShutdown(void *p){ memfault.m.xShutdown(memfault.m.pAppData); } /* ** This routine configures the malloc failure simulation. After ** calling this routine, the next nDelay mallocs will succeed, followed ** by a block of nRepeat failures, after which malloc() calls will begin ** to succeed again. */ static void faultsimConfig(int nDelay, int nRepeat){ memfault.iCountdown = nDelay; memfault.nRepeat = nRepeat; memfault.nBenign = 0; memfault.nFail = 0; memfault.enable = nDelay>=0; } /* ** Return the number of faults (both hard and benign faults) that have ** occurred since the injector was last configured. */ static int faultsimFailures(void){ return memfault.nFail; } /* ** Return the number of benign faults that have occurred since the ** injector was last configured. */ static int faultsimBenignFailures(void){ return memfault.nBenign; } /* ** Return the number of successes that will occur before the next failure. ** If no failures are scheduled, return -1. */ static int faultsimPending(void){ if( memfault.enable ){ return memfault.iCountdown; }else{ return -1; } } /* ** Add or remove the fault-simulation layer using sqlite3_config(). If ** the argument is non-zero, the */ static int faultsimInstall(int install){ static struct sqlite3_mem_methods m = { faultsimMalloc, /* xMalloc */ faultsimFree, /* xFree */ faultsimRealloc, /* xRealloc */ faultsimSize, /* xSize */ faultsimRoundup, /* xRoundup */ faultsimInit, /* xInit */ faultsimShutdown, /* xShutdown */ 0 /* pAppData */ }; int rc; install = (install ? 1 : 0); assert(memfault.isInstalled==1 || memfault.isInstalled==0); if( install==memfault.isInstalled ){ return SQLITE_ERROR; } rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m); assert(memfault.m.xMalloc); if( rc==SQLITE_OK ){ rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m); } if( rc==SQLITE_OK ){ memfault.isInstalled = 1; } return rc; } #ifdef SQLITE_TEST /* ** This function is implemented in test1.c. Returns a pointer to a static ** buffer containing the symbolic SQLite error code that corresponds to ** the least-significant 8-bits of the integer passed as an argument. ** For example: ** ** sqlite3TestErrorName(1) -> "SQLITE_ERROR" */ const char *sqlite3TestErrorName(int); /* ** Transform pointers to text and back again */ static void pointerToText(void *p, char *z){ static const char zHex[] = "0123456789abcdef"; |
︙ | ︙ | |||
125 126 127 128 129 130 131 | return TCL_ERROR; } p = sqlite3_realloc(pPrior, (unsigned)nByte); pointerToText(p, zOut); Tcl_AppendResult(interp, zOut, NULL); return TCL_OK; } | < | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | return TCL_ERROR; } p = sqlite3_realloc(pPrior, (unsigned)nByte); pointerToText(p, zOut); Tcl_AppendResult(interp, zOut, NULL); return TCL_OK; } /* ** Usage: sqlite3_free PRIOR ** ** Raw test interface for sqlite3_free(). */ static int test_free( |
︙ | ︙ | |||
435 436 437 438 439 440 441 | if( zErr ){ Tcl_AppendResult(interp, zErr, zOption, 0); return TCL_ERROR; } } | < | < | < < | > | 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 | if( zErr ){ Tcl_AppendResult(interp, zErr, zOption, 0); return TCL_ERROR; } } nBenign = faultsimBenignFailures(); nFail = faultsimFailures(); faultsimConfig(iFail, nRepeat); if( pBenignCnt ){ Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0); } Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail)); return TCL_OK; } |
︙ | ︙ | |||
467 468 469 470 471 472 473 | Tcl_Obj *CONST objv[] ){ int nPending; if( objc!=1 ){ Tcl_WrongNumArgs(interp, 1, objv, ""); return TCL_ERROR; } | | < | 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 | Tcl_Obj *CONST objv[] ){ int nPending; if( objc!=1 ){ Tcl_WrongNumArgs(interp, 1, objv, ""); return TCL_ERROR; } nPending = faultsimPending(); Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending)); return TCL_OK; } /* ** Usage: sqlite3_memdebug_settitle TITLE |
︙ | ︙ | |||
797 798 799 800 801 802 803 | if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); return TCL_ERROR; } if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){ return TCL_ERROR; } | | | 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 | if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN"); return TCL_ERROR; } if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){ return TCL_ERROR; } rc = faultsimInstall(isInstall); Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); return TCL_OK; } /* ** Register commands with the TCL interpreter. */ |
︙ | ︙ | |||
836 837 838 839 840 841 842 | }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); } return TCL_OK; } | > | 1017 1018 1019 1020 1021 1022 1023 1024 | }; int i; for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0); } return TCL_OK; } #endif |