Memory Management: new main-section config option "debug_store" to control extra...
authorJeremy Harris <jgh146exb@wizmail.org>
Sat, 11 Feb 2017 16:36:23 +0000 (16:36 +0000)
committerJeremy Harris <jgh146exb@wizmail.org>
Sat, 25 Feb 2017 15:18:38 +0000 (15:18 +0000)
(cherry picked from commit 10919584f8ad580434442c7d971083f91c315bc0)
Signed-off-by: Phil Pennock <pdp@exim.org>
doc/doc-docbook/spec.xfpt
doc/doc-txt/NewStuff
doc/doc-txt/OptionLists.txt
src/src/globals.c
src/src/globals.h
src/src/readconf.c
src/src/store.c
test/confs/0001

index c69e45c391514af127b3f09c194309071cedd224..8b20910c1aed686be7e8d32979a3d0c72c0ea4f6 100644 (file)
@@ -13541,6 +13541,7 @@ listed in more than one group.
 .section "Miscellaneous" "SECID96"
 .table2
 .row &%bi_command%&                  "to run for &%-bi%& command line option"
 .section "Miscellaneous" "SECID96"
 .table2
 .row &%bi_command%&                  "to run for &%-bi%& command line option"
+.row &%debug_store%&                 "do extra internal checks"
 .row &%disable_ipv6%&                "do no IPv6 processing"
 .row &%keep_malformed%&              "for broken files &-- should not happen"
 .row &%localhost_number%&            "for unique message ids in clusters"
 .row &%disable_ipv6%&                "do no IPv6 processing"
 .row &%keep_malformed%&              "for broken files &-- should not happen"
 .row &%localhost_number%&            "for unique message ids in clusters"
@@ -14429,6 +14430,15 @@ The CHUNKING extension (RFC3030) will be advertised in the EHLO message to
 these hosts.
 Hosts may use the BDAT command as an alternate to DATA.
 
 these hosts.
 Hosts may use the BDAT command as an alternate to DATA.
 
+.new
+.option debug_store main boolean &`false`&
+.cindex debugging "memory corruption"
+.cindex memory debugging
+This option, when true, enables extra checking in Exim's internal memory
+management.  For use when a memory corruption issue is being investigated,
+it should normally be left as default.
+.wen
+
 .option daemon_smtp_ports main string &`smtp`&
 .cindex "port" "for daemon"
 .cindex "TCP/IP" "setting listening ports"
 .option daemon_smtp_ports main string &`smtp`&
 .cindex "port" "for daemon"
 .cindex "TCP/IP" "setting listening ports"
index ac876ed9ffb168c7a47cafb42ba42d93502cde14..2a8e520c6160ec99c890615800822cc0007cc93c 100644 (file)
@@ -18,6 +18,10 @@ Version 4.89
 
  1. Allow relative config file names for ".include"
 
 
  1. Allow relative config file names for ".include"
 
+ 2. A main-section config option "debug_store" to control the checks on
+    variable locations during store-reset.  Normally false but can be enabled
+    when a memory corrution issue is suspected on a production system.
+
 
 Version 4.88
 ------------
 
 Version 4.88
 ------------
index fc528518d0d72ce8ad74b56b3829c9bccf6a0903..696b5f3fa99f0413d5653ca0535353c394b423f2 100644 (file)
@@ -152,6 +152,7 @@ data_timeout                         time            5m            smtp
 debug_print                          string*         unset         authenticators    4.00
                                                      unset         routers           4.00
                                                      unset         transports        2.00
 debug_print                          string*         unset         authenticators    4.00
                                                      unset         routers           4.00
                                                      unset         transports        2.00
+debug_store                          boolean         false         main                     4.90
 delay_after_cutoff                   boolean         true          smtp
 delay_warning                        time list       24h           main
 delay_warning_condition              string*         +             main              1.73
 delay_after_cutoff                   boolean         true          smtp
 delay_warning                        time list       24h           main
 delay_warning_condition              string*         +             main              1.73
index 5e0fc2387bbac923f4e74b482031ccad77a78966..79ac37f92acf684a2125a8ddf6871364cbc8afb9 100644 (file)
@@ -599,6 +599,7 @@ bit_table debug_options[]      = { /* must be in alphabetical order */
 int     debug_options_count    = nelem(debug_options);
 
 unsigned int debug_selector    = 0;
 int     debug_options_count    = nelem(debug_options);
 
 unsigned int debug_selector    = 0;
+BOOL    debug_store            = FALSE;
 int     delay_warning[DELAY_WARNING_SIZE] = { DELAY_WARNING_SIZE, 1, 24*60*60 };
 uschar *delay_warning_condition=
   US"${if or {"
 int     delay_warning[DELAY_WARNING_SIZE] = { DELAY_WARNING_SIZE, 1, 24*60*60 };
 uschar *delay_warning_condition=
   US"${if or {"
index c2c69cf7ccd6fb6fdfe6cb9dac8151298f1eaedd..340f1aecfa142a769e55a7cd3cebad0aab31cbbc 100644 (file)
@@ -327,6 +327,7 @@ extern FILE   *debug_file;             /* Where to write debugging info */
 extern int     debug_notall[];         /* Debug options excluded from +all */
 extern bit_table debug_options[];      /* Table of debug options */
 extern int     debug_options_count;    /* Size of table */
 extern int     debug_notall[];         /* Debug options excluded from +all */
 extern bit_table debug_options[];      /* Table of debug options */
 extern int     debug_options_count;    /* Size of table */
+extern BOOL    debug_store;           /* Do extra checks on store_reset */
 extern int     delay_warning[];        /* Times between warnings */
 extern uschar *delay_warning_condition; /* Condition string for warnings */
 extern BOOL    delivery_date_remove;   /* Remove delivery-date headers */
 extern int     delay_warning[];        /* Times between warnings */
 extern uschar *delay_warning_condition; /* Condition string for warnings */
 extern BOOL    delivery_date_remove;   /* Remove delivery-date headers */
index 5efe7aa0411ea3378d1a378ab152077e4665919a..8b685c8fc6db142c12d9162597ded4d251719a94 100644 (file)
@@ -226,6 +226,7 @@ static optionlist optionlist_config[] = {
   { "dccifd_address",           opt_stringptr,   &dccifd_address },
   { "dccifd_options",           opt_stringptr,   &dccifd_options },
 #endif
   { "dccifd_address",           opt_stringptr,   &dccifd_address },
   { "dccifd_options",           opt_stringptr,   &dccifd_options },
 #endif
+  { "debug_store",              opt_bool,        &debug_store },
   { "delay_warning",            opt_timelist,    &delay_warning },
   { "delay_warning_condition",  opt_stringptr,   &delay_warning_condition },
   { "deliver_drop_privilege",   opt_bool,        &deliver_drop_privilege },
   { "delay_warning",            opt_timelist,    &delay_warning },
   { "delay_warning_condition",  opt_stringptr,   &delay_warning_condition },
   { "deliver_drop_privilege",   opt_bool,        &deliver_drop_privilege },
index e88555cbf6180b2112ffbe719cb379a220ed7e8c..8628954b5b2eec784aea7ddbb2456e04b8e3ca87 100644 (file)
@@ -144,39 +144,39 @@ if (size > yield_length[store_pool])
   {
   int length = (size <= STORE_BLOCK_SIZE)? STORE_BLOCK_SIZE : size;
   int mlength = length + ALIGNED_SIZEOF_STOREBLOCK;
   {
   int length = (size <= STORE_BLOCK_SIZE)? STORE_BLOCK_SIZE : size;
   int mlength = length + ALIGNED_SIZEOF_STOREBLOCK;
-  storeblock *newblock = NULL;
+  storeblock * newblock = NULL;
 
   /* Sometimes store_reset() may leave a block for us; check if we can use it */
 
 
   /* Sometimes store_reset() may leave a block for us; check if we can use it */
 
-  if (current_block[store_pool] != NULL &&
-      current_block[store_pool]->next != NULL)
+  if (  (newblock = current_block[store_pool])
+     && (newblock = newblock->next)
+     && newblock->length < length
+     )
     {
     {
-    newblock = current_block[store_pool]->next;
-    if (newblock->length < length)
-      {
-      /* Give up on this block, because it's too small */
-      store_free(newblock);
-      newblock = NULL;
-      }
+    /* Give up on this block, because it's too small */
+    store_free(newblock);
+    newblock = NULL;
     }
 
   /* If there was no free block, get a new one */
 
     }
 
   /* If there was no free block, get a new one */
 
-  if (newblock == NULL)
+  if (!newblock)
     {
     pool_malloc += mlength;           /* Used in pools */
     nonpool_malloc -= mlength;        /* Exclude from overall total */
     newblock = store_malloc(mlength);
     newblock->next = NULL;
     newblock->length = length;
     {
     pool_malloc += mlength;           /* Used in pools */
     nonpool_malloc -= mlength;        /* Exclude from overall total */
     newblock = store_malloc(mlength);
     newblock->next = NULL;
     newblock->length = length;
-    if (chainbase[store_pool] == NULL) chainbase[store_pool] = newblock;
-      else current_block[store_pool]->next = newblock;
+    if (!chainbase[store_pool])
+      chainbase[store_pool] = newblock;
+    else
+      current_block[store_pool]->next = newblock;
     }
 
   current_block[store_pool] = newblock;
   yield_length[store_pool] = newblock->length;
   next_yield[store_pool] =
     }
 
   current_block[store_pool] = newblock;
   yield_length[store_pool] = newblock->length;
   next_yield[store_pool] =
-    (void *)((char *)current_block[store_pool] + ALIGNED_SIZEOF_STOREBLOCK);
+    (void *)(CS current_block[store_pool] + ALIGNED_SIZEOF_STOREBLOCK);
   (void) VALGRIND_MAKE_MEM_NOACCESS(next_yield[store_pool], yield_length[store_pool]);
   }
 
   (void) VALGRIND_MAKE_MEM_NOACCESS(next_yield[store_pool], yield_length[store_pool]);
   }
 
@@ -354,11 +354,14 @@ the released memory. */
 
 newlength = bc + b->length - CS ptr;
 #ifndef COMPILE_UTILITY
 
 newlength = bc + b->length - CS ptr;
 #ifndef COMPILE_UTILITY
-if (running_in_test_harness)
+if (running_in_test_harness || debug_store)
   {
   assert_no_variables(ptr, newlength, filename, linenumber);
   {
   assert_no_variables(ptr, newlength, filename, linenumber);
-  (void) VALGRIND_MAKE_MEM_DEFINED(ptr, newlength);
-  memset(ptr, 0xF0, newlength);
+  if (running_in_test_harness)
+    {
+    (void) VALGRIND_MAKE_MEM_DEFINED(ptr, newlength);
+    memset(ptr, 0xF0, newlength);
+    }
   }
 #endif
 (void) VALGRIND_MAKE_MEM_NOACCESS(ptr, newlength);
   }
 #endif
 (void) VALGRIND_MAKE_MEM_NOACCESS(ptr, newlength);
@@ -376,7 +379,7 @@ if (yield_length[store_pool] < STOREPOOL_MIN_SIZE &&
   {
   b = b->next;
 #ifndef COMPILE_UTILITY
   {
   b = b->next;
 #ifndef COMPILE_UTILITY
-  if (running_in_test_harness)
+  if (running_in_test_harness || debug_store)
     assert_no_variables(b, b->length + ALIGNED_SIZEOF_STOREBLOCK,
                        filename, linenumber);
 #endif
     assert_no_variables(b, b->length + ALIGNED_SIZEOF_STOREBLOCK,
                        filename, linenumber);
 #endif
@@ -390,7 +393,7 @@ b->next = NULL;
 while ((b = bb))
   {
 #ifndef COMPILE_UTILITY
 while ((b = bb))
   {
 #ifndef COMPILE_UTILITY
-  if (running_in_test_harness)
+  if (running_in_test_harness || debug_store)
     assert_no_variables(b, b->length + ALIGNED_SIZEOF_STOREBLOCK,
                        filename, linenumber);
 #endif
     assert_no_variables(b, b->length + ALIGNED_SIZEOF_STOREBLOCK,
                        filename, linenumber);
 #endif
index b0f8f61e35097e456df33d9b90c1258500967571..471c8f817257534c08b884b934d334300a2e3d14 100644 (file)
@@ -54,6 +54,7 @@ daemon_smtp_port =
 daemon_smtp_ports =
 daemon_startup_retries = 3
 daemon_startup_sleep = 8s
 daemon_smtp_ports =
 daemon_startup_retries = 3
 daemon_startup_sleep = 8s
+debug_store
 delay_warning = 1d
 delay_warning_condition = ${if match{$h_precedence:}{(?i)bulk|list}{no}{yes}}
 deliver_drop_privilege
 delay_warning = 1d
 delay_warning_condition = ${if match{$h_precedence:}{(?i)bulk|list}{no}{yes}}
 deliver_drop_privilege