MINOR: pools: support setting debugging options using -dM
The 9 currently available debugging options may now be checked, set, or cleared using -dM. The directive now takes a comma-delimited list of options after the optional poisonning byte. With "help", the list of available options is displayed with a short help and their current status. The management doc was updated.
This commit is contained in:
parent
1408b1f8be
commit
f4b79c4a01
@ -2531,10 +2531,10 @@ tune.comp.maxlevel <number>
|
||||
this value. The default value is 1.
|
||||
|
||||
tune.fail-alloc
|
||||
If compiled with DEBUG_FAIL_ALLOC, gives the percentage of chances an
|
||||
allocation attempt fails. Must be between 0 (no failure) and 100 (no
|
||||
success). This is useful to debug and make sure memory failures are handled
|
||||
gracefully.
|
||||
If compiled with DEBUG_FAIL_ALLOC or started with "-dMfail", gives the
|
||||
percentage of chances an allocation attempt fails. Must be between 0 (no
|
||||
failure) and 100 (no success). This is useful to debug and make sure memory
|
||||
failures are handled gracefully.
|
||||
|
||||
tune.fd.edge-triggered { on | off } [ EXPERIMENTAL ]
|
||||
Enables ('on') or disables ('off') the edge-triggered polling mode for FDs
|
||||
|
@ -227,7 +227,8 @@ list of options is :
|
||||
|
||||
./haproxy -W -q -c -dL -f foo.cfg | tar -T - -hzcf archive.tgz
|
||||
|
||||
-dM[<byte>] : forces memory poisoning, which means that each and every
|
||||
-dM[<byte>[,]][help|options,...] : forces memory poisoning, and/or changes
|
||||
memory other debugging options. Memory poisonning means that each and every
|
||||
memory region allocated with malloc() or pool_alloc() will be filled with
|
||||
<byte> before being passed to the caller. When <byte> is not specified, it
|
||||
defaults to 0x50 ('P'). While this slightly slows down operations, it is
|
||||
@ -235,7 +236,74 @@ list of options is :
|
||||
the code that cause random crashes. Note that -dM0 has the effect of
|
||||
turning any malloc() into a calloc(). In any case if a bug appears or
|
||||
disappears when using this option it means there is a bug in haproxy, so
|
||||
please report it.
|
||||
please report it. A number of other options are available either alone or
|
||||
after a comma following the byte. The special option "help" will list the
|
||||
currently supported options and their current value. Each debugging option
|
||||
may be forced on or off. The most optimal options are usually chosen at
|
||||
build time based on the operating system and do not need to be adjusted,
|
||||
unless suggested by a developer. Supported debugging options include
|
||||
(set/clear):
|
||||
- fail / no-fail:
|
||||
This enables randomly failing memory allocations, in conjunction with
|
||||
the global "tune.fail-alloc" setting. This is used to detect missing
|
||||
error checks in the code.
|
||||
|
||||
- no-merge / merge:
|
||||
By default, pools of very similar sizes are merged, resulting in more
|
||||
efficiency, but this complicates the analysis of certain memory dumps.
|
||||
This option allows to disable this mechanism, and may slightly increase
|
||||
the memory usage.
|
||||
|
||||
- cold-first / hot-first:
|
||||
In order to optimize the CPU cache hit ratio, by default the most
|
||||
recently released objects ("hot") are recycled for new allocations.
|
||||
But doing so also complicates analysis of memory dumps and may hide
|
||||
use-after-free bugs. This option allows to instead pick the coldest
|
||||
objects first, which may result in a slight increase of CPU usage.
|
||||
|
||||
- integrity / no-integrity:
|
||||
When this option is enabled, memory integrity checks are enabled on
|
||||
the allocated area to verify that it hasn't been modified since it was
|
||||
last released. This works best with "no-merge", "cold-first" and "tag".
|
||||
Enabling this option will slightly increase the CPU usage.
|
||||
|
||||
- no-global / global:
|
||||
Depending on the operating system, a process-wide global memory cache
|
||||
may be enabled if it is estimated that the standard allocator is too
|
||||
slow or inefficient with threads. This option allows to forcefully
|
||||
disable it or enable it. Disabling it may result in a CPU usage
|
||||
increase with inefficient allocators. Enabling it may result in a
|
||||
higher memory usage with efficient allocators.
|
||||
|
||||
- no-cache / cache:
|
||||
Each thread uses a very fast local object cache for allocations, which
|
||||
is always enabled by default. This option allows to disable it. Since
|
||||
the global cache also passes via the local caches, this will
|
||||
effectively result in disabling all caches and allocating directly from
|
||||
the default allocator. This may result in a significant increase of CPU
|
||||
usage, but may also result in small memory savings on tiny systems.
|
||||
|
||||
- caller / no-caller:
|
||||
Enabling this option reserves some extra space in each allocated object
|
||||
to store the address of the last caller that allocated or released it.
|
||||
This helps developers go back in time when analysing memory dumps and
|
||||
to guess how something unexpected happened.
|
||||
|
||||
- tag / no-tag:
|
||||
Enabling this option reserves some extra space in each allocated object
|
||||
to store a tag that allows to detect bugs such as double-free, freeing
|
||||
an invalid object, and buffer overflows. It offers much stronger
|
||||
reliability guarantees at the expense of 4 or 8 extra bytes per
|
||||
allocation. It usually is the first step to detect memory corruption.
|
||||
|
||||
- poison / no-poison:
|
||||
Enabling this option will fill allocated objects with a fixed pattern
|
||||
that will make sure that some accidental values such as 0 will not be
|
||||
present if a newly added field was mistakenly forgotten in an
|
||||
initialization routine. Such bugs tend to rarely reproduce, especially
|
||||
when pools are not merged. This is normally enabled by directly passing
|
||||
the byte's value to -dM but using this option allows to disable/enable
|
||||
use of a previously set value.
|
||||
|
||||
-dS : disable use of the splice() system call. It is equivalent to the
|
||||
"global" section's "nosplice" keyword. This may be used when splice() is
|
||||
|
@ -564,7 +564,7 @@ static void usage(char *name)
|
||||
" [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
|
||||
" -v displays version ; -vv shows known build options.\n"
|
||||
" -d enters debug mode ; -db only disables background mode.\n"
|
||||
" -dM[<byte>] poisons memory with <byte> (defaults to 0x50)\n"
|
||||
" -dM[<byte>,help,...] debug memory (default: poison with <byte>/0x50)\n"
|
||||
" -V enters verbose mode (disables quiet mode)\n"
|
||||
" -D goes daemon ; -C changes to <dir> before loading files.\n"
|
||||
" -W master-worker mode.\n"
|
||||
|
70
src/pool.c
70
src/pool.c
@ -62,6 +62,25 @@ uint pool_debugging __read_mostly = /* set of POOL_DBG_* flags */
|
||||
#endif
|
||||
0;
|
||||
|
||||
static const struct {
|
||||
uint flg;
|
||||
const char *set;
|
||||
const char *clr;
|
||||
const char *hlp;
|
||||
} dbg_options[] = {
|
||||
/* flg, set, clr, hlp */
|
||||
{ POOL_DBG_FAIL_ALLOC, "fail", "no-fail", "randomly fail allocations" },
|
||||
{ POOL_DBG_DONT_MERGE, "no-merge", "merge", "disable merging of similar pools" },
|
||||
{ POOL_DBG_COLD_FIRST, "cold-first", "hot-first", "pick cold objects first" },
|
||||
{ POOL_DBG_INTEGRITY, "integrity", "no-integrity", "enable cache integrity checks" },
|
||||
{ POOL_DBG_NO_GLOBAL, "no-global", "global", "disable global shared cache" },
|
||||
{ POOL_DBG_NO_CACHE, "no-cache", "cache", "disable thread-local cache" },
|
||||
{ POOL_DBG_CALLER, "caller", "no-caller", "save caller information in cache" },
|
||||
{ POOL_DBG_TAG, "tag", "no-tag", "add tag at end of allocated objects" },
|
||||
{ POOL_DBG_POISON, "poison", "no-poison", "poison newly allocated objects" },
|
||||
{ 0 /* end */ }
|
||||
};
|
||||
|
||||
static int mem_fail_rate __read_mostly = 0;
|
||||
static int using_default_allocator __read_mostly = 1;
|
||||
static int(*my_mallctl)(const char *, void *, size_t *, void *, size_t) = NULL;
|
||||
@ -902,7 +921,9 @@ unsigned long pool_total_used()
|
||||
*/
|
||||
int pool_parse_debugging(const char *str, char **err)
|
||||
{
|
||||
struct ist args;
|
||||
char *end;
|
||||
uint new_dbg;
|
||||
int v;
|
||||
|
||||
|
||||
@ -916,6 +937,55 @@ int pool_parse_debugging(const char *str, char **err)
|
||||
pool_debugging &= ~POOL_DBG_POISON;
|
||||
str = end;
|
||||
}
|
||||
|
||||
new_dbg = pool_debugging;
|
||||
|
||||
for (args = ist(str); istlen(args); args = istadv(istfind(args, ','), 1)) {
|
||||
struct ist feat = iststop(args, ',');
|
||||
|
||||
if (!istlen(feat))
|
||||
continue;
|
||||
|
||||
if (isteq(feat, ist("help"))) {
|
||||
ha_free(err);
|
||||
memprintf(err,
|
||||
"-dM alone enables memory poisonning with byte 0x50 on allocation. A numeric\n"
|
||||
"value may be appended immediately after -dM to use another value (0 supported).\n"
|
||||
"Then an optional list of comma-delimited keywords may be appended to set or\n"
|
||||
"clear some debugging options ('*' marks the current setting):\n\n"
|
||||
" set clear description\n"
|
||||
" -----------------+-----------------+-----------------------------------------\n");
|
||||
|
||||
for (v = 0; dbg_options[v].flg; v++) {
|
||||
memprintf(err, "%s %c %-15s|%c %-15s| %s\n",
|
||||
*err,
|
||||
(pool_debugging & dbg_options[v].flg) ? '*' : ' ',
|
||||
dbg_options[v].set,
|
||||
(pool_debugging & dbg_options[v].flg) ? ' ' : '*',
|
||||
dbg_options[v].clr,
|
||||
dbg_options[v].hlp);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (v = 0; dbg_options[v].flg; v++) {
|
||||
if (isteq(feat, ist(dbg_options[v].set))) {
|
||||
new_dbg |= dbg_options[v].flg;
|
||||
break;
|
||||
}
|
||||
else if (isteq(feat, ist(dbg_options[v].clr))) {
|
||||
new_dbg &= ~dbg_options[v].flg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dbg_options[v].flg) {
|
||||
memprintf(err, "unknown pool debugging feature <%.*s>", (int)istlen(feat), istptr(feat));
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
pool_debugging = new_dbg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user