diff options
author | Ian Rogers <irogers@google.com> | 2023-06-07 23:18:12 -0700 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2023-06-14 18:19:06 -0300 |
commit | 701677b95764c06bb058c92be11c3a4ad25ab5f2 (patch) | |
tree | 3fb3b56c1fa8a39221f42aad9d8bf47e5ee22a69 | |
parent | f4c0d5309a3e5f16ca3c3854b1e719dace843e03 (diff) | |
download | lwn-701677b95764c06bb058c92be11c3a4ad25ab5f2.tar.gz lwn-701677b95764c06bb058c92be11c3a4ad25ab5f2.zip |
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>
-rw-r--r-- | tools/perf/util/config.c | 7 | ||||
-rw-r--r-- | tools/perf/util/srcline.c | 10 | ||||
-rw-r--r-- | tools/perf/util/srcline.h | 1 |
3 files changed, 14 insertions, 4 deletions
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c index f340dc73db6d..46f144c46827 100644 --- a/tools/perf/util/config.c +++ b/tools/perf/util/config.c @@ -19,6 +19,7 @@ #include "util/llvm-utils.h" /* perf_llvm_config */ #include "util/stat.h" /* perf_stat__set_big_num */ #include "util/evsel.h" /* evsel__hw_names, evsel__use_bpf_counters */ +#include "util/srcline.h" /* addr2line_timeout_ms */ #include "build-id.h" #include "debug.h" #include "config.h" @@ -434,12 +435,14 @@ static int perf_buildid_config(const char *var, const char *value) return 0; } -static int perf_default_core_config(const char *var __maybe_unused, - const char *value __maybe_unused) +static int perf_default_core_config(const char *var, const char *value) { if (!strcmp(var, "core.proc-map-timeout")) 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. */ return 0; } diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index b27b4b3c391b..c013bcbdfd42 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -21,6 +21,8 @@ #include "symbol.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; char *srcline__unknown = (char *)"??:0"; @@ -631,7 +633,7 @@ static int addr2line(const char *dso_name, u64 addr, int len; char buf[128]; ssize_t written; - struct io io; + struct io io = { .eof = false }; enum a2l_style a2l_style; if (!a2l) { @@ -670,7 +672,7 @@ static int addr2line(const char *dso_name, u64 addr, goto out; } io__init(&io, a2l->out, buf, sizeof(buf)); - + io.timeout_ms = addr2line_timeout_ms; switch (read_addr2line_record(&io, a2l_style, &record_function, &record_filename, &record_line_nr)) { case -1: @@ -741,6 +743,10 @@ static int addr2line(const char *dso_name, u64 addr, out: free(record_function); free(record_filename); + if (io.eof) { + dso->a2l = NULL; + addr2line_subprocess_cleanup(a2l); + } return ret; } diff --git a/tools/perf/util/srcline.h b/tools/perf/util/srcline.h index 167645bcff07..75010d39ea28 100644 --- a/tools/perf/util/srcline.h +++ b/tools/perf/util/srcline.h @@ -9,6 +9,7 @@ struct dso; struct symbol; +extern int addr2line_timeout_ms; extern bool srcline_full_filename; char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, bool show_sym, bool show_addr, u64 ip); |