/ Check-in [2c57b2f3]
Login

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

Overview
Comment:Disable the SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS mechanism and replace it with SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL, which gives better control.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | malloc-testing
Files: files | file ages | folders
SHA1: 2c57b2f38691356405b95245fc22fd5e6bfcb2f1
User & Date: drh 2015-09-25 16:29:49
Context
2015-09-25
20:18
Fix a faulty assert() on the benign-malloc controller callback in test_malloc.c. Leaf check-in: 64f2cb8d user: drh tags: malloc-testing
16:29
Disable the SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS mechanism and replace it with SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL, which gives better control. check-in: 2c57b2f3 user: drh tags: malloc-testing
13:42
Report an error if the number of named columns in a VIEW is different from the number of result columns in the SELECT statement that implements the VIEW. check-in: 6e4ac0be user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/fault.c.

    25     25   */
    26     26   
    27     27   #include "sqliteInt.h"
    28     28   
    29     29   #ifndef SQLITE_OMIT_BUILTIN_TEST
    30     30   
    31     31   /*
    32         -** Global variables.
           32  +** The default xBenignCtrl function is a no-op
           33  +*/
           34  +static void sqlite3BenignCtrlNoop(int eOp){
           35  +  (void)eOp;
           36  +}
           37  +
           38  +/*
           39  +** Global variable:  Pointer to the benign malloc control interface.
    33     40   */
    34         -typedef struct BenignMallocHooks BenignMallocHooks;
    35         -static SQLITE_WSD struct BenignMallocHooks {
    36         -  void (*xBenignBegin)(void);
    37         -  void (*xBenignEnd)(void);
    38         -} sqlite3Hooks = { 0, 0 };
           41  +static void (*sqlite3xBenignCtrl)(int) = sqlite3BenignCtrlNoop;
    39     42   
    40         -/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
    41         -** structure.  If writable static data is unsupported on the target,
    42         -** we have to locate the state vector at run-time.  In the more common
    43         -** case where writable static data is supported, wsdHooks can refer directly
    44         -** to the "sqlite3Hooks" state vector declared above.
           43  +/*
           44  +** Register a pointer to the benign-malloc control interface function.
           45  +** If the argument is a NULL pointer, register the default no-op controller.
    45     46   */
    46         -#ifdef SQLITE_OMIT_WSD
    47         -# define wsdHooksInit \
    48         -  BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
    49         -# define wsdHooks x[0]
    50         -#else
    51         -# define wsdHooksInit
    52         -# define wsdHooks sqlite3Hooks
    53         -#endif
    54         -
           47  +void sqlite3BenignMallocHooks(void (*xBenignCtrl)(int)){
           48  +  sqlite3xBenignCtrl = xBenignCtrl ? xBenignCtrl : sqlite3BenignCtrlNoop;
           49  +}
    55     50   
    56     51   /*
    57         -** Register hooks to call when sqlite3BeginBenignMalloc() and
    58         -** sqlite3EndBenignMalloc() are called, respectively.
           52  +** The sqlite3BeginBenignMalloc() and sqlite3EndBenignMalloc() calls bracket
           53  +** sections of code for which malloc failures are non-fatal.  
    59     54   */
    60         -void sqlite3BenignMallocHooks(
    61         -  void (*xBenignBegin)(void),
    62         -  void (*xBenignEnd)(void)
    63         -){
    64         -  wsdHooksInit;
    65         -  wsdHooks.xBenignBegin = xBenignBegin;
    66         -  wsdHooks.xBenignEnd = xBenignEnd;
           55  +void sqlite3BeginBenignMalloc(void){
           56  +  sqlite3xBenignCtrl(1);
           57  +}
           58  +void sqlite3EndBenignMalloc(void){
           59  +  sqlite3xBenignCtrl(0);
    67     60   }
    68     61   
    69     62   /*
    70         -** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
    71         -** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
    72         -** indicates that subsequent malloc failures are non-benign.
           63  +** The sqlite3PreviousBenignMalloc() call indicates that the previous
           64  +** malloc call (which must have failed) was a benign failure.
    73     65   */
    74         -void sqlite3BeginBenignMalloc(void){
    75         -  wsdHooksInit;
    76         -  if( wsdHooks.xBenignBegin ){
    77         -    wsdHooks.xBenignBegin();
    78         -  }
    79         -}
    80         -void sqlite3EndBenignMalloc(void){
    81         -  wsdHooksInit;
    82         -  if( wsdHooks.xBenignEnd ){
    83         -    wsdHooks.xBenignEnd();
    84         -  }
           66  +void sqlite3PreviousBenignMalloc(void){
           67  +  sqlite3xBenignCtrl(2);
    85     68   }
    86     69   
    87     70   #endif   /* #ifndef SQLITE_OMIT_BUILTIN_TEST */

Changes to src/hash.c.

   114    114     ** a performance hit but it is not a fatal error.  So mark the
   115    115     ** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of 
   116    116     ** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
   117    117     ** only zeroes the requested number of bytes whereas this module will
   118    118     ** use the actual amount of space allocated for the hash table (which
   119    119     ** may be larger than the requested amount).
   120    120     */
   121         -  sqlite3BeginBenignMalloc();
   122    121     new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
   123         -  sqlite3EndBenignMalloc();
   124         -
   125         -  if( new_ht==0 ) return 0;
          122  +  if( new_ht==0 ){
          123  +    sqlite3PreviousBenignMalloc();
          124  +    return 0;
          125  +  }
   126    126     sqlite3_free(pH->ht);
   127    127     pH->ht = new_ht;
   128    128     pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
   129    129     memset(new_ht, 0, new_size*sizeof(struct _ht));
   130    130     for(elem=pH->first, pH->first=0; elem; elem = next_elem){
   131    131       unsigned int h = strHash(elem->pKey) % new_size;
   132    132       next_elem = elem->next;

Changes to src/main.c.

   660    660     sz = ROUNDDOWN8(sz);  /* IMP: R-33038-09382 */
   661    661     if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0;
   662    662     if( cnt<0 ) cnt = 0;
   663    663     if( sz==0 || cnt==0 ){
   664    664       sz = 0;
   665    665       pStart = 0;
   666    666     }else if( pBuf==0 ){
   667         -    sqlite3BeginBenignMalloc();
   668    667       pStart = sqlite3Malloc( sz*cnt );  /* IMP: R-61949-35727 */
   669         -    sqlite3EndBenignMalloc();
   670         -    if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
          668  +    if( pStart==0 ){
          669  +      sqlite3PreviousBenignMalloc();
          670  +    }else{
          671  +      cnt = sqlite3MallocSize(pStart)/sz;
          672  +    }
   671    673     }else{
   672    674       pStart = pBuf;
   673    675     }
   674    676     db->lookaside.pStart = pStart;
   675    677     db->lookaside.pFree = 0;
   676    678     db->lookaside.sz = (u16)sz;
   677    679     if( pStart ){
................................................................................
  3436   3438         typedef int(*TESTCALLBACKFUNC_t)(int);
  3437   3439         sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
  3438   3440         rc = sqlite3FaultSim(0);
  3439   3441         break;
  3440   3442       }
  3441   3443   
  3442   3444       /*
  3443         -    **  sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
         3445  +    **  sqlite3_test_control(BENIGN_MALLOC_CTRL, xCtrl)
  3444   3446       **
  3445         -    ** Register hooks to call to indicate which malloc() failures 
  3446         -    ** are benign.
         3447  +    ** Register a callback function that will handle calls to
         3448  +    ** sqlite3BeginBenignMalloc(), sqlite3EndBenignMalloc(), and
         3449  +    ** sqlite3PreviousBenignMalloc().  If the callback function pointer
         3450  +    ** is NULL, then a built-in default (no-op) handler is used.
  3447   3451       */
  3448         -    case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: {
  3449         -      typedef void (*void_function)(void);
  3450         -      void_function xBenignBegin;
  3451         -      void_function xBenignEnd;
  3452         -      xBenignBegin = va_arg(ap, void_function);
  3453         -      xBenignEnd = va_arg(ap, void_function);
  3454         -      sqlite3BenignMallocHooks(xBenignBegin, xBenignEnd);
         3452  +    case SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL: {
         3453  +      typedef void (*void_function)(int);
         3454  +      void_function xBenignCtrl;
         3455  +      xBenignCtrl = va_arg(ap, void_function);
         3456  +      sqlite3BenignMallocHooks(xBenignCtrl);
  3455   3457         break;
  3456   3458       }
  3457   3459   
  3458   3460       /*
  3459   3461       **  sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, unsigned int X)
  3460   3462       **
  3461   3463       ** Set the PENDING byte to the value in the argument, if X>0.

Changes to src/malloc.c.

   522    522       nDiff = nNew - nOld;
   523    523       if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED) >= 
   524    524             mem0.alarmThreshold-nDiff ){
   525    525         sqlite3MallocAlarm(nDiff);
   526    526       }
   527    527       pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
   528    528       if( pNew==0 && mem0.alarmThreshold>0 ){
          529  +      sqlite3PreviousBenignMalloc();
   529    530         sqlite3MallocAlarm((int)nBytes);
   530    531         pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
   531    532       }
   532    533       if( pNew ){
   533    534         nNew = sqlite3MallocSize(pNew);
   534    535         sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
   535    536       }

Changes to src/pcache1.c.

   268    268   */
   269    269   static int pcache1InitBulk(PCache1 *pCache){
   270    270     i64 szBulk;
   271    271     char *zBulk;
   272    272     if( pcache1.nInitPage==0 ) return 0;
   273    273     /* Do not bother with a bulk allocation if the cache size very small */
   274    274     if( pCache->nMax<3 ) return 0;
   275         -  sqlite3BeginBenignMalloc();
   276    275     if( pcache1.nInitPage>0 ){
   277    276       szBulk = pCache->szAlloc * (i64)pcache1.nInitPage;
   278    277     }else{
   279    278       szBulk = -1024 * (i64)pcache1.nInitPage;
   280    279     }
   281    280     if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
   282    281       szBulk = pCache->szAlloc*pCache->nMax;
   283    282     }
   284    283     zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
   285         -  sqlite3EndBenignMalloc();
   286         -  if( zBulk ){
          284  +  if( zBulk==0 ){
          285  +    sqlite3PreviousBenignMalloc();
          286  +  }else{
   287    287       int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
   288    288       int i;
   289    289       for(i=0; i<nBulk; i++){
   290    290         PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
   291    291         pX->page.pBuf = zBulk;
   292    292         pX->page.pExtra = &pX[1];
   293    293         pX->isBulkLocal = 1;

Changes to src/shell.c.

  3795   3795          int ctrlCode;            /* Integer code for that option */
  3796   3796       } aCtrl[] = {
  3797   3797         { "prng_save",             SQLITE_TESTCTRL_PRNG_SAVE              },
  3798   3798         { "prng_restore",          SQLITE_TESTCTRL_PRNG_RESTORE           },
  3799   3799         { "prng_reset",            SQLITE_TESTCTRL_PRNG_RESET             },
  3800   3800         { "bitvec_test",           SQLITE_TESTCTRL_BITVEC_TEST            },
  3801   3801         { "fault_install",         SQLITE_TESTCTRL_FAULT_INSTALL          },
  3802         -      { "benign_malloc_hooks",   SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS    },
  3803   3802         { "pending_byte",          SQLITE_TESTCTRL_PENDING_BYTE           },
  3804   3803         { "assert",                SQLITE_TESTCTRL_ASSERT                 },
  3805   3804         { "always",                SQLITE_TESTCTRL_ALWAYS                 },
  3806   3805         { "reserve",               SQLITE_TESTCTRL_RESERVE                },
  3807   3806         { "optimizations",         SQLITE_TESTCTRL_OPTIMIZATIONS          },
  3808   3807         { "iskeyword",             SQLITE_TESTCTRL_ISKEYWORD              },
  3809   3808         { "scratchmalloc",         SQLITE_TESTCTRL_SCRATCHMALLOC          },
................................................................................
  3910   3909                             integerValue(azArg[4]));
  3911   3910               fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
  3912   3911             }else{
  3913   3912               fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
  3914   3913             }
  3915   3914             break;
  3916   3915   
  3917         -        case SQLITE_TESTCTRL_BITVEC_TEST:         
  3918         -        case SQLITE_TESTCTRL_FAULT_INSTALL:       
  3919         -        case SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS: 
  3920         -        case SQLITE_TESTCTRL_SCRATCHMALLOC:       
  3921   3916           default:
  3922   3917             fprintf(stderr,"Error: CLI support for testctrl %s not implemented\n",
  3923   3918                     azArg[1]);
  3924   3919             break;
  3925   3920         }
  3926   3921       }
  3927   3922     }else

Changes to src/sqlite.h.in.

  6414   6414   */
  6415   6415   #define SQLITE_TESTCTRL_FIRST                    5
  6416   6416   #define SQLITE_TESTCTRL_PRNG_SAVE                5
  6417   6417   #define SQLITE_TESTCTRL_PRNG_RESTORE             6
  6418   6418   #define SQLITE_TESTCTRL_PRNG_RESET               7
  6419   6419   #define SQLITE_TESTCTRL_BITVEC_TEST              8
  6420   6420   #define SQLITE_TESTCTRL_FAULT_INSTALL            9
  6421         -#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10
         6421  +#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10  /* NOT USED */
  6422   6422   #define SQLITE_TESTCTRL_PENDING_BYTE            11
  6423   6423   #define SQLITE_TESTCTRL_ASSERT                  12
  6424   6424   #define SQLITE_TESTCTRL_ALWAYS                  13
  6425   6425   #define SQLITE_TESTCTRL_RESERVE                 14
  6426   6426   #define SQLITE_TESTCTRL_OPTIMIZATIONS           15
  6427   6427   #define SQLITE_TESTCTRL_ISKEYWORD               16
  6428   6428   #define SQLITE_TESTCTRL_SCRATCHMALLOC           17
................................................................................
  6430   6430   #define SQLITE_TESTCTRL_EXPLAIN_STMT            19  /* NOT USED */
  6431   6431   #define SQLITE_TESTCTRL_NEVER_CORRUPT           20
  6432   6432   #define SQLITE_TESTCTRL_VDBE_COVERAGE           21
  6433   6433   #define SQLITE_TESTCTRL_BYTEORDER               22
  6434   6434   #define SQLITE_TESTCTRL_ISINIT                  23
  6435   6435   #define SQLITE_TESTCTRL_SORTER_MMAP             24
  6436   6436   #define SQLITE_TESTCTRL_IMPOSTER                25
  6437         -#define SQLITE_TESTCTRL_LAST                    25
         6437  +#define SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL      26
         6438  +#define SQLITE_TESTCTRL_LAST                    26
  6438   6439   
  6439   6440   /*
  6440   6441   ** CAPI3REF: SQLite Runtime Status
  6441   6442   **
  6442   6443   ** ^These interfaces are used to retrieve runtime status information
  6443   6444   ** about the performance of SQLite, and optionally to reset various
  6444   6445   ** highwater marks.  ^The first argument is an integer code for

Changes to src/sqliteInt.h.

  3152   3152   int sqlite3DbMallocSize(sqlite3*, void*);
  3153   3153   void *sqlite3ScratchMalloc(int);
  3154   3154   void sqlite3ScratchFree(void*);
  3155   3155   void *sqlite3PageMalloc(int);
  3156   3156   void sqlite3PageFree(void*);
  3157   3157   void sqlite3MemSetDefault(void);
  3158   3158   #ifndef SQLITE_OMIT_BUILTIN_TEST
  3159         -void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
         3159  +void sqlite3BenignMallocHooks(void (*)(int));
  3160   3160   #endif
  3161   3161   int sqlite3HeapNearlyFull(void);
  3162   3162   
  3163   3163   /*
  3164   3164   ** On systems with ample stack space and that support alloca(), make
  3165   3165   ** use of alloca() to obtain space for large automatic objects.  By default,
  3166   3166   ** obtain space from malloc().
................................................................................
  3832   3832   ** The interface to the code in fault.c used for identifying "benign"
  3833   3833   ** malloc failures. This is only present if SQLITE_OMIT_BUILTIN_TEST
  3834   3834   ** is not defined.
  3835   3835   */
  3836   3836   #ifndef SQLITE_OMIT_BUILTIN_TEST
  3837   3837     void sqlite3BeginBenignMalloc(void);
  3838   3838     void sqlite3EndBenignMalloc(void);
         3839  +  void sqlite3PreviousBenignMalloc(void);
  3839   3840   #else
  3840   3841     #define sqlite3BeginBenignMalloc()
  3841   3842     #define sqlite3EndBenignMalloc()
         3843  +  #define sqlite3PreviousBenignMalloc()
  3842   3844   #endif
  3843   3845   
  3844   3846   /*
  3845   3847   ** Allowed return values from sqlite3FindInIndex()
  3846   3848   */
  3847   3849   #define IN_INDEX_ROWID        1   /* Search the rowid of the table */
  3848   3850   #define IN_INDEX_EPH          2   /* Search an ephemeral b-tree */

Changes to src/test_malloc.c.

   165    165     if( memfault.enable ){
   166    166       return memfault.iCountdown;
   167    167     }else{
   168    168       return -1;
   169    169     }
   170    170   }
   171    171   
   172         -
   173         -static void faultsimBeginBenign(void){
   174         -  memfault.isBenignMode++;
   175         -}
   176         -static void faultsimEndBenign(void){
   177         -  memfault.isBenignMode--;
          172  +/*
          173  +** The SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL callback.  The eOp argument means:
          174  +**
          175  +**     0:      Leave benign malloc mode
          176  +**     1:      Enter benign malloc mode (may be nested)
          177  +**     2:      Make the previous malloc failure benign if it was not already so
          178  +*/
          179  +static void faultsimBenignCtrl(int eOp){
          180  +  switch( eOp ){
          181  +    case 0:    /* Leave benign malloc mode */
          182  +      assert( memfault.isBenignMode>0 );
          183  +      memfault.isBenignMode--;
          184  +      break;
          185  +    case 1:    /* Enter benign malloc mode */
          186  +      memfault.isBenignMode++;
          187  +      break;
          188  +    case 2:    /* Previous failure is benign */
          189  +      assert( memfault.nFail>0 );
          190  +      if( memfault.isBenignMode==0 ) memfault.nBenign++;
          191  +      break;
          192  +  }
   178    193   }
   179    194   
   180    195   /*
   181    196   ** Add or remove the fault-simulation layer using sqlite3_config(). If
   182    197   ** the argument is non-zero, the 
   183    198   */
   184    199   static int faultsimInstall(int install){
................................................................................
   203    218   
   204    219     if( install ){
   205    220       rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
   206    221       assert(memfault.m.xMalloc);
   207    222       if( rc==SQLITE_OK ){
   208    223         rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
   209    224       }
   210         -    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 
   211         -        faultsimBeginBenign, faultsimEndBenign
   212         -    );
          225  +    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL, 
          226  +                        faultsimBenignCtrl);
   213    227     }else{
   214    228       sqlite3_mem_methods m2;
   215    229       assert(memfault.m.xMalloc);
   216    230   
   217    231       /* One should be able to reset the default memory allocator by storing
   218    232       ** a zeroed allocator then calling GETMALLOC. */
   219    233       memset(&m2, 0, sizeof(m2));
   220    234       sqlite3_config(SQLITE_CONFIG_MALLOC, &m2);
   221    235       sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2);
   222    236       assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );
   223    237   
   224    238       rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
   225         -    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0);
          239  +    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_CTRL, 0);
   226    240     }
   227    241   
   228    242     if( rc==SQLITE_OK ){
   229    243       memfault.isInstalled = 1;
   230    244     }
   231    245     return rc;
   232    246   }