]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the fault injector module in fault.c. Use it as a basis for memory
authordrh <drh@noemail.net>
Tue, 22 Jan 2008 21:30:53 +0000 (21:30 +0000)
committerdrh <drh@noemail.net>
Tue, 22 Jan 2008 21:30:53 +0000 (21:30 +0000)
allocation failure testing. (CVS 4742)

FossilOrigin-Name: 1a335e180183b414fcc3510ce28b98b21cd134a6

20 files changed:
Makefile.in
main.mk
manifest
manifest.uuid
src/fault.c [new file with mode: 0644]
src/hash.c
src/main.c
src/mem2.c
src/pager.c
src/sqliteInt.h
src/test1.c
src/test8.c
src/test_config.c
src/test_malloc.c
src/vdbe.c
src/vdbeInt.h
src/vdbeapi.c
src/vdbemem.c
test/malloc_common.tcl
tool/mksqlite3c.tcl

index 9076de78a3b8181a9006a75f1bee8832899f6214..6e01c4c26948a30dbb4fc70452d3b0894f80d3f7 100644 (file)
@@ -122,7 +122,8 @@ TCC += -DSQLITE_OMIT_LOAD_EXTENSION=1
 #
 LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btmutex.lo btree.lo build.lo \
          callback.lo complete.lo date.lo \
-         delete.lo expr.lo func.lo hash.lo journal.lo insert.lo loadext.lo \
+         delete.lo expr.lo fault.lo func.lo \
+         hash.lo journal.lo insert.lo loadext.lo \
          main.lo malloc.lo mem1.lo mem2.lo mem3.lo mem4.lo mutex.lo \
          mutex_os2.lo mutex_unix.lo mutex_w32.lo \
          opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \
@@ -148,6 +149,7 @@ SRC = \
   $(TOP)/src/date.c \
   $(TOP)/src/delete.c \
   $(TOP)/src/expr.c \
+  $(TOP)/src/fault.c \
   $(TOP)/src/func.c \
   $(TOP)/src/hash.c \
   $(TOP)/src/hash.h \
@@ -230,6 +232,7 @@ TESTSRC = \
   $(TOP)/src/pragma.c \
   $(TOP)/src/prepare.c \
   $(TOP)/src/printf.c \
+  $(TOP)/src/random.c \
   $(TOP)/src/select.c \
   $(TOP)/src/test1.c \
   $(TOP)/src/test2.c \
@@ -384,6 +387,9 @@ delete.lo:  $(TOP)/src/delete.c $(HDR)
 expr.lo:       $(TOP)/src/expr.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/expr.c
 
+fault.lo:      $(TOP)/src/fault.c $(HDR)
+       $(LTCOMPILE) -c $(TOP)/src/fault.c
+
 func.lo:       $(TOP)/src/func.c $(HDR)
        $(LTCOMPILE) -c $(TOP)/src/func.c
 
diff --git a/main.mk b/main.mk
index db0807d7f9bd41319f2dc557a55e663b2b092ead..5b1fe537287d33a403f74ae94c24b4ba0c6e5625 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -50,7 +50,7 @@ TCCX = $(TCC) $(OPTS) -I. -I$(TOP)/src
 #
 LIBOBJ+= alter.o analyze.o attach.o auth.o btmutex.o btree.o build.o \
          callback.o complete.o date.o delete.o \
-         expr.o func.o hash.o insert.o journal.o loadext.o \
+         expr.o fault.o func.o hash.o insert.o journal.o loadext.o \
          main.o malloc.o mem1.o mem2.o mem3.o mem4.o mutex.o mutex_os2.o \
          mutex_unix.o mutex_w32.o \
          opcodes.o os.o os_os2.o os_unix.o os_win.o \
@@ -95,6 +95,7 @@ SRC = \
   $(TOP)/src/date.c \
   $(TOP)/src/delete.c \
   $(TOP)/src/expr.c \
+  $(TOP)/src/fault.c \
   $(TOP)/src/func.c \
   $(TOP)/src/hash.c \
   $(TOP)/src/hash.h \
index aebc2e30c0efc4f9804df158c780fa466f334633..93b350a257e6bca70b5591f6ce6625a647d34727 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,7 +1,7 @@
-C Fix\sa\sbug\sintroduced\sby\scheckin\s(4739).\s(CVS\s4741)
-D 2008-01-22T19:34:28
+C Add\sthe\sfault\sinjector\smodule\sin\sfault.c.\s\sUse\sit\sas\sa\sbasis\sfor\smemory\nallocation\sfailure\stesting.\s(CVS\s4742)
+D 2008-01-22T21:30:53
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
-F Makefile.in 936bcacced594b24b8fdcfc0fc0efc00e15de8a8
+F Makefile.in bc2b5df3e3d0d4b801b824b7ef6dec43812b049b
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
 F VERSION 6055d543dbd832b5c0209d6cc787413c1814efdc
@@ -64,7 +64,7 @@ F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
 F ext/icu/icu.c 12e763d288d23b5a49de37caa30737b971a2f1e2
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
 F ltmain.sh 56abb507100ed2d4261f6dd1653dec3cf4066387
-F main.mk b49a8c68baf8c17f72bb1ac78ef183b62f6e3f97
+F main.mk ad3a30d15d88f7d7c58b3c5f6bcee6f917043887
 F mkdll.sh 5f8438dcac98e795d7df6529159a1ec566de0183
 F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
 F mkextw.sh 1a866b53637dab137191341cc875575a5ca110fb
@@ -93,19 +93,20 @@ F src/date.c 8ce763c68143b1e8fb6f79dcfc8b801853c97017
 F src/delete.c 739ccbab8fa7478762bded5c9cc67f16a4d09dbe
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
 F src/expr.c 07318c7e5e3062e2d33314f72819ea420b210dc1
+F src/fault.c 049b88b8ba0a1db3240aeaf9695cd08b9a3ba9e1
 F src/func.c 8e3d0c59961dc403716767308ee764504179054b
-F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
+F src/hash.c 2dc6afe7478a0b739499af360c8863c900ea11a8
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
 F src/insert.c a741d7f0643f52995475d866004eb779578cd773
 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
 F src/loadext.c d17a0f760d6866aacf5262f97d8efaaad379cdd7
-F src/main.c f17abe4d28c442749ec892fc466d7e5727af04f2
+F src/main.c de0a4555caa68268c9c804283e9476a4e9aa0c62
 F src/malloc.c 60e392a4c12c839517f9b0db7b995f825444fb35
 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
 F src/mem1.c 6d1a11864963d249c67e72ad5f6533b040333880
-F src/mem2.c a9400e06b41ad5b5189e8416239833212de2c8c7
+F src/mem2.c 607af52ad7593f34934e7e4fa53a364556853d30
 F src/mem3.c 9d80034bb004c1bddc28d6befe1ddb044d18deab
 F src/mem4.c 36ecd536a8b7acfe4cbf011353dae6ea68121e40
 F src/mutex.c 3259f62c2429967aee6dc112117a6d2f499ef061
@@ -124,7 +125,7 @@ F src/os_unix.c e4daef7628f690fa2b188af3632fb18f96525946
 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
 F src/os_win.c c832d528ea774c7094d887749d71884984c9034c
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c fae75270b4e2b2542b905791087f0c52142974f8
+F src/pager.c d8c2f06c3ce225dd14816cd02f07d7c65aff1f53
 F src/pager.h f504f7ae84060fee0416a853e368d3d113c3d6fa
 F src/parse.y bcc6092d2577f4b525e09928b3ed164965e35c54
 F src/pragma.c 2bb8d6882b9a330e041acd05fb6aff5a01bf0a08
@@ -136,27 +137,27 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c ca06cb687c40a8bff6307b5fad41a0e86a0f8558
 F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
 F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h 9c3384439e402016037115ad143ed0c3adbd1c93
+F src/sqliteInt.h 3b67a79e9b7b9bb1aa5689384ae6524a78070d2c
 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
-F src/test1.c 7e620caf76fe1c9d78e2c062c90f387caab2b40d
+F src/test1.c 0040e28115047a50dde02383658f6b25ecbbcb42
 F src/test2.c 77b34303883b9d722c65a6879bb0163a400e3789
 F src/test3.c 6b49ddb0946907a07210998810807ace51be00a5
 F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
 F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
 F src/test6.c f8b34a6ff04937092327798ddf0ab46863535bc5
 F src/test7.c acec2256c7c2d279db5a8b5fa1a2a68fcc942c67
-F src/test8.c 6399d2f0561f1f65785c63e94f2cdd36fb248872
+F src/test8.c cab3f576353dfef4877c7cc3b0d0e48acc65c37c
 F src/test9.c b46c8fe02ac7cca1a7316436d8d38d50c66f4b2f
 F src/test_async.c 5f21392d66869a4c87dc9153e40d0dc0e085261f
 F src/test_autoext.c 855157d97aa28cf84233847548bfacda21807436
 F src/test_btree.c c1308ba0b88ab577fa56c9e493a09829dfcded9c
-F src/test_config.c fd6ba4c62dd943e794f00f6ea1e9e32d97bf27f1
+F src/test_config.c c0917656ada90c4aa23c52d1ade39815a930ee18
 F src/test_devsym.c 6341971bf1c7769c740501b36bc6192cd975c335
 F src/test_hexio.c 1a1cd8324d57585ea86b922f609fa1fbaaf9662d
 F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
-F src/test_malloc.c 72ceed192f7b229db34a2869ff9285b41a5cb796
+F src/test_malloc.c 7ba7e0c283d22c8b079acc4f73d0a034e9779b26
 F src/test_md5.c c107c96637123239c3518b5fbe97a79130f4d32e
 F src/test_onefile.c 54282b6796d55d7acc489be83b89b8715e7d3756
 F src/test_schema.c 12c9de7661d6294eec2d57afbb52e2af1128084f
@@ -169,14 +170,14 @@ F src/update.c 31edd9c9764e80753930bd5f9b43e0edb404636f
 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
 F src/util.c ca0e3820ce9b0e0ff9bf21f4b726a81163d7b417
 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
-F src/vdbe.c e7ec3089f1e2ee5ab47b66d2be940f4e8b0029a7
+F src/vdbe.c a3ac8efb7c862ddc3c357ee02612de857cbfd182
 F src/vdbe.h 58a7d931ffb704e034b2a725981cfa5bd406fad9
-F src/vdbeInt.h 835e6f0337ce89d705ef9a162338788808adc4b7
-F src/vdbeapi.c cb8c427a3ab646490c83204a98e94eff03ee2e89
+F src/vdbeInt.h 6b4a438198f98a2a2233cc228ed0f120a18628e7
+F src/vdbeapi.c a0cb07fc69553727b5b25c7fb12348528defd99b
 F src/vdbeaux.c 4a0c75af5366c9114b340c39bea5df76fb26e215
 F src/vdbeblob.c e386d49d8354aa5a58f0a7f2794303442c149120
 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
-F src/vdbemem.c bb8d4f70e387bd7ff7f4ee349e9f6a9c77cd67c3
+F src/vdbemem.c 79ec9d0d15167baafde2259dddde2a67bd21bcd7
 F src/vtab.c 9924e37cf7f5c527aeabb5da025874af505fb91d
 F src/where.c 0c18a6d88d78886fd5f3c11ef2cf001321acd918
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
@@ -383,7 +384,7 @@ F test/mallocD.test 24c1d07a00e605831d0d627b036bd690b2952416
 F test/mallocE.test e15333c394d7c330c8372a7cdf7b0f7c16573082
 F test/mallocF.test 6f25bc474f2b29954e5fac274d0e6ed9d86efea5
 F test/mallocG.test ac896f96098a30ed0dcc001b6f9243770a463081
-F test/malloc_common.tcl 262c71dd4af005bc3a6b8fe449237688255072a0
+F test/malloc_common.tcl 5c5f7ee985c9ef3480f441efb6329aeefbf9380c
 F test/manydb.test 8de36b8d33aab5ef295b11d9e95310aeded31af8
 F test/memdb.test a67bda4ff90a38f2b19f6c7f95aa7289e051d893
 F test/memleak.test d2d2a1ff7105d32dc3fdf691458cf6cba58c7217
@@ -543,7 +544,7 @@ F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
 F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf
 F tool/mkkeywordhash.c ef93810fc41fb3d3dbacf9a33a29be88ea99ffa9
 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
-F tool/mksqlite3c.tcl 21605262fb98d702fbd7c64213c414bd7e60dba4
+F tool/mksqlite3c.tcl 7354a40a96fce512d80be5b5c7f6dce1c61ca070
 F tool/mksqlite3internalh.tcl 47737a925fb02fce43e2c0a14b3cc17574a4d44a
 F tool/omittest.tcl 7d1fdf469e2f4d175f70c36e469db64a1626fabb
 F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
@@ -613,7 +614,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P f47cf3cc5c70ffb70795e9412e6eaeaf044c3559
-R 71bc19b9323f20366a9e6c74fd0d62a0
+P c8394ac24b87707fa7f2e3cb43ad8efb65d2595e
+R 21d4a739d8a6a8ab5aa325f6376c5db5
 U drh
-Z 7ffec562f9d034046208e1f4dd82239a
+Z 7682f023570ed6783cc7782294e94c3e
index d53c8f01dbb7ed4b37df0cf361ba59b23cb42e94..2d0a28a5bb02761bbf686215acfd13ab85299735 100644 (file)
@@ -1 +1 @@
-c8394ac24b87707fa7f2e3cb43ad8efb65d2595e
\ No newline at end of file
+1a335e180183b414fcc3510ce28b98b21cd134a6
\ No newline at end of file
diff --git a/src/fault.c b/src/fault.c
new file mode 100644 (file)
index 0000000..4cc369e
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+** 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 implement a fault-injector used for
+** testing and verification of SQLite.
+**
+** Subsystems within SQLite can call sqlite3FaultStep() to see if
+** they should simulate a fault.  sqlite3FaultStep() normally returns
+** zero but will return non-zero if a fault should be simulated.
+** Fault injectors can be used, for example, to simulate memory
+** allocation failures or I/O errors.
+**
+** The fault injector is omitted from the code if SQLite is
+** compiled with -DSQLITE_OMIT_FAULTINJECTOR=1.  There is a very
+** small performance hit for leaving the fault injector in the code.
+** Commerical products will probably want to omit the fault injector
+** from production builds.  But safety-critical systems who work
+** under the motto "fly what you test and test what you fly" may
+** choose to leave the fault injector enabled even in production.
+*/
+#include "sqliteInt.h"
+
+#ifndef SQLITE_OMIT_FAULTINJECTOR
+
+/*
+** There can be various kinds of faults.  For example, there can be
+** a memory allocation failure.  Or an I/O failure.  For each different
+** fault type, there is a separate FaultInjector structure to keep track
+** of the status of that fault.
+*/
+static struct FaultInjector {
+  int iCountdown;   /* Number of pending successes before we hit 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 */
+  u8 benign;        /* Ture if next failure will be benign */
+} aFault[SQLITE_FAULTINJECTOR_COUNT];
+
+/*
+** This routine configures and enables a fault injector.  After
+** calling this routine, aFaultStep() will return false (zero)
+** nDelay times, then it will return true nRepeat times,
+** then it will again begin returning false.
+*/
+void sqlite3FaultConfig(int id, int nDelay, int nRepeat){
+  assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
+  aFault[id].iCountdown = nDelay;
+  aFault[id].nRepeat = nRepeat;
+  aFault[id].nBenign = 0;
+  aFault[id].nFail = 0;
+  aFault[id].enable = nDelay>=0;
+  aFault[id].benign = 0;
+}
+
+/*
+** Return the number of faults (both hard and benign faults) that have
+** occurred since the injector was last configured.
+*/
+int sqlite3FaultFailures(int id){
+  assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
+  return aFault[id].nFail;
+}
+
+/*
+** Return the number of benign faults that have occurred since the
+** injector was last configured.
+*/
+int sqlite3FaultBenignFailures(int id){
+  assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
+  return aFault[id].nBenign;
+}
+
+/*
+** Return the number of successes that will occur before the next failure.
+** If no failures are scheduled, return -1.
+*/
+int sqlite3FaultPending(int id){
+  assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
+  if( aFault[id].enable ){
+    return aFault[id].iCountdown;
+  }else{
+    return -1;
+  }
+}
+
+/* 
+** After this routine causes subsequent 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 sqlite3FaultBenign(int id, int enable){
+  assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
+  aFault[id].benign = enable;
+}
+
+/*
+** This routine exists as a place to set a breakpoint that will
+** fire on any simulated fault.
+*/
+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.
+*/
+int sqlite3FaultStep(int id){
+  assert( id>=0 && id<SQLITE_FAULTINJECTOR_COUNT );
+  if( likely(!aFault[id].enable) ){
+    return 0;
+  }
+  if( aFault[id].iCountdown>0 ){
+    aFault[id].iCountdown--;
+    return 0;
+  }
+  sqlite3Fault();
+  aFault[id].nFail++;
+  if( aFault[id].benign ){
+    aFault[id].nBenign++;
+  }
+  aFault[id].nRepeat--;
+  if( aFault[id].nRepeat<=0 ){
+    aFault[id].enable = 0;
+  }
+  return 1;  
+}
+
+#endif /* SQLITE_OMIT_FAULTINJECTOR */
index a88d16b06bf26cb89a3dd351ec403ba99b496c9b..9a91e85e2ba8a11a64b82f65b9936c091c86ae6a 100644 (file)
@@ -12,7 +12,7 @@
 ** This is the implementation of generic hash-tables
 ** used in SQLite.
 **
-** $Id: hash.c,v 1.24 2007/09/04 14:31:47 danielk1977 Exp $
+** $Id: hash.c,v 1.25 2008/01/22 21:30:53 drh Exp $
 */
 #include "sqliteInt.h"
 #include <assert.h>
@@ -228,9 +228,10 @@ static void rehash(Hash *pH, int new_size){
   ** is benign (since failing to resize a hash table is a performance
   ** hit only, not a fatal error).
   */
-  sqlite3MallocBenignFailure(pH->htsize>0);
-
+  sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, pH->htsize>0);
   new_ht = (struct _ht *)sqlite3MallocZero( new_size*sizeof(struct _ht) );
+  sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0);
+
   if( new_ht==0 ) return;
   if( pH->ht ) sqlite3_free(pH->ht);
   pH->ht = new_ht;
index c123eb95e4004030317b005742f05c906a0dd083..7fa01c2e819e90e6d18b56f34108d6a2176e5fd6 100644 (file)
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.411 2008/01/22 14:50:17 drh Exp $
+** $Id: main.c,v 1.412 2008/01/22 21:30:53 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -252,7 +252,7 @@ void sqlite3RollbackAll(sqlite3 *db){
   int i;
   int inTrans = 0;
   assert( sqlite3_mutex_held(db->mutex) );
-  sqlite3MallocEnterBenignBlock(1);                 /* Enter benign region */
+  sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 1);
   for(i=0; i<db->nDb; i++){
     if( db->aDb[i].pBt ){
       if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){
@@ -263,7 +263,7 @@ void sqlite3RollbackAll(sqlite3 *db){
     }
   }
   sqlite3VtabRollback(db);
-  sqlite3MallocLeaveBenignBlock();                 /* Leave benign region */
+  sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0);
 
   if( db->flags&SQLITE_InternChanges ){
     sqlite3ExpirePreparedStatements(db);
index 69a641a858ff452d5158d6d0532d628b9fa5abf7..0c99c63e5863ffeab35c41d3be29acb1699171e9 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains the C functions that implement a memory
 ** allocation subsystem for use by SQLite.  
 **
-** $Id: mem2.c,v 1.18 2007/11/29 18:36:49 drh Exp $
+** $Id: mem2.c,v 1.19 2008/01/22 21:30:53 drh Exp $
 */
 
 /*
@@ -136,18 +136,6 @@ static struct {
   int nTitle;        /* Bytes of zTitle to save.  Includes '\0' and padding */
   char zTitle[100];  /* The title text */
 
-  /*
-  ** These values are used to simulate malloc failures.  When
-  ** iFail is 1, simulate a malloc failures and reset the value
-  ** to iReset.
-  */
-  int iFail;    /* Decrement and fail malloc when this is 1 */
-  int iReset;   /* When malloc fails set iiFail to this value */
-  int iFailCnt;         /* Number of failures */
-  int iBenignFailCnt;   /* Number of benign failures */
-  int iNextIsBenign;    /* True if the next call to malloc may fail benignly */
-  int iIsBenign;        /* All malloc calls may fail benignly */
-
   /* 
   ** sqlite3MallocDisallow() increments the following counter.
   ** sqlite3MallocAllow() decrements it.
@@ -255,17 +243,6 @@ static struct MemBlockHdr *sqlite3MemsysGetHeader(void *pAllocation){
   return p;
 }
 
-/*
-** This routine is called once the first time a simulated memory
-** failure occurs.  The sole purpose of this routine is to provide
-** a convenient place to set a debugger breakpoint when debugging
-** errors related to malloc() failures.
-*/
-static void sqlite3MemsysFailed(void){
-  mem.iFailCnt = 0;
-  mem.iBenignFailCnt = 0;
-}
-
 /*
 ** Allocate nByte bytes of memory.
 */
@@ -291,21 +268,8 @@ void *sqlite3_malloc(int nByte){
     }
     totalSize = nByte + sizeof(*pHdr) + sizeof(int) +
                  mem.nBacktrace*sizeof(void*) + mem.nTitle;
-    if( mem.iFail>0 ){
-      if( mem.iFail==1 ){
-        p = 0;
-        mem.iFail = mem.iReset;
-        if( mem.iFailCnt==0 ){
-          sqlite3MemsysFailed();  /* A place to set a breakpoint */
-        }
-        mem.iFailCnt++;
-        if( mem.iNextIsBenign || mem.iIsBenign ){
-          mem.iBenignFailCnt++;
-        }
-      }else{
-        p = malloc(totalSize);
-        mem.iFail--;
-      }
+    if( sqlite3FaultStep(SQLITE_FAULTINJECTOR_MALLOC) ){
+      p = 0;
     }else{
       p = malloc(totalSize);
       if( p==0 ){
@@ -350,7 +314,6 @@ void *sqlite3_malloc(int nByte){
     }
     sqlite3_mutex_leave(mem.mutex);
   }
-  mem.iNextIsBenign = 0;
   return p; 
 }
 
@@ -489,85 +452,5 @@ void sqlite3_memdebug_dump(const char *zFilename){
   fclose(out);
 }
 
-/*
-** This routine is used to simulate malloc failures.
-**
-** After calling this routine, there will be iFail successful
-** memory allocations and then a failure.  If iRepeat is 1
-** all subsequent memory allocations will fail.  If iRepeat is
-** 0, only a single allocation will fail.  If iRepeat is negative
-** then the previous setting for iRepeat is unchanged.
-**
-** Each call to this routine overrides the previous.  To disable
-** the simulated allocation failure mechanism, set iFail to -1.
-**
-** This routine returns the number of simulated failures that have
-** occurred since the previous call.
-*/
-int sqlite3_memdebug_fail(int iFail, int iRepeat, int *piBenign){
-  int n = mem.iFailCnt;
-  if( piBenign ){
-    *piBenign = mem.iBenignFailCnt;
-  }
-  mem.iFail = iFail+1;
-  if( iRepeat>=0 ){
-    mem.iReset = iRepeat;
-  }
-  mem.iFailCnt = 0;
-  mem.iBenignFailCnt = 0;
-  return n;
-}
-
-int sqlite3_memdebug_pending(){
-  return (mem.iFail-1);
-}
-
-/*
-** The following three functions are used to indicate to the test 
-** infrastructure which malloc() calls may fail benignly without
-** affecting functionality. This can happen when resizing hash tables 
-** (failing to resize a hash-table is a performance hit, but not an 
-** error) or sometimes during a rollback operation.
-**
-** If the argument is true, sqlite3MallocBenignFailure() indicates that the
-** next call to allocate memory may fail benignly.
-**
-** If sqlite3MallocEnterBenignBlock() is called with a non-zero argument,
-** then all memory allocations requested before the next call to
-** sqlite3MallocLeaveBenignBlock() may fail benignly.
-*/
-void sqlite3MallocBenignFailure(int isBenign){
-  if( isBenign ){
-    mem.iNextIsBenign = 1;
-  }
-}
-void sqlite3MallocEnterBenignBlock(int isBenign){
-  if( isBenign ){
-    mem.iIsBenign = 1;
-  }
-}
-void sqlite3MallocLeaveBenignBlock(){
-  mem.iIsBenign = 0;
-}
-
-/*
-** The following two routines are used to assert that no memory
-** allocations occur between one call and the next.  The use of
-** these routines does not change the computed results in any way.
-** These routines are like asserts.
-*/
-void sqlite3MallocDisallow(void){
-  assert( mem.mutex!=0 );
-  sqlite3_mutex_enter(mem.mutex);
-  mem.disallow++;
-  sqlite3_mutex_leave(mem.mutex);
-}
-void sqlite3MallocAllow(void){
-  assert( mem.mutex );
-  sqlite3_mutex_enter(mem.mutex);
-  assert( mem.disallow>0 );
-  mem.disallow--;
-  sqlite3_mutex_leave(mem.mutex);
-}
 
 #endif /* SQLITE_MEMDEBUG && !SQLITE_OMIT_MEMORY_ALLOCATION */
index 13b0b6d3998b5d9627fe2dc6a3c07e68ce8a88b8..e7e38953e7429e1c0678c26fec33e6763e4b4506 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.403 2008/01/21 13:04:35 danielk1977 Exp $
+** @(#) $Id: pager.c,v 1.404 2008/01/22 21:30:53 drh Exp $
 */
 #ifndef SQLITE_OMIT_DISKIO
 #include "sqliteInt.h"
@@ -699,8 +699,9 @@ static void pager_resize_hash_table(Pager *pPager, int N){
   PgHdr **aHash, *pPg;
   assert( N>0 && (N&(N-1))==0 );
   pagerLeave(pPager);
-  sqlite3MallocBenignFailure((int)pPager->aHash);
+  sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, pPager->aHash!=0);
   aHash = sqlite3MallocZero( sizeof(aHash[0])*N );
+  sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0);
   pagerEnter(pPager);
   if( aHash==0 ){
     /* Failure to rehash is not an error.  It is only a performance hit. */
index 943e396318aa687471b19441af8aa5abee6cc884..1ba3b8de8ae95cd9f3a60f5fcf3731b95a433015 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.652 2008/01/18 14:08:24 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.653 2008/01/22 21:30:53 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1976,26 +1976,6 @@ void sqlite3Parser(void*, int, Token, Parse*);
   int sqlite3Utf8To8(unsigned char*);
 #endif
 
-/*
-** The MallocDisallow() and MallocAllow() routines are like asserts.
-** Call them around a section of code that you do not expect to do
-** any memory allocation.
-*/
-#ifdef SQLITE_MEMDEBUG
-  void sqlite3MallocDisallow(void);
-  void sqlite3MallocAllow(void);
-  void sqlite3MallocBenignFailure(int);
-  void sqlite3MallocEnterBenignBlock(int isBenign);
-  void sqlite3MallocLeaveBenignBlock();
-#else
-# define sqlite3MallocDisallow()
-# define sqlite3MallocAllow()
-# define sqlite3MallocBenignFailure(x)
-# define sqlite3MallocEnterBenignBlock(x);
-# define sqlite3MallocLeaveBenignBlock();
-#endif
-
-
 #ifdef SQLITE_OMIT_VIRTUALTABLE
 #  define sqlite3VtabClear(X)
 #  define sqlite3VtabSync(X,Y) (Y)
@@ -2023,6 +2003,37 @@ int sqlite3Reprepare(Vdbe*);
 void sqlite3ExprListCheckLength(Parse*, ExprList*, int, const char*);
 CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
 
+
+/*
+** Available fault injectors.  Should be numbered beginning with 0.
+*/
+#define SQLITE_FAULTINJECTOR_MALLOC     0
+#define SQLITE_FAULTINJECTOR_SAFETY     1
+#define SQLITE_FAULTINJECTOR_COUNT      2
+
+/*
+** The interface to the fault injector subsystem.  If the fault injector
+** mechanism is disabled at compile-time then set up macros so that no
+** unnecessary code is generated.
+*/
+#ifndef SQLITE_OMIT_FAULTINJECTOR
+  void sqlite3FaultConfig(int,int,int);
+  int sqlite3FaultFailures(int);
+  int sqlite3FaultBenignFailures(int);
+  int sqlite3FaultPending(int);
+  void sqlite3FaultBenign(int,int);
+  int sqlite3FaultStep(int);
+#else
+# define sqlite3FaultConfig(A,B,C)
+# define sqlite3FaultFailures(A)         0
+# define sqlite3FaultBenignFailures(A)   0
+# define sqlite3FaultPending(A)          (-1)
+# define sqlite3FaultBenign(A,B)
+# define sqlite3FaultStep(A)             0
+#endif
+  
+  
+
 #define IN_INDEX_ROWID           1
 #define IN_INDEX_EPH             2
 #define IN_INDEX_INDEX           3
index 543021c88031d0b631a2f1286ab5c202f8191d9b..277489241b18a96a049cc022096570dab0aabfb2 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.285 2008/01/22 14:50:17 drh Exp $
+** $Id: test1.c,v 1.286 2008/01/22 21:30:53 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -4095,35 +4095,6 @@ static int test_soft_heap_limit(
   return TCL_OK;
 }
 
-/*
-** Usage:   sqlite3_clear_tsd_memdebug
-**
-** Clear all of the MEMDEBUG information out of thread-specific data.
-** This will allow it to be deallocated.
-*/
-static int test_clear_tsd_memdebug(
-  void * clientData,
-  Tcl_Interp *interp,
-  int objc,
-  Tcl_Obj *CONST objv[]
-){
-  return TCL_OK;
-}
-
-/*
-** Usage:   sqlite3_tsd_release
-**
-** Call sqlite3ReleaseThreadData.
-*/
-static int test_tsd_release(
-  void * clientData,
-  Tcl_Interp *interp,
-  int objc,
-  Tcl_Obj *CONST objv[]
-){
-  return TCL_OK;
-}
-
 /*
 ** Usage:   sqlite3_thread_cleanup
 **
@@ -4469,8 +4440,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
 
      { "sqlite3_release_memory",        test_release_memory,     0},
      { "sqlite3_soft_heap_limit",       test_soft_heap_limit,    0},
-     { "sqlite3_clear_tsd_memdebug",    test_clear_tsd_memdebug, 0},
-     { "sqlite3_tsd_release",           test_tsd_release,        0},
      { "sqlite3_thread_cleanup",        test_thread_cleanup,     0},
      { "sqlite3_pager_refcounts",       test_pager_refcounts,    0},
 
index 5cbcf533e4a6cc1c7158c247cfe7042891269ef0..944ac686ef4b6d2eed727daabce68198ff99ef59 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test8.c,v 1.58 2007/12/13 21:54:11 drh Exp $
+** $Id: test8.c,v 1.59 2008/01/22 21:30:53 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -1021,8 +1021,11 @@ static int echoSync(sqlite3_vtab *tab){
   return rc;
 }
 static int echoCommit(sqlite3_vtab *tab){
-  sqlite3MallocBenignFailure(1);
-  return echoTransactionCall(tab, "xCommit");
+  int rc;
+  sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 1);
+  rc = echoTransactionCall(tab, "xCommit");
+  sqlite3FaultBenign(SQLITE_FAULTINJECTOR_MALLOC, 0);
+  return rc;
 }
 static int echoRollback(sqlite3_vtab *tab){
   return echoTransactionCall(tab, "xRollback");
index aa769e6d261d62bb656d39ffd2a3d0a8877a0968..4f44281224f51e447716b971c37025724a5d01cc 100644 (file)
@@ -16,7 +16,7 @@
 ** The focus of this file is providing the TCL testing layer
 ** access to compile-time constants.
 **
-** $Id: test_config.c,v 1.16 2007/10/19 17:47:25 drh Exp $
+** $Id: test_config.c,v 1.17 2008/01/22 21:30:53 drh Exp $
 */
 
 #include "sqliteLimit.h"
@@ -205,6 +205,12 @@ static void set_options(Tcl_Interp *interp){
   Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
 #endif
 
+#ifdef SQLITE_OMIT_FAULTINJECTOR
+  Tcl_SetVar2(interp, "sqlite_options", "faultinjector", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "faultinjector", "1", TCL_GLOBAL_ONLY);
+#endif
+
 #ifdef SQLITE_OMIT_FLOATING_POINT
   Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
 #else
index 5b777f7d819a9d400039a8b81d159c48873fd7f2..237cb96aaf70ce73b15cfce7051dd93cdfe5bd40 100644 (file)
@@ -13,7 +13,7 @@
 ** This file contains code used to implement test interfaces to the
 ** memory allocation subsystem.
 **
-** $Id: test_malloc.c,v 1.9 2007/10/19 17:47:25 drh Exp $
+** $Id: test_malloc.c,v 1.10 2008/01/22 21:30:53 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -349,12 +349,12 @@ static int test_memdebug_dump(
 **
 ** where options are:
 **
-**     -repeat    <boolean>
+**     -repeat    <count>
 **     -benigncnt <varname>
 **
 ** Arrange for a simulated malloc() failure after COUNTER successes.
-** If REPEAT is 1 then all subsequent malloc()s fail.   If REPEAT is
-** 0 then only a single failure occurs.
+** If a repeat count is specified, the fault is repeated that many
+** times.
 **
 ** Each call to this routine overrides the prior counter value.
 ** This routine returns the number of simulated failures that have
@@ -370,9 +370,9 @@ static int test_memdebug_fail(
 ){
   int ii;
   int iFail;
-  int iRepeat = -1;
+  int nRepeat = 1;
   Tcl_Obj *pBenignCnt = 0;
-
+  int nBenign;
   int nFail = 0;
 
   if( objc<2 ){
@@ -390,7 +390,7 @@ static int test_memdebug_fail(
       if( ii==(objc-1) ){
         zErr = "option requires an argument: ";
       }else{
-        if( Tcl_GetIntFromObj(interp, objv[ii+1], &iRepeat) ){
+        if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){
           return TCL_ERROR;
         }
       }
@@ -410,16 +410,12 @@ static int test_memdebug_fail(
     }
   }
   
-#ifdef SQLITE_MEMDEBUG
-  {
-    extern int sqlite3_memdebug_fail(int,int,int*);
-    int iBenignCnt;
-    nFail = sqlite3_memdebug_fail(iFail, iRepeat, &iBenignCnt);
-    if( pBenignCnt ){
-      Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(iBenignCnt), 0);
-    }
+  nBenign = sqlite3FaultBenignFailures(SQLITE_FAULTINJECTOR_MALLOC);
+  nFail = sqlite3FaultFailures(SQLITE_FAULTINJECTOR_MALLOC);
+  sqlite3FaultConfig(SQLITE_FAULTINJECTOR_MALLOC, iFail, nRepeat);
+  if( pBenignCnt ){
+    Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0);
   }
-#endif
   Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail));
   return TCL_OK;
 }
@@ -444,8 +440,9 @@ static int test_memdebug_pending(
 
 #ifdef SQLITE_MEMDEBUG
   {
-    extern int sqlite3_memdebug_pending();
-    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_memdebug_pending()));
+    Tcl_SetObjResult(interp, 
+       Tcl_NewIntObj(sqlite3FaultPending(SQLITE_FAULTINJECTOR_MALLOC))
+    );
   }
 #endif
   return TCL_OK;
index cefc0ba01f8d056fcf590d57a4ac40806677ad89..a827115b97f75c89a3e2b21353c4ea561911cf01 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.703 2008/01/21 16:22:46 drh Exp $
+** $Id: vdbe.c,v 1.704 2008/01/22 21:30:53 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -948,7 +948,7 @@ case OP_SCopy: {
   pOut = &p->aMem[pOp->p2];
   assert( pOut!=pIn1 );
   if( pOp->opcode==OP_Move ){
-    rc = sqlite3VdbeMemMove(pOut, pIn1);
+    sqlite3VdbeMemMove(pOut, pIn1);
   }else{
     sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
     if( pOp->opcode==OP_Copy ){
index 094867fa6d8aa921cdf6e6d419985fca3883c22b..d1377bdd89c28ffe96b1416ddda82208fed1f491 100644 (file)
@@ -377,7 +377,7 @@ int sqlite3VdbeChangeEncoding(Mem *, int);
 int sqlite3VdbeMemTooBig(Mem*);
 int sqlite3VdbeMemCopy(Mem*, const Mem*);
 void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
-int sqlite3VdbeMemMove(Mem*, Mem*);
+void sqlite3VdbeMemMove(Mem*, Mem*);
 int sqlite3VdbeMemNulTerminate(Mem*);
 int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
 void sqlite3VdbeMemSetInt64(Mem*, i64);
index ae9af1674cf95affafe01d740f0c1fa0bf654aa3..7d44fb158c05cd22e5989a33caa44328dc1122aa 100644 (file)
@@ -1041,9 +1041,7 @@ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
   }
   sqlite3_mutex_enter(pTo->db->mutex);
   for(i=0; rc==SQLITE_OK && i<pFrom->nVar; i++){
-    sqlite3MallocDisallow();
-    rc = sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
-    sqlite3MallocAllow();
+    sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
   }
   sqlite3_mutex_leave(pTo->db->mutex);
   assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
index c2631c970c8eacf9189f1e53b637c99339a5c56d..0449d52f13cb1a2d839a529df36028601f885dbe 100644 (file)
@@ -542,12 +542,9 @@ int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
 ** Transfer the contents of pFrom to pTo. Any existing value in pTo is
 ** freed. If pFrom contains ephemeral data, a copy is made.
 **
-** pFrom contains an SQL NULL when this routine returns.  SQLITE_NOMEM
-** might be returned if pFrom held ephemeral data and we were unable
-** to allocate enough space to make a copy.
+** pFrom contains an SQL NULL when this routine returns.
 */
-int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
-  int rc;
+void sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
   assert( pFrom->db==0 || sqlite3_mutex_held(pFrom->db->mutex) );
   assert( pTo->db==0 || sqlite3_mutex_held(pTo->db->mutex) );
   assert( pFrom->db==0 || pTo->db==0 || pFrom->db==pTo->db );
@@ -560,12 +557,6 @@ int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
   }
   pFrom->flags = MEM_Null;
   pFrom->xDel = 0;
-  if( 0 /* pTo->flags & MEM_Ephem */ ){
-    rc = sqlite3VdbeMemMakeWriteable(pTo);
-  }else{
-    rc = SQLITE_OK;
-  }
-  return rc;
 }
 
 /*
index f06dbbe84a0814daddc6c6b053913ef21d548129..840678c0454f2431e5592109578d42100be35cc0 100644 (file)
@@ -12,7 +12,7 @@
 # This file contains common code used by many different malloc tests
 # within the test suite.
 #
-# $Id: malloc_common.tcl,v 1.11 2008/01/18 17:03:33 drh Exp $
+# $Id: malloc_common.tcl,v 1.12 2008/01/22 21:30:53 drh Exp $
 
 # If we did not compile with malloc testing enabled, then do nothing.
 #
@@ -63,7 +63,7 @@ proc do_malloc_test {tn args} {
   }
   save_prng_state
 
-  foreach ::iRepeat {0 1} {
+  foreach ::iRepeat {0 10000000} {
     set ::go 1
     for {set ::n $start} {$::go && $::n <= $end} {incr ::n} {
 
@@ -125,6 +125,7 @@ proc do_malloc_test {tn args} {
         #
         set isFail [catch $::mallocbody msg]
         set nFail [sqlite3_memdebug_fail -1 -benigncnt nBenign]
+        # puts -nonewline " (isFail=$isFail nFail=$nFail nBenign=$nBenign) "
 
         # If one or more mallocs failed, run this loop body again.
         #
index d99745ca109c0f53e561281bb40fc921ea89b21f..6d98790044c63354b2a1b8ec3ca082520e39831a 100644 (file)
@@ -201,6 +201,7 @@ foreach file {
    date.c
    os.c
 
+   fault.c
    mem1.c
    mem2.c
    mem3.c