Add support for namespace pids in heap profile names

This change adds support for writing pid namespaces to the filename of a
heap profile. When running with namespaces pids may reused across
namespaces and if mounts are shared where profiles are written there is
not a great way to differentiate profiles between pids.

Signed-off-by: Daniel Hodges <hodges.daniel.scott@gmail.com>
Signed-off-by: Daniel Hodges <hodgesd@fb.com>
This commit is contained in:
Daniel Hodges 2023-12-23 19:40:44 -05:00 committed by Qi Wang
parent 83b075789b
commit 11038ff762
7 changed files with 93 additions and 10 deletions

View file

@ -153,6 +153,7 @@ CTL_PROTO(opt_prof_final)
CTL_PROTO(opt_prof_leak)
CTL_PROTO(opt_prof_leak_error)
CTL_PROTO(opt_prof_accum)
CTL_PROTO(opt_prof_pid_namespace)
CTL_PROTO(opt_prof_recent_alloc_max)
CTL_PROTO(opt_prof_stats)
CTL_PROTO(opt_prof_sys_thread_name)
@ -507,6 +508,7 @@ static const ctl_named_node_t opt_node[] = {
{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_pid_namespace"), CTL(opt_prof_pid_namespace)},
{NAME("prof_recent_alloc_max"), CTL(opt_prof_recent_alloc_max)},
{NAME("prof_stats"), CTL(opt_prof_stats)},
{NAME("prof_sys_thread_name"), CTL(opt_prof_sys_thread_name)},
@ -2226,6 +2228,8 @@ CTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init,
CTL_RO_NL_CGEN(config_prof, opt_prof_bt_max, opt_prof_bt_max, unsigned)
CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
CTL_RO_NL_CGEN(config_prof, opt_prof_pid_namespace, opt_prof_pid_namespace,
bool)
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_final, opt_prof_final, bool)

View file

@ -1628,6 +1628,7 @@ malloc_conf_init_helper(sc_data_t *sc_data, unsigned bin_shard_sizes[SC_NBINS],
CONF_HANDLE_BOOL(opt_prof_leak_error,
"prof_leak_error")
CONF_HANDLE_BOOL(opt_prof_log, "prof_log")
CONF_HANDLE_BOOL(opt_prof_pid_namespace, "prof_pid_namespace")
CONF_HANDLE_SSIZE_T(opt_prof_recent_alloc_max,
"prof_recent_alloc_max", -1, SSIZE_MAX)
CONF_HANDLE_BOOL(opt_prof_stats, "prof_stats")

View file

@ -34,6 +34,7 @@ bool opt_prof_final = false;
bool opt_prof_leak = false;
bool opt_prof_leak_error = false;
bool opt_prof_accum = false;
bool opt_prof_pid_namespace = false;
char opt_prof_prefix[PROF_DUMP_FILENAME_LEN];
bool opt_prof_sys_thread_name = false;
bool opt_prof_unbias = true;

View file

@ -484,6 +484,41 @@ prof_getpid(void) {
#endif
}
long
prof_get_pid_namespace() {
long ret = 0;
#if defined(_WIN32) || defined(__APPLE__)
// Not supported, do nothing.
#else
char buf[PATH_MAX];
const char* linkname =
# if defined(__FreeBSD__) || defined(__DragonFly__)
"/proc/curproc/ns/pid"
# else
"/proc/self/ns/pid"
# endif
;
ssize_t linklen =
# ifndef JEMALLOC_READLINKAT
readlink(linkname, buf, PATH_MAX)
# else
readlinkat(AT_FDCWD, linkname, buf, PATH_MAX)
# endif
;
// namespace string is expected to be like pid:[4026531836]
if (linklen > 0) {
// Trim the trailing "]"
buf[linklen-1] = '\0';
char* index = strtok(buf, "pid:[");
ret = atol(index);
}
#endif
return ret;
}
/*
* This buffer is rather large for stack allocation, so use a single buffer for
* all profile dumps; protected by prof_dump_mtx.
@ -713,15 +748,30 @@ prof_dump_filename(tsd_t *tsd, char *filename, char v, uint64_t vseq) {
const char *prefix = prof_prefix_get(tsd_tsdn(tsd));
if (vseq != VSEQ_INVALID) {
/* "<prefix>.<pid>.<seq>.v<vseq>.heap" */
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
"%s.%d.%"FMTu64".%c%"FMTu64".heap", prefix, prof_getpid(),
prof_dump_seq, v, vseq);
if (opt_prof_pid_namespace) {
/* "<prefix>.<pid_namespace>.<pid>.<seq>.v<vseq>.heap" */
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
"%s.%ld.%d.%"FMTu64".%c%"FMTu64".heap", prefix,
prof_get_pid_namespace(), prof_getpid(), prof_dump_seq, v,
vseq);
} else {
/* "<prefix>.<pid>.<seq>.v<vseq>.heap" */
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
"%s.%d.%"FMTu64".%c%"FMTu64".heap", prefix, prof_getpid(),
prof_dump_seq, v, vseq);
}
} else {
/* "<prefix>.<pid>.<seq>.<v>.heap" */
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
"%s.%d.%"FMTu64".%c.heap", prefix, prof_getpid(),
prof_dump_seq, v);
if (opt_prof_pid_namespace) {
/* "<prefix>.<pid_namespace>.<pid>.<seq>.<v>.heap" */
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
"%s.%ld.%d.%"FMTu64".%c.heap", prefix,
prof_get_pid_namespace(), prof_getpid(), prof_dump_seq, v);
} else {
/* "<prefix>.<pid>.<seq>.<v>.heap" */
malloc_snprintf(filename, DUMP_FILENAME_BUFSIZE,
"%s.%d.%"FMTu64".%c.heap", prefix, prof_getpid(),
prof_dump_seq, v);
}
}
prof_dump_seq++;
}
@ -729,8 +779,14 @@ prof_dump_filename(tsd_t *tsd, char *filename, char v, uint64_t vseq) {
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_prefix_get(tsdn), prof_getpid(), ind);
if (opt_prof_pid_namespace) {
malloc_snprintf(filename, PROF_DUMP_FILENAME_LEN,
"%s.%ld.%d.%"FMTu64".json", prof_prefix_get(tsdn),
prof_get_pid_namespace(), prof_getpid(), ind);
} else {
malloc_snprintf(filename, PROF_DUMP_FILENAME_LEN,
"%s.%d.%"FMTu64".json", prof_prefix_get(tsdn), prof_getpid(), ind);
}
malloc_mutex_unlock(tsdn, &prof_dump_filename_mtx);
}