.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"
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"
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
------------
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
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 {"
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 */
{ "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 },
{
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 */
{
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]);
}
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);
{
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
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
daemon_smtp_ports =
daemon_startup_retries = 3
daemon_startup_sleep = 8s
daemon_smtp_ports =
daemon_startup_retries = 3
daemon_startup_sleep = 8s
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