Add "prof.dump_prefix" to override filename prefixes for dumps.

This commit is contained in:
zhxchen17 2019-09-09 20:18:41 -07:00 committed by Qi Wang
parent 242af439b8
commit 4b76c684bb
8 changed files with 166 additions and 38 deletions

View File

@ -1344,7 +1344,10 @@ malloc_conf = "xmalloc:true";]]></programlisting>
set to the empty string, no automatic dumps will occur; this is set to the empty string, no automatic dumps will occur; this is
primarily useful for disabling the automatic final heap dump (which primarily useful for disabling the automatic final heap dump (which
also disables leak reporting, if enabled). The default prefix is also disables leak reporting, if enabled). The default prefix is
<filename>jeprof</filename>.</para></listitem> <filename>jeprof</filename>. This prefix value can be overriden by
<link
linkend="prof.dump_prefix"><mallctl>prof.dump_prefix</mallctl></link>.
</para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="opt.prof_active"> <varlistentry id="opt.prof_active">
@ -1423,8 +1426,10 @@ malloc_conf = "xmalloc:true";]]></programlisting>
<filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.i&lt;iseq&gt;.heap</filename>, <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.i&lt;iseq&gt;.heap</filename>,
where <literal>&lt;prefix&gt;</literal> is controlled by the where <literal>&lt;prefix&gt;</literal> is controlled by the
<link <link
linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> and
option. By default, interval-triggered profile dumping is disabled <link
linkend="prof.dump_prefix"><mallctl>prof.dump_prefix</mallctl></link>
options. By default, interval-triggered profile dumping is disabled
(encoded as -1). (encoded as -1).
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
@ -1456,8 +1461,10 @@ malloc_conf = "xmalloc:true";]]></programlisting>
usage to a file named according to the pattern usage to a file named according to the pattern
<filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.f.heap</filename>, <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.f.heap</filename>,
where <literal>&lt;prefix&gt;</literal> is controlled by the <link where <literal>&lt;prefix&gt;</literal> is controlled by the <link
linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> and
option. Note that <function>atexit()</function> may allocate <link
linkend="prof.dump_prefix"><mallctl>prof.dump_prefix</mallctl></link>
options. Note that <function>atexit()</function> may allocate
memory during application initialization and then deadlock internally memory during application initialization and then deadlock internally
when jemalloc in turn calls <function>atexit()</function>, so when jemalloc in turn calls <function>atexit()</function>, so
this option is not universally usable (though the application can this option is not universally usable (though the application can
@ -2224,8 +2231,25 @@ struct extent_hooks_s {
<filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.m&lt;mseq&gt;.heap</filename>, <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.m&lt;mseq&gt;.heap</filename>,
where <literal>&lt;prefix&gt;</literal> is controlled by the where <literal>&lt;prefix&gt;</literal> is controlled by the
<link <link
linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> and
<link
linkend="prof.dump_prefix"><mallctl>prof.dump_prefix</mallctl></link>
options.</para></listitem>
</varlistentry>
<varlistentry id="prof.dump_prefix">
<term>
<mallctl>prof.dump_prefix</mallctl>
(<type>const char *</type>)
<literal>-w</literal>
[<option>--enable-prof</option>]
</term>
<listitem><para>Set the filename prefix for profile dumps. See
<link
linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link>
option.</para></listitem> for the default setting. This can be useful to differentiate profile
dumps such as from forked processes.
</para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="prof.gdump"> <varlistentry id="prof.gdump">
@ -2240,8 +2264,10 @@ struct extent_hooks_s {
dumped to files named according to the pattern dumped to files named according to the pattern
<filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.u&lt;useq&gt;.heap</filename>, <filename>&lt;prefix&gt;.&lt;pid&gt;.&lt;seq&gt;.u&lt;useq&gt;.heap</filename>,
where <literal>&lt;prefix&gt;</literal> is controlled by the <link where <literal>&lt;prefix&gt;</literal> is controlled by the <link
linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> linkend="opt.prof_prefix"><mallctl>opt.prof_prefix</mallctl></link> and
option.</para></listitem> <link
linkend="prof.dump_prefix"><mallctl>prof.dump_prefix</mallctl></link>
options.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry id="prof.reset"> <varlistentry id="prof.reset">

View File

@ -103,6 +103,7 @@ bool ctl_boot(void);
void ctl_prefork(tsdn_t *tsdn); void ctl_prefork(tsdn_t *tsdn);
void ctl_postfork_parent(tsdn_t *tsdn); void ctl_postfork_parent(tsdn_t *tsdn);
void ctl_postfork_child(tsdn_t *tsdn); void ctl_postfork_child(tsdn_t *tsdn);
void ctl_mtx_assert_held(tsdn_t *tsdn);
#define xmallctl(name, oldp, oldlenp, newp, newlen) do { \ #define xmallctl(name, oldp, oldlenp, newp, newlen) do { \
if (je_mallctl(name, oldp, oldlenp, newp, newlen) \ if (je_mallctl(name, oldp, oldlenp, newp, newlen) \

View File

@ -72,10 +72,12 @@ void prof_cnt_all(uint64_t *curobjs, uint64_t *curbytes, uint64_t *accumobjs,
uint64_t *accumbytes); uint64_t *accumbytes);
#endif #endif
int prof_getpid(void); int prof_getpid(void);
void prof_get_default_filename(tsdn_t *tsdn, char *filename, uint64_t ind);
bool prof_accum_init(tsdn_t *tsdn, prof_accum_t *prof_accum); bool prof_accum_init(tsdn_t *tsdn, prof_accum_t *prof_accum);
void prof_idump(tsdn_t *tsdn); void prof_idump(tsdn_t *tsdn);
bool prof_mdump(tsd_t *tsd, const char *filename); bool prof_mdump(tsd_t *tsd, const char *filename);
void prof_gdump(tsdn_t *tsdn); void prof_gdump(tsdn_t *tsdn);
bool prof_dump_prefix_set(tsdn_t *tsdn, const char *prefix);
void prof_bt_hash(const void *key, size_t r_hash[2]); void prof_bt_hash(const void *key, size_t r_hash[2]);
bool prof_bt_keycomp(const void *k1, const void *k2); bool prof_bt_keycomp(const void *k1, const void *k2);

View File

@ -53,4 +53,11 @@ typedef struct prof_tdata_s prof_tdata_t;
#define PROF_TDATA_STATE_PURGATORY ((prof_tdata_t *)(uintptr_t)2) #define PROF_TDATA_STATE_PURGATORY ((prof_tdata_t *)(uintptr_t)2)
#define PROF_TDATA_STATE_MAX PROF_TDATA_STATE_PURGATORY #define PROF_TDATA_STATE_MAX PROF_TDATA_STATE_PURGATORY
/* Minimize memory bloat for non-prof builds. */
#ifdef JEMALLOC_PROF
#define PROF_DUMP_FILENAME_LEN (PATH_MAX + 1)
#else
#define PROF_DUMP_FILENAME_LEN 1
#endif
#endif /* JEMALLOC_INTERNAL_PROF_TYPES_H */ #endif /* JEMALLOC_INTERNAL_PROF_TYPES_H */

View File

@ -148,6 +148,7 @@ CTL_PROTO(prof_thread_active_init)
CTL_PROTO(prof_active) CTL_PROTO(prof_active)
CTL_PROTO(prof_dump) CTL_PROTO(prof_dump)
CTL_PROTO(prof_gdump) CTL_PROTO(prof_gdump)
CTL_PROTO(prof_dump_prefix)
CTL_PROTO(prof_reset) CTL_PROTO(prof_reset)
CTL_PROTO(prof_interval) CTL_PROTO(prof_interval)
CTL_PROTO(lg_prof_sample) CTL_PROTO(lg_prof_sample)
@ -413,6 +414,7 @@ static const ctl_named_node_t prof_node[] = {
{NAME("active"), CTL(prof_active)}, {NAME("active"), CTL(prof_active)},
{NAME("dump"), CTL(prof_dump)}, {NAME("dump"), CTL(prof_dump)},
{NAME("gdump"), CTL(prof_gdump)}, {NAME("gdump"), CTL(prof_gdump)},
{NAME("dump_prefix"), CTL(prof_dump_prefix)},
{NAME("reset"), CTL(prof_reset)}, {NAME("reset"), CTL(prof_reset)},
{NAME("interval"), CTL(prof_interval)}, {NAME("interval"), CTL(prof_interval)},
{NAME("lg_sample"), CTL(lg_prof_sample)}, {NAME("lg_sample"), CTL(lg_prof_sample)},
@ -1416,6 +1418,11 @@ ctl_postfork_child(tsdn_t *tsdn) {
malloc_mutex_postfork_child(tsdn, &ctl_mtx); malloc_mutex_postfork_child(tsdn, &ctl_mtx);
} }
void
ctl_mtx_assert_held(tsdn_t *tsdn) {
malloc_mutex_assert_owner(tsdn, &ctl_mtx);
}
/******************************************************************************/ /******************************************************************************/
/* *_ctl() functions. */ /* *_ctl() functions. */
@ -2720,6 +2727,26 @@ label_return:
return ret; return ret;
} }
static int
prof_dump_prefix_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
int ret;
const char *prefix = NULL;
if (!config_prof) {
return ENOENT;
}
malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
WRITEONLY();
WRITE(prefix, const char *);
ret = prof_dump_prefix_set(tsd_tsdn(tsd), prefix) ? EFAULT : 0;
label_return:
malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
return ret;
}
static int static int
prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { void *oldp, size_t *oldlenp, void *newp, size_t newlen) {

View File

@ -2,6 +2,7 @@
#include "jemalloc/internal/jemalloc_preamble.h" #include "jemalloc/internal/jemalloc_preamble.h"
#include "jemalloc/internal/jemalloc_internal_includes.h" #include "jemalloc/internal/jemalloc_internal_includes.h"
#include "jemalloc/internal/ctl.h"
#include "jemalloc/internal/assert.h" #include "jemalloc/internal/assert.h"
#include "jemalloc/internal/mutex.h" #include "jemalloc/internal/mutex.h"
@ -41,12 +42,7 @@ 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_accum = false; bool opt_prof_accum = false;
char opt_prof_prefix[ char opt_prof_prefix[PROF_DUMP_FILENAME_LEN];
/* Minimize memory bloat for non-prof builds. */
#ifdef JEMALLOC_PROF
PATH_MAX +
#endif
1];
/* /*
* Initialized as opt_prof_active, and accessed via * Initialized as opt_prof_active, and accessed via
@ -106,6 +102,7 @@ static uint64_t prof_dump_mseq;
static uint64_t prof_dump_useq; static uint64_t prof_dump_useq;
malloc_mutex_t prof_dump_mtx; malloc_mutex_t prof_dump_mtx;
static char *prof_dump_prefix = NULL;
/* Do not dump any profiles until bootstrapping is complete. */ /* Do not dump any profiles until bootstrapping is complete. */
bool prof_booted = false; bool prof_booted = false;
@ -514,26 +511,53 @@ prof_getpid(void) {
#endif #endif
} }
static const char *
prof_dump_prefix_get(tsdn_t* tsdn) {
malloc_mutex_assert_owner(tsdn, &prof_dump_filename_mtx);
return prof_dump_prefix == NULL ? opt_prof_prefix : prof_dump_prefix;
}
static bool
prof_dump_prefix_is_empty(tsdn_t *tsdn) {
malloc_mutex_lock(tsdn, &prof_dump_filename_mtx);
bool ret = (prof_dump_prefix_get(tsdn)[0] == '\0');
malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx);
return ret;
}
#define DUMP_FILENAME_BUFSIZE (PATH_MAX + 1) #define DUMP_FILENAME_BUFSIZE (PATH_MAX + 1)
#define VSEQ_INVALID UINT64_C(0xffffffffffffffff) #define VSEQ_INVALID UINT64_C(0xffffffffffffffff)
static void static void
prof_dump_filename(char *filename, char v, uint64_t vseq) { prof_dump_filename(tsd_t *tsd, char *filename, char v, uint64_t vseq) {
cassert(config_prof); cassert(config_prof);
assert(tsd_reentrancy_level_get(tsd) == 0);
const char *prof_prefix = prof_dump_prefix_get(tsd_tsdn(tsd));
if (vseq != VSEQ_INVALID) { if (vseq != VSEQ_INVALID) {
/* "<prefix>.<pid>.<seq>.v<vseq>.heap" */ /* "<prefix>.<pid>.<seq>.v<vseq>.heap" */
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
"%s.%d.%"FMTu64".%c%"FMTu64".heap", "%s.%d.%"FMTu64".%c%"FMTu64".heap",
opt_prof_prefix, prof_getpid(), prof_dump_seq, v, vseq); prof_prefix, prof_getpid(), prof_dump_seq, v, vseq);
} else { } else {
/* "<prefix>.<pid>.<seq>.<v>.heap" */ /* "<prefix>.<pid>.<seq>.<v>.heap" */
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE, malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
"%s.%d.%"FMTu64".%c.heap", "%s.%d.%"FMTu64".%c.heap",
opt_prof_prefix, prof_getpid(), prof_dump_seq, v); prof_prefix, prof_getpid(), prof_dump_seq, v);
} }
prof_dump_seq++; prof_dump_seq++;
} }
void
prof_get_default_filename(tsdn_t *tsdn, char *filename, uint64_t ind) {
malloc_mutex_lock(tsdn, &prof_dump_filename_mtx);
malloc_snprintf(filename, PROF_DUMP_FILENAME_LEN,
"%s.%d.%"FMTu64".json", prof_dump_prefix_get(tsdn), prof_getpid(),
ind);
malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx);
}
static void static void
prof_fdump(void) { prof_fdump(void) {
tsd_t *tsd; tsd_t *tsd;
@ -541,16 +565,16 @@ prof_fdump(void) {
cassert(config_prof); cassert(config_prof);
assert(opt_prof_final); assert(opt_prof_final);
assert(opt_prof_prefix[0] != '\0');
if (!prof_booted) { if (!prof_booted) {
return; return;
} }
tsd = tsd_fetch(); tsd = tsd_fetch();
assert(tsd_reentrancy_level_get(tsd) == 0); assert(tsd_reentrancy_level_get(tsd) == 0);
assert(!prof_dump_prefix_is_empty(tsd_tsdn(tsd)));
malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_filename_mtx); malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_filename_mtx);
prof_dump_filename(filename, 'f', VSEQ_INVALID); prof_dump_filename(tsd, filename, 'f', VSEQ_INVALID);
malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_filename_mtx); malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_filename_mtx);
prof_dump(tsd, false, filename, opt_prof_leak); prof_dump(tsd, false, filename, opt_prof_leak);
} }
@ -571,6 +595,31 @@ prof_accum_init(tsdn_t *tsdn, prof_accum_t *prof_accum) {
return false; return false;
} }
bool
prof_dump_prefix_set(tsdn_t *tsdn, const char *prefix) {
cassert(config_prof);
ctl_mtx_assert_held(tsdn);
malloc_mutex_lock(tsdn, &prof_dump_filename_mtx);
if (prof_dump_prefix == NULL) {
malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx);
/* Everything is still guarded by ctl_mtx. */
char *buffer = base_alloc(tsdn, b0get(), PROF_DUMP_FILENAME_LEN,
QUANTUM);
if (buffer == NULL) {
return true;
}
malloc_mutex_lock(tsdn, &prof_dump_filename_mtx);
prof_dump_prefix = buffer;
}
assert(prof_dump_prefix != NULL);
strncpy(prof_dump_prefix, prefix, PROF_DUMP_FILENAME_LEN - 1);
prof_dump_prefix[PROF_DUMP_FILENAME_LEN - 1] = '\0';
malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx);
return false;
}
void void
prof_idump(tsdn_t *tsdn) { prof_idump(tsdn_t *tsdn) {
tsd_t *tsd; tsd_t *tsd;
@ -595,15 +644,17 @@ prof_idump(tsdn_t *tsdn) {
return; return;
} }
if (opt_prof_prefix[0] != '\0') {
char filename[PATH_MAX + 1];
malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_filename_mtx); malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_filename_mtx);
prof_dump_filename(filename, 'i', prof_dump_iseq); if (prof_dump_prefix_get(tsd_tsdn(tsd))[0] == '\0') {
malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_filename_mtx);
return;
}
char filename[PATH_MAX + 1];
prof_dump_filename(tsd, filename, 'i', prof_dump_iseq);
prof_dump_iseq++; prof_dump_iseq++;
malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_filename_mtx); malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_filename_mtx);
prof_dump(tsd, false, filename, false); prof_dump(tsd, false, filename, false);
} }
}
bool bool
prof_mdump(tsd_t *tsd, const char *filename) { prof_mdump(tsd_t *tsd, const char *filename) {
@ -616,11 +667,12 @@ prof_mdump(tsd_t *tsd, const char *filename) {
char filename_buf[DUMP_FILENAME_BUFSIZE]; char filename_buf[DUMP_FILENAME_BUFSIZE];
if (filename == NULL) { if (filename == NULL) {
/* No filename specified, so automatically generate one. */ /* No filename specified, so automatically generate one. */
if (opt_prof_prefix[0] == '\0') { malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_filename_mtx);
if (prof_dump_prefix_get(tsd_tsdn(tsd))[0] == '\0') {
malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_filename_mtx);
return true; return true;
} }
malloc_mutex_lock(tsd_tsdn(tsd), &prof_dump_filename_mtx); prof_dump_filename(tsd, filename_buf, 'm', prof_dump_mseq);
prof_dump_filename(filename_buf, 'm', prof_dump_mseq);
prof_dump_mseq++; prof_dump_mseq++;
malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_filename_mtx); malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_filename_mtx);
filename = filename_buf; filename = filename_buf;
@ -652,15 +704,17 @@ prof_gdump(tsdn_t *tsdn) {
return; return;
} }
if (opt_prof_prefix[0] != '\0') {
char filename[DUMP_FILENAME_BUFSIZE];
malloc_mutex_lock(tsdn, &prof_dump_filename_mtx); malloc_mutex_lock(tsdn, &prof_dump_filename_mtx);
prof_dump_filename(filename, 'u', prof_dump_useq); if (prof_dump_prefix_get(tsdn)[0] == '\0') {
malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx);
return;
}
char filename[DUMP_FILENAME_BUFSIZE];
prof_dump_filename(tsd, filename, 'u', prof_dump_useq);
prof_dump_useq++; prof_dump_useq++;
malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx); malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx);
prof_dump(tsd, false, filename, false); prof_dump(tsd, false, filename, false);
} }
}
static uint64_t static uint64_t
prof_thr_uid_alloc(tsdn_t *tsdn) { prof_thr_uid_alloc(tsdn_t *tsdn) {

View File

@ -405,7 +405,6 @@ prof_log_start(tsdn_t *tsdn, const char *filename) {
} }
bool ret = false; bool ret = false;
size_t buf_size = PATH_MAX + 1;
malloc_mutex_lock(tsdn, &log_mtx); malloc_mutex_lock(tsdn, &log_mtx);
@ -413,11 +412,10 @@ prof_log_start(tsdn_t *tsdn, const char *filename) {
ret = true; ret = true;
} else if (filename == NULL) { } else if (filename == NULL) {
/* Make default name. */ /* Make default name. */
malloc_snprintf(log_filename, buf_size, "%s.%d.%"FMTu64".json", prof_get_default_filename(tsdn, log_filename, log_seq);
opt_prof_prefix, prof_getpid(), log_seq);
log_seq++; log_seq++;
prof_logging_state = prof_logging_state_started; prof_logging_state = prof_logging_state_started;
} else if (strlen(filename) >= buf_size) { } else if (strlen(filename) >= PROF_DUMP_FILENAME_LEN) {
ret = true; ret = true;
} else { } else {
strcpy(log_filename, filename); strcpy(log_filename, filename);

View File

@ -1,5 +1,7 @@
#include "test/jemalloc_test.h" #include "test/jemalloc_test.h"
#define TEST_PREFIX "test_prefix"
static bool did_prof_dump_open; static bool did_prof_dump_open;
static int static int
@ -8,6 +10,10 @@ prof_dump_open_intercept(bool propagate_err, const char *filename) {
did_prof_dump_open = true; did_prof_dump_open = true;
const char filename_prefix[] = TEST_PREFIX ".";
assert_d_eq(strncmp(filename_prefix, filename, sizeof(filename_prefix)
- 1), 0, "Dump file name should start with \"" TEST_PREFIX ".\"");
fd = open("/dev/null", O_WRONLY); fd = open("/dev/null", O_WRONLY);
assert_d_ne(fd, -1, "Unexpected open() failure"); assert_d_ne(fd, -1, "Unexpected open() failure");
@ -18,9 +24,16 @@ TEST_BEGIN(test_idump) {
bool active; bool active;
void *p; void *p;
const char *dump_prefix = TEST_PREFIX;
test_skip_if(!config_prof); test_skip_if(!config_prof);
active = true; active = true;
assert_d_eq(mallctl("prof.dump_prefix", NULL, NULL,
(void *)&dump_prefix, sizeof(dump_prefix)), 0,
"Unexpected mallctl failure while overwriting dump prefix");
assert_d_eq(mallctl("prof.active", NULL, NULL, (void *)&active, assert_d_eq(mallctl("prof.active", NULL, NULL, (void *)&active,
sizeof(active)), 0, sizeof(active)), 0,
"Unexpected mallctl failure while activating profiling"); "Unexpected mallctl failure while activating profiling");