Messages in this thread | | | Date | Mon, 20 Apr 2020 11:05:00 +0200 | From | Jiri Olsa <> | Subject | Re: [PATCH 3/4] perf tools: Fix segfaults due to missing zstd decompressor initialization |
| |
On Fri, Apr 17, 2020 at 04:23:28PM +0300, Tommi Rantala wrote: > Initialization of zstd decompressor state is done for "perf report" and > "perf inject", but missing for other tools, causing segfaults e.g. with > "perf script" and "perf annotate" when zstd compressed data is used: > > # ./perf record -z -a -- sleep 1 > # gdb -q --args ./perf script > (gdb) run > Program received signal SIGSEGV, Segmentation fault. > 0x00007ffff771d4cb in ZSTD_decompressStream () from /lib64/libzstd.so.1 > (gdb) bt > #0 0x00007ffff771d4cb in ZSTD_decompressStream () from /lib64/libzstd.so.1 > #1 0x00000000005c92a8 in zstd_decompress_stream (data=0xc3f8e0, src=0x7ffff6dd3038, src_size=255, dst=0x7ffff61ec028, dst_size=528384) at util/zstd.c:100 > #2 0x00000000005262ba in perf_session__process_compressed_event (session=0xc38cc0, event=0x7ffff6dd3030, file_offset=11948080) at util/session.c:73 > #3 0x000000000052a596 in perf_session__process_user_event (session=0xc38cc0, event=0x7ffff6dd3030, file_offset=11948080) at util/session.c:1581 > #4 0x000000000052ab4b in perf_session__process_event (session=0xc38cc0, event=0x7ffff6dd3030, file_offset=11948080) at util/session.c:1713 > #5 0x000000000052bed6 in process_simple (session=0xc38cc0, event=0x7ffff6dd3030, file_offset=11948080) at util/session.c:2209 > #6 0x000000000052bcfe in reader__process_events (rd=0x7fffffffb400, session=0xc38cc0, prog=0x7fffffffb420) at util/session.c:2175 > #7 0x000000000052bfc2 in __perf_session__process_events (session=0xc38cc0) at util/session.c:2232 > #8 0x000000000052c0f3 in perf_session__process_events (session=0xc38cc0) at util/session.c:2265 > #9 0x0000000000447266 in __cmd_script (script=0x7fffffffb5c0) at builtin-script.c:2608 > #10 0x000000000044ba79 in cmd_script (argc=0, argv=0x7fffffffd330) at builtin-script.c:3988 > #11 0x00000000004bf2b8 in run_builtin (p=0xa398f8 <commands+408>, argc=1, argv=0x7fffffffd330) at perf.c:312 > #12 0x00000000004bf525 in handle_internal_command (argc=1, argv=0x7fffffffd330) at perf.c:364 > #13 0x00000000004bf66c in run_argv (argcp=0x7fffffffd18c, argv=0x7fffffffd180) at perf.c:408 > #14 0x00000000004bfa38 in main (argc=1, argv=0x7fffffffd330) at perf.c:538 > > Split zstd_init() into zstd_decomp_init() and zstd_comp_init(), so that > we can do lazy initialization for the decompressor, and handle it all in > perf_session to make it easily available to all the tools.
Alexey, could you please check on this one?
thanks, jirka
> > Signed-off-by: Tommi Rantala <tommi.t.rantala@nokia.com> > --- > tools/perf/builtin-inject.c | 3 --- > tools/perf/builtin-record.c | 2 +- > tools/perf/builtin-report.c | 3 --- > tools/perf/util/compress.h | 10 ++++++++-- > tools/perf/util/session.c | 3 +++ > tools/perf/util/zstd.c | 14 +++++++++++++- > 6 files changed, 25 insertions(+), 10 deletions(-) > > diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c > index 1ffb8393357a..8cc9dff9e66b 100644 > --- a/tools/perf/builtin-inject.c > +++ b/tools/perf/builtin-inject.c > @@ -803,9 +803,6 @@ int cmd_inject(int argc, const char **argv) > if (IS_ERR(inject.session)) > return PTR_ERR(inject.session); > > - if (zstd_init(&(inject.session->zstd_data), 0) < 0) > - pr_warning("Decompression initialization failed.\n"); > - > if (inject.build_ids) { > /* > * to make sure the mmap records are ordered correctly > diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c > index 8ed00de1ca29..fa9c59fc4fe0 100644 > --- a/tools/perf/builtin-record.c > +++ b/tools/perf/builtin-record.c > @@ -1461,7 +1461,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) > fd = perf_data__fd(data); > rec->session = session; > > - if (zstd_init(&session->zstd_data, rec->opts.comp_level) < 0) { > + if (zstd_comp_init(&session->zstd_data, rec->opts.comp_level) < 0) { > pr_err("Compression initialization failed.\n"); > return -1; > } > diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c > index e06e14980264..b85fcdebdb5a 100644 > --- a/tools/perf/builtin-report.c > +++ b/tools/perf/builtin-report.c > @@ -1355,9 +1355,6 @@ int cmd_report(int argc, const char **argv) > if (ret) > return ret; > > - if (zstd_init(&(session->zstd_data), 0) < 0) > - pr_warning("Decompression initialization failed. Reported data may be incomplete.\n"); > - > if (report.queue_size) { > ordered_events__set_alloc_size(&session->ordered_events, > report.queue_size); > diff --git a/tools/perf/util/compress.h b/tools/perf/util/compress.h > index 0cd3369af2a4..aff9ce60dfb8 100644 > --- a/tools/perf/util/compress.h > +++ b/tools/perf/util/compress.h > @@ -26,7 +26,8 @@ struct zstd_data { > > #ifdef HAVE_ZSTD_SUPPORT > > -int zstd_init(struct zstd_data *data, int level); > +int zstd_comp_init(struct zstd_data *data, int level); > +int zstd_decomp_init(struct zstd_data *data); > int zstd_fini(struct zstd_data *data); > > size_t zstd_compress_stream_to_records(struct zstd_data *data, void *dst, size_t dst_size, > @@ -37,7 +38,12 @@ size_t zstd_decompress_stream(struct zstd_data *data, void *src, size_t src_size > void *dst, size_t dst_size); > #else /* !HAVE_ZSTD_SUPPORT */ > > -static inline int zstd_init(struct zstd_data *data __maybe_unused, int level __maybe_unused) > +static inline int zstd_comp_init(struct zstd_data *data __maybe_unused, int level __maybe_unused) > +{ > + return 0; > +} > + > +static inline int zstd_decomp_init(struct zstd_data *data __maybe_unused) > { > return 0; > } > diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c > index 64e8b794b0bc..2bba731e7cbf 100644 > --- a/tools/perf/util/session.c > +++ b/tools/perf/util/session.c > @@ -45,6 +45,9 @@ static int perf_session__process_compressed_event(struct perf_session *session, > size_t mmap_len, decomp_len = session->header.env.comp_mmap_len; > struct decomp *decomp, *decomp_last = session->decomp_last; > > + if (zstd_decomp_init(&session->zstd_data) < 0) > + return -1; > + > if (decomp_last) { > decomp_last_rem = decomp_last->size - decomp_last->head; > decomp_len += decomp_last_rem; > diff --git a/tools/perf/util/zstd.c b/tools/perf/util/zstd.c > index d2202392ffdb..d789665e8c0c 100644 > --- a/tools/perf/util/zstd.c > +++ b/tools/perf/util/zstd.c > @@ -5,10 +5,13 @@ > #include "util/compress.h" > #include "util/debug.h" > > -int zstd_init(struct zstd_data *data, int level) > +int zstd_decomp_init(struct zstd_data *data) > { > size_t ret; > > + if (data->dstream) > + return 0; > + > data->dstream = ZSTD_createDStream(); > if (data->dstream == NULL) { > pr_err("Couldn't create decompression stream.\n"); > @@ -18,9 +21,18 @@ int zstd_init(struct zstd_data *data, int level) > ret = ZSTD_initDStream(data->dstream); > if (ZSTD_isError(ret)) { > pr_err("Failed to initialize decompression stream: %s\n", ZSTD_getErrorName(ret)); > + ZSTD_freeDStream(data->dstream); > + data->dstream = NULL; > return -1; > } > > + return 0; > +} > + > +int zstd_comp_init(struct zstd_data *data, int level) > +{ > + size_t ret; > + > if (!level) > return 0; > > -- > 2.25.2 >
| |