Add prof_leak_error option

The option makes the process to exit with error code 1 if a memory leak
is detected. This is useful for implementing automated tools that rely
on leak detection.
This commit is contained in:
yunxu 2022-01-12 18:46:34 +08:00 committed by Alex Lapenkou
parent eafd2ac39f
commit b798fabdf7
8 changed files with 56 additions and 0 deletions

View File

@ -1553,6 +1553,25 @@ malloc_conf = "xmalloc:true";]]></programlisting>
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="opt.prof_leak_error">
<term>
<mallctl>opt.prof_leak_error</mallctl>
(<type>bool</type>)
<literal>r-</literal>
[<option>--enable-prof</option>]
</term>
<listitem><para>Similar to <link linkend="opt.prof_leak"><mallctl>
opt.prof_leak</mallctl></link>, but makes the process exit with error
code 1 if a memory leak is detected. This option supersedes
<link linkend="opt.prof_leak"><mallctl>opt.prof_leak</mallctl></link>,
meaning that if both are specified, this option takes precedence. When
enabled, also enables <link linkend="opt.prof_leak"><mallctl>
opt.prof_leak</mallctl></link>. Works only when combined with
<link linkend="opt.prof_final"><mallctl>opt.prof_final</mallctl></link>,
otherwise does nothing. This option is disabled by default.
</para></listitem>
</varlistentry>
<varlistentry id="opt.zero_realloc"> <varlistentry id="opt.zero_realloc">
<term> <term>
<mallctl>opt.zero_realloc</mallctl> <mallctl>opt.zero_realloc</mallctl>

View File

@ -12,6 +12,7 @@ extern ssize_t opt_lg_prof_interval; /* lg(prof_interval). */
extern bool opt_prof_gdump; /* High-water memory dumping. */ extern bool opt_prof_gdump; /* High-water memory dumping. */
extern bool opt_prof_final; /* Final profile dumping. */ extern bool opt_prof_final; /* Final profile dumping. */
extern bool opt_prof_leak; /* Dump leak summary at exit. */ extern bool opt_prof_leak; /* Dump leak summary at exit. */
extern bool opt_prof_leak_error; /* Exit with error code if memory leaked */
extern bool opt_prof_accum; /* Report cumulative bytes. */ extern bool opt_prof_accum; /* Report cumulative bytes. */
extern bool opt_prof_log; /* Turn logging on at boot. */ extern bool opt_prof_log; /* Turn logging on at boot. */
extern char opt_prof_prefix[ extern char opt_prof_prefix[

View File

@ -145,6 +145,7 @@ CTL_PROTO(opt_lg_prof_interval)
CTL_PROTO(opt_prof_gdump) CTL_PROTO(opt_prof_gdump)
CTL_PROTO(opt_prof_final) CTL_PROTO(opt_prof_final)
CTL_PROTO(opt_prof_leak) CTL_PROTO(opt_prof_leak)
CTL_PROTO(opt_prof_leak_error)
CTL_PROTO(opt_prof_accum) CTL_PROTO(opt_prof_accum)
CTL_PROTO(opt_prof_recent_alloc_max) CTL_PROTO(opt_prof_recent_alloc_max)
CTL_PROTO(opt_prof_stats) CTL_PROTO(opt_prof_stats)
@ -469,6 +470,7 @@ static const ctl_named_node_t opt_node[] = {
{NAME("prof_gdump"), CTL(opt_prof_gdump)}, {NAME("prof_gdump"), CTL(opt_prof_gdump)},
{NAME("prof_final"), CTL(opt_prof_final)}, {NAME("prof_final"), CTL(opt_prof_final)},
{NAME("prof_leak"), CTL(opt_prof_leak)}, {NAME("prof_leak"), CTL(opt_prof_leak)},
{NAME("prof_leak_error"), CTL(opt_prof_leak_error)},
{NAME("prof_accum"), CTL(opt_prof_accum)}, {NAME("prof_accum"), CTL(opt_prof_accum)},
{NAME("prof_recent_alloc_max"), CTL(opt_prof_recent_alloc_max)}, {NAME("prof_recent_alloc_max"), CTL(opt_prof_recent_alloc_max)},
{NAME("prof_stats"), CTL(opt_prof_stats)}, {NAME("prof_stats"), CTL(opt_prof_stats)},
@ -2201,6 +2203,7 @@ CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool) CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool) CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool) CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)
CTL_RO_NL_CGEN(config_prof, opt_prof_leak_error, opt_prof_leak_error, bool)
CTL_RO_NL_CGEN(config_prof, opt_prof_recent_alloc_max, CTL_RO_NL_CGEN(config_prof, opt_prof_recent_alloc_max,
opt_prof_recent_alloc_max, ssize_t) opt_prof_recent_alloc_max, ssize_t)
CTL_RO_NL_CGEN(config_prof, opt_prof_stats, opt_prof_stats, bool) CTL_RO_NL_CGEN(config_prof, opt_prof_stats, opt_prof_stats, bool)

View File

@ -1578,6 +1578,26 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
CONF_HANDLE_BOOL(opt_prof_gdump, "prof_gdump") CONF_HANDLE_BOOL(opt_prof_gdump, "prof_gdump")
CONF_HANDLE_BOOL(opt_prof_final, "prof_final") CONF_HANDLE_BOOL(opt_prof_final, "prof_final")
CONF_HANDLE_BOOL(opt_prof_leak, "prof_leak") CONF_HANDLE_BOOL(opt_prof_leak, "prof_leak")
if (CONF_MATCH("prof_leak_error")) {
if (CONF_MATCH_VALUE("true")) {
if (!opt_prof_final) {
CONF_ERROR(
"prof_leak_error is"
" not allowed"
" without"
" prof_leak_final",
k, klen, v, vlen);
} else {
opt_prof_leak = true;
opt_prof_leak_error =
true;
}
} else if (!CONF_MATCH_VALUE("false")) {
CONF_ERROR("Invalid conf value",
k, klen, v, vlen);
}
CONF_CONTINUE;
}
CONF_HANDLE_BOOL(opt_prof_log, "prof_log") CONF_HANDLE_BOOL(opt_prof_log, "prof_log")
CONF_HANDLE_SSIZE_T(opt_prof_recent_alloc_max, CONF_HANDLE_SSIZE_T(opt_prof_recent_alloc_max,
"prof_recent_alloc_max", -1, SSIZE_MAX) "prof_recent_alloc_max", -1, SSIZE_MAX)

View File

@ -31,6 +31,7 @@ ssize_t opt_lg_prof_interval = LG_PROF_INTERVAL_DEFAULT;
bool opt_prof_gdump = false; bool opt_prof_gdump = false;
bool opt_prof_final = false; bool opt_prof_final = false;
bool opt_prof_leak = false; bool opt_prof_leak = false;
bool opt_prof_leak_error = false;
bool opt_prof_accum = false; bool opt_prof_accum = false;
char opt_prof_prefix[PROF_DUMP_FILENAME_LEN]; char opt_prof_prefix[PROF_DUMP_FILENAME_LEN];
bool opt_prof_sys_thread_name = false; bool opt_prof_sys_thread_name = false;

View File

@ -1037,6 +1037,16 @@ prof_leakcheck(const prof_cnt_t *cnt_all, size_t leak_ngctx) {
1) ? "s" : "", leak_ngctx, (leak_ngctx != 1) ? "s" : ""); 1) ? "s" : "", leak_ngctx, (leak_ngctx != 1) ? "s" : "");
malloc_printf( malloc_printf(
"<jemalloc>: Run jeprof on dump output for leak detail\n"); "<jemalloc>: Run jeprof on dump output for leak detail\n");
if (opt_prof_leak_error) {
malloc_printf(
"<jemalloc>: Exiting with error code because memory"
" leaks were detected\n");
/*
* Use _exit() with underscore to avoid calling atexit()
* and entering endless cycle.
*/
_exit(1);
}
} }
#endif #endif
} }

View File

@ -1530,6 +1530,7 @@ stats_general_print(emitter_t *emitter) {
OPT_WRITE_BOOL("prof_gdump") OPT_WRITE_BOOL("prof_gdump")
OPT_WRITE_BOOL("prof_final") OPT_WRITE_BOOL("prof_final")
OPT_WRITE_BOOL("prof_leak") OPT_WRITE_BOOL("prof_leak")
OPT_WRITE_BOOL("prof_leak_error")
OPT_WRITE_BOOL("stats_print") OPT_WRITE_BOOL("stats_print")
OPT_WRITE_CHAR_P("stats_print_opts") OPT_WRITE_CHAR_P("stats_print_opts")
OPT_WRITE_BOOL("stats_print") OPT_WRITE_BOOL("stats_print")

View File

@ -320,6 +320,7 @@ TEST_BEGIN(test_mallctl_opt) {
TEST_MALLCTL_OPT(bool, prof_gdump, prof); TEST_MALLCTL_OPT(bool, prof_gdump, prof);
TEST_MALLCTL_OPT(bool, prof_final, prof); TEST_MALLCTL_OPT(bool, prof_final, prof);
TEST_MALLCTL_OPT(bool, prof_leak, prof); TEST_MALLCTL_OPT(bool, prof_leak, prof);
TEST_MALLCTL_OPT(bool, prof_leak_error, prof);
TEST_MALLCTL_OPT(ssize_t, prof_recent_alloc_max, prof); TEST_MALLCTL_OPT(ssize_t, prof_recent_alloc_max, prof);
TEST_MALLCTL_OPT(bool, prof_stats, prof); TEST_MALLCTL_OPT(bool, prof_stats, prof);
TEST_MALLCTL_OPT(bool, prof_sys_thread_name, prof); TEST_MALLCTL_OPT(bool, prof_sys_thread_name, prof);