Allow setting a dump hook
If users want to be notified when a heap dump occurs, they can set this hook.
This commit is contained in:
committed by
Alexander Lapenkov
parent
f7d46b8119
commit
a9031a0970
32
src/ctl.c
32
src/ctl.c
@@ -306,6 +306,7 @@ CTL_PROTO(stats_zero_reallocs)
|
||||
CTL_PROTO(experimental_hooks_install)
|
||||
CTL_PROTO(experimental_hooks_remove)
|
||||
CTL_PROTO(experimental_hooks_prof_backtrace)
|
||||
CTL_PROTO(experimental_hooks_prof_dump)
|
||||
CTL_PROTO(experimental_thread_activity_callback)
|
||||
CTL_PROTO(experimental_utilization_query)
|
||||
CTL_PROTO(experimental_utilization_batch_query)
|
||||
@@ -835,7 +836,8 @@ static const ctl_named_node_t stats_node[] = {
|
||||
static const ctl_named_node_t experimental_hooks_node[] = {
|
||||
{NAME("install"), CTL(experimental_hooks_install)},
|
||||
{NAME("remove"), CTL(experimental_hooks_remove)},
|
||||
{NAME("prof_backtrace"), CTL(experimental_hooks_prof_backtrace)}
|
||||
{NAME("prof_backtrace"), CTL(experimental_hooks_prof_backtrace)},
|
||||
{NAME("prof_dump"), CTL(experimental_hooks_prof_dump)},
|
||||
};
|
||||
|
||||
static const ctl_named_node_t experimental_thread_node[] = {
|
||||
@@ -3362,6 +3364,34 @@ label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
experimental_hooks_prof_dump_ctl(tsd_t *tsd, const size_t *mib,
|
||||
size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
|
||||
if (oldp == NULL && newp == NULL) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
if (oldp != NULL) {
|
||||
prof_dump_hook_t old_hook =
|
||||
prof_dump_hook_get();
|
||||
READ(old_hook, prof_dump_hook_t);
|
||||
}
|
||||
if (newp != NULL) {
|
||||
if (!opt_prof) {
|
||||
ret = ENOENT;
|
||||
goto label_return;
|
||||
}
|
||||
prof_dump_hook_t new_hook JEMALLOC_CC_SILENCE_INIT(NULL);
|
||||
WRITE(new_hook, prof_dump_hook_t);
|
||||
prof_dump_hook_set(new_hook);
|
||||
}
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats->allocated, size_t)
|
||||
|
16
src/prof.c
16
src/prof.c
@@ -73,6 +73,9 @@ bool prof_booted = false;
|
||||
/* Logically a prof_backtrace_hook_t. */
|
||||
atomic_p_t prof_backtrace_hook;
|
||||
|
||||
/* Logically a prof_dump_hook_t. */
|
||||
atomic_p_t prof_dump_hook;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void
|
||||
@@ -533,6 +536,17 @@ prof_backtrace_hook_get() {
|
||||
ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
void
|
||||
prof_dump_hook_set(prof_dump_hook_t hook) {
|
||||
atomic_store_p(&prof_dump_hook, hook, ATOMIC_RELEASE);
|
||||
}
|
||||
|
||||
prof_dump_hook_t
|
||||
prof_dump_hook_get() {
|
||||
return (prof_dump_hook_t)atomic_load_p(&prof_dump_hook,
|
||||
ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
void
|
||||
prof_boot0(void) {
|
||||
cassert(config_prof);
|
||||
@@ -672,8 +686,8 @@ prof_boot2(tsd_t *tsd, base_t *base) {
|
||||
}
|
||||
}
|
||||
|
||||
prof_hooks_init();
|
||||
prof_unwind_init();
|
||||
prof_hooks_init();
|
||||
}
|
||||
prof_booted = true;
|
||||
|
||||
|
@@ -55,6 +55,7 @@ prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) {
|
||||
cassert(config_prof);
|
||||
assert(*len == 0);
|
||||
assert(vec != NULL);
|
||||
assert(max_len == PROF_BT_MAX);
|
||||
|
||||
nframes = unw_backtrace(vec, PROF_BT_MAX);
|
||||
if (nframes <= 0) {
|
||||
@@ -95,6 +96,8 @@ prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) {
|
||||
prof_unwind_data_t data = {vec, len, max_len};
|
||||
|
||||
cassert(config_prof);
|
||||
assert(vec != NULL);
|
||||
assert(max_len == PROF_BT_MAX);
|
||||
|
||||
_Unwind_Backtrace(prof_unwind_callback, &data);
|
||||
}
|
||||
@@ -118,6 +121,8 @@ prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) {
|
||||
}
|
||||
|
||||
cassert(config_prof);
|
||||
assert(vec != NULL);
|
||||
assert(max_len == PROF_BT_MAX);
|
||||
|
||||
BT_FRAME(0)
|
||||
BT_FRAME(1)
|
||||
@@ -272,8 +277,10 @@ prof_backtrace_impl(void **vec, unsigned *len, unsigned max_len) {
|
||||
void
|
||||
prof_backtrace(tsd_t *tsd, prof_bt_t *bt) {
|
||||
cassert(config_prof);
|
||||
pre_reentrancy(tsd, NULL);
|
||||
prof_backtrace_hook_t prof_backtrace_hook = prof_backtrace_hook_get();
|
||||
assert(prof_backtrace_hook != NULL);
|
||||
|
||||
pre_reentrancy(tsd, NULL);
|
||||
prof_backtrace_hook(bt->vec, &bt->len, PROF_BT_MAX);
|
||||
post_reentrancy(tsd);
|
||||
}
|
||||
@@ -281,6 +288,7 @@ prof_backtrace(tsd_t *tsd, prof_bt_t *bt) {
|
||||
void
|
||||
prof_hooks_init() {
|
||||
prof_backtrace_hook_set(&prof_backtrace_impl);
|
||||
prof_dump_hook_set(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -506,6 +514,10 @@ prof_dump(tsd_t *tsd, bool propagate_err, const char *filename,
|
||||
buf_writer_terminate(tsd_tsdn(tsd), &buf_writer);
|
||||
prof_dump_close(&arg);
|
||||
|
||||
prof_dump_hook_t dump_hook = prof_dump_hook_get();
|
||||
if (dump_hook != NULL) {
|
||||
dump_hook(filename);
|
||||
}
|
||||
malloc_mutex_unlock(tsd_tsdn(tsd), &prof_dump_mtx);
|
||||
post_reentrancy(tsd);
|
||||
|
||||
|
Reference in New Issue
Block a user