perf srcline: Add a timeout to reading from addr2line
addr2line may fail to send expected values causing perf to wait indefinitely. Add a 1 second timeout (twice the timeout for reading from /proc/pid/maps) so that such reads don't cause perf to appear to lock up. There are already checks that the file for addr2line contains a debug section but this isn't always sufficient. The problem was observed when a valid elf file would set the configuration for binutils addr2line, then a later read of vmlinux with ELF debug sections would cause a failing write/read which would block indefinitely. As a service to future readers, if the io hits eof or an error, cleanup the addr2line process. Signed-off-by: Ian Rogers <irogers@google.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Yang Jihong <yangjihong1@huawei.com> Link: https://lore.kernel.org/r/20230608061812.3715566-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Родитель
f4c0d5309a
Коммит
701677b957
|
@ -19,6 +19,7 @@
|
||||||
#include "util/llvm-utils.h" /* perf_llvm_config */
|
#include "util/llvm-utils.h" /* perf_llvm_config */
|
||||||
#include "util/stat.h" /* perf_stat__set_big_num */
|
#include "util/stat.h" /* perf_stat__set_big_num */
|
||||||
#include "util/evsel.h" /* evsel__hw_names, evsel__use_bpf_counters */
|
#include "util/evsel.h" /* evsel__hw_names, evsel__use_bpf_counters */
|
||||||
|
#include "util/srcline.h" /* addr2line_timeout_ms */
|
||||||
#include "build-id.h"
|
#include "build-id.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -434,12 +435,14 @@ static int perf_buildid_config(const char *var, const char *value)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int perf_default_core_config(const char *var __maybe_unused,
|
static int perf_default_core_config(const char *var, const char *value)
|
||||||
const char *value __maybe_unused)
|
|
||||||
{
|
{
|
||||||
if (!strcmp(var, "core.proc-map-timeout"))
|
if (!strcmp(var, "core.proc-map-timeout"))
|
||||||
proc_map_timeout = strtoul(value, NULL, 10);
|
proc_map_timeout = strtoul(value, NULL, 10);
|
||||||
|
|
||||||
|
if (!strcmp(var, "core.addr2line-timeout"))
|
||||||
|
addr2line_timeout_ms = strtoul(value, NULL, 10);
|
||||||
|
|
||||||
/* Add other config variables here. */
|
/* Add other config variables here. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "symbol.h"
|
#include "symbol.h"
|
||||||
#include "subcmd/run-command.h"
|
#include "subcmd/run-command.h"
|
||||||
|
|
||||||
|
/* If addr2line doesn't return data for 1 second then timeout. */
|
||||||
|
int addr2line_timeout_ms = 1 * 1000;
|
||||||
bool srcline_full_filename;
|
bool srcline_full_filename;
|
||||||
|
|
||||||
char *srcline__unknown = (char *)"??:0";
|
char *srcline__unknown = (char *)"??:0";
|
||||||
|
@ -631,7 +633,7 @@ static int addr2line(const char *dso_name, u64 addr,
|
||||||
int len;
|
int len;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
ssize_t written;
|
ssize_t written;
|
||||||
struct io io;
|
struct io io = { .eof = false };
|
||||||
enum a2l_style a2l_style;
|
enum a2l_style a2l_style;
|
||||||
|
|
||||||
if (!a2l) {
|
if (!a2l) {
|
||||||
|
@ -670,7 +672,7 @@ static int addr2line(const char *dso_name, u64 addr,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
io__init(&io, a2l->out, buf, sizeof(buf));
|
io__init(&io, a2l->out, buf, sizeof(buf));
|
||||||
|
io.timeout_ms = addr2line_timeout_ms;
|
||||||
switch (read_addr2line_record(&io, a2l_style,
|
switch (read_addr2line_record(&io, a2l_style,
|
||||||
&record_function, &record_filename, &record_line_nr)) {
|
&record_function, &record_filename, &record_line_nr)) {
|
||||||
case -1:
|
case -1:
|
||||||
|
@ -741,6 +743,10 @@ static int addr2line(const char *dso_name, u64 addr,
|
||||||
out:
|
out:
|
||||||
free(record_function);
|
free(record_function);
|
||||||
free(record_filename);
|
free(record_filename);
|
||||||
|
if (io.eof) {
|
||||||
|
dso->a2l = NULL;
|
||||||
|
addr2line_subprocess_cleanup(a2l);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
struct dso;
|
struct dso;
|
||||||
struct symbol;
|
struct symbol;
|
||||||
|
|
||||||
|
extern int addr2line_timeout_ms;
|
||||||
extern bool srcline_full_filename;
|
extern bool srcline_full_filename;
|
||||||
char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
|
char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym,
|
||||||
bool show_sym, bool show_addr, u64 ip);
|
bool show_sym, bool show_addr, u64 ip);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче