/ Check-in [519bc9d9]
Login

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

Overview
Comment:Rig the sqliteMalloc() routine so that we can make it fail multiple times in a row. Modify the malloc.test procedure to make malloc fail in this way and verify that the failures are still handled correctly. (CVS 2121)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 519bc9d9975bbdb4ba056799534d5c465e0cd042
User & Date: drh 2004-11-20 19:18:01
Context
2004-11-20
19:18
Omit the maximum loop count on the random name chooser in the VACUUM command. Add a comment to explain why this is safe and does not result in an infinite loop. Ticket #1009. (CVS 2122) check-in: 1241086f user: drh tags: trunk
19:18
Rig the sqliteMalloc() routine so that we can make it fail multiple times in a row. Modify the malloc.test procedure to make malloc fail in this way and verify that the failures are still handled correctly. (CVS 2121) check-in: 519bc9d9 user: drh tags: trunk
18:13
Fix segfaults that might occur after a malloc failure. (CVS 2119) check-in: 36877448 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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.340 2004/11/16 15:50:20 danielk1977 Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.341 2004/11/20 19:18:01 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** These #defines should enable >2GB file support on Posix if the
    21     21   ** underlying operating system supports it.  If the OS lacks
................................................................................
   246    246   extern int sqlite3_malloc_failed;
   247    247   
   248    248   /*
   249    249   ** The following global variables are used for testing and debugging
   250    250   ** only.  They only work if SQLITE_DEBUG is defined.
   251    251   */
   252    252   #ifdef SQLITE_DEBUG
   253         -extern int sqlite3_nMalloc;       /* Number of sqliteMalloc() calls */
   254         -extern int sqlite3_nFree;         /* Number of sqliteFree() calls */
   255         -extern int sqlite3_iMallocFail;   /* Fail sqliteMalloc() after this many calls */
          253  +extern int sqlite3_nMalloc;      /* Number of sqliteMalloc() calls */
          254  +extern int sqlite3_nFree;        /* Number of sqliteFree() calls */
          255  +extern int sqlite3_iMallocFail;  /* Fail sqliteMalloc() after this many calls */
          256  +extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */
   256    257   #endif
   257    258   
   258    259   /*
   259    260   ** Name of the master database table.  The master database table
   260    261   ** is a special table that holds the names and attributes of all
   261    262   ** user tables and indices.
   262    263   */

Changes to src/test1.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Code for testing the printf() interface to SQLite.  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: test1.c,v 1.115 2004/11/19 07:07:31 danielk1977 Exp $
           16  +** $Id: test1.c,v 1.116 2004/11/20 19:18:01 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "tcl.h"
    20     20   #include "os.h"
    21     21   #include <stdlib.h>
    22     22   #include <string.h>
    23     23   
................................................................................
   742    742     z = sqlite3_mprintf(argv[1], argv[2]);
   743    743     Tcl_AppendResult(interp, z, 0);
   744    744     sqlite3_free(z);
   745    745     return TCL_OK;
   746    746   }
   747    747   
   748    748   /*
   749         -** Usage: sqlite_malloc_fail N
          749  +** Usage: sqlite_malloc_fail N  ?REPEAT-INTERVAL?
   750    750   **
   751         -** Rig sqliteMalloc() to fail on the N-th call.  Turn off this mechanism
   752         -** and reset the sqlite3_malloc_failed variable is N==0.
          751  +** Rig sqliteMalloc() to fail on the N-th call and every REPEAT-INTERVAL call
          752  +** after that.  If REPEAT-INTERVAL is 0 or is omitted, then only a single
          753  +** malloc will fail.  If REPEAT-INTERVAL is 1 then all mallocs after the
          754  +** first failure will continue to fail on every call.  If REPEAT-INTERVAL is
          755  +** 2 then every other malloc will fail.  And so forth.
          756  +**
          757  +** Turn off this mechanism and reset the sqlite3_malloc_failed variable is N==0.
   753    758   */
   754    759   #ifdef SQLITE_DEBUG
   755    760   static int sqlite_malloc_fail(
   756    761     void *NotUsed,
   757    762     Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
   758    763     int argc,              /* Number of arguments */
   759    764     char **argv            /* Text of each argument */
   760    765   ){
   761    766     int n;
   762         -  if( argc!=2 ){
          767  +  int rep;
          768  +  if( argc!=2 && argc!=3 ){
   763    769       Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
   764    770       return TCL_ERROR;
   765    771     }
   766    772     if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
          773  +  if( argc==3 ){
          774  +    if( Tcl_GetInt(interp, argv[2], &rep) ) return TCL_ERROR;
          775  +  }else{
          776  +    rep = 0;
          777  +  }
   767    778     sqlite3_iMallocFail = n;
          779  +  sqlite3_iMallocReset = rep;
   768    780     sqlite3_malloc_failed = 0;
   769    781     return TCL_OK;
   770    782   }
   771    783   #endif
   772    784   
   773    785   /*
   774    786   ** Usage: sqlite_malloc_stat

Changes to src/util.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Utility functions used throughout sqlite.
    13     13   **
    14     14   ** This file contains functions for allocating memory, comparing
    15     15   ** strings, and stuff like that.
    16     16   **
    17         -** $Id: util.c,v 1.121 2004/11/04 04:34:15 drh Exp $
           17  +** $Id: util.c,v 1.122 2004/11/20 19:18:01 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include <stdarg.h>
    21     21   #include <ctype.h>
    22     22   
    23     23   #if SQLITE_DEBUG>2 && defined(__GLIBC__)
    24     24   #include <execinfo.h>
................................................................................
    47     47   ** If SQLITE_DEBUG is defined, then use versions of malloc() and
    48     48   ** free() that track memory usage and check for buffer overruns.
    49     49   */
    50     50   #ifdef SQLITE_DEBUG
    51     51   
    52     52   /*
    53     53   ** For keeping track of the number of mallocs and frees.   This
    54         -** is used to check for memory leaks.
           54  +** is used to check for memory leaks.  The iMallocFail and iMallocReset
           55  +** values are used to simulate malloc() failures during testing in 
           56  +** order to verify that the library correctly handles an out-of-memory
           57  +** condition.
    55     58   */
    56     59   int sqlite3_nMalloc;         /* Number of sqliteMalloc() calls */
    57     60   int sqlite3_nFree;           /* Number of sqliteFree() calls */
    58     61   int sqlite3_iMallocFail;     /* Fail sqliteMalloc() after this many calls */
           62  +int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */
    59     63   #if SQLITE_DEBUG>1
    60     64   static int memcnt = 0;
    61     65   #endif
    62     66   
    63     67   /*
    64     68   ** Number of 32-bit guard words
    65     69   */
................................................................................
    77     81       sqlite3_iMallocFail--;
    78     82       if( sqlite3_iMallocFail==0 ){
    79     83         sqlite3_malloc_failed++;
    80     84   #if SQLITE_DEBUG>1
    81     85         fprintf(stderr,"**** failed to allocate %d bytes at %s:%d\n",
    82     86                 n, zFile,line);
    83     87   #endif
    84         -      sqlite3_iMallocFail--;
           88  +      sqlite3_iMallocFail = sqlite3_iMallocReset;
    85     89         return 0;
    86     90       }
    87     91     }
    88     92     if( n==0 ) return 0;
    89     93     k = (n+sizeof(int)-1)/sizeof(int);
    90     94     pi = malloc( (N_GUARD*2+1+k)*sizeof(int));
    91     95     if( pi==0 ){

Changes to test/malloc.test.

    10     10   #***********************************************************************
    11     11   # This file attempts to check the library in an out-of-memory situation.
    12     12   # When compiled with -DMEMORY_DEBUG=1, the SQLite library accepts a special
    13     13   # command (sqlite_malloc_fail N) which causes the N-th malloc to fail.  This
    14     14   # special feature is used to see what happens in the library if a malloc
    15     15   # were to really fail due to an out-of-memory situation.
    16     16   #
    17         -# $Id: malloc.test,v 1.10 2004/06/30 09:49:24 danielk1977 Exp $
           17  +# $Id: malloc.test,v 1.11 2004/11/20 19:18:01 drh Exp $
    18     18   
    19     19   set testdir [file dirname $argv0]
    20     20   source $testdir/tester.tcl
    21     21   
    22     22   # Only run these tests if memory debugging is turned on.
    23     23   #
    24     24   if {[info command sqlite_malloc_stat]==""} {
................................................................................
    29     29   
    30     30   for {set go 1; set i 1} {$go} {incr i} {
    31     31     do_test malloc-1.$i {
    32     32        sqlite_malloc_fail 0
    33     33        catch {db close}
    34     34        catch {file delete -force test.db}
    35     35        catch {file delete -force test.db-journal}
    36         -     sqlite_malloc_fail $i
           36  +     sqlite_malloc_fail $i [expr {$i%4}]
    37     37        set v [catch {sqlite3 db test.db} msg]
    38     38        if {$v} {
    39     39          set msg ""
    40     40        } else {
    41     41          set v [catch {execsql {
    42     42             CREATE TABLE t1(
    43     43                a int, b float, c double, d text, e varchar(20),