Memory Managment: new main-section config option "debug_store" to control extra inter... exim-4_89_RC6
authorJeremy Harris <jgh146exb@wizmail.org>
Sat, 11 Feb 2017 16:36:23 +0000 (16:36 +0000)
committerPhil Pennock <pdp@exim.org>
Wed, 22 Feb 2017 17:27:36 +0000 (12:27 -0500)
(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 919b36a146d5260aa27baa6594e6dd31da39f13c..19227beef0868a2e78465ba5981ca6abe3e5b76a 100644 (file)
@@ -13535,6 +13535,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"
@@ -14423,6 +14424,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 dd70201e5e22a01b7b995725b6c63722a33c7dbb..9d9c817967d433ed3f127a972a454f9f5ad641ff 100644 (file)
@@ -11,6 +11,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 4ebfca19ba4b18a530b2b46694eedb548d12931d..790f073174846d8aa192167a7b59c2452aeea355 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