free_dup_event is called in two places 1) ordered_events__free 2) ordered_events__delete
without this patch, calling 1) after 2) would cause a double de-allocation, but that's exactly what happens in __perf_session__process_pipe_events. It wasn't triggered before because events where not copied when queued. With this patch, the event->event = NULL in ordered_events__delete will clear event pointer that is checked in free_dup_event, avoiding de-allocating the event a second time. Thanks, David On Tue, Apr 11, 2017 at 2:40 AM, Jiri Olsa <jo...@redhat.com> wrote: > On Mon, Apr 10, 2017 at 01:14:27PM -0700, David Carrillo-Cisneros wrote: >> __perf_session__process_pipe_events reuses the same memory buffer to >> process all events in the pipe. >> >> When reordering is needed (e.g. -b option), events are not immediately >> flushed, but kept around until reordering is possible, causing >> memory corruption. >> >> The problem is usually observed by a "Unknown sample error" output. It >> can easily be reproduced by: >> >> perf record -o - noploop | perf inject -b > output >> >> Signed-off-by: David Carrillo-Cisneros <davi...@google.com> >> --- >> tools/perf/util/ordered-events.c | 3 ++- >> tools/perf/util/session.c | 1 + >> 2 files changed, 3 insertions(+), 1 deletion(-) >> >> diff --git a/tools/perf/util/ordered-events.c >> b/tools/perf/util/ordered-events.c >> index fe84df1875aa..e70e935b1841 100644 >> --- a/tools/perf/util/ordered-events.c >> +++ b/tools/perf/util/ordered-events.c >> @@ -79,7 +79,7 @@ static union perf_event *dup_event(struct ordered_events >> *oe, >> >> static void free_dup_event(struct ordered_events *oe, union perf_event >> *event) >> { >> - if (oe->copy_on_queue) { >> + if (event && oe->copy_on_queue) { >> oe->cur_alloc_size -= event->header.size; >> free(event); >> } >> @@ -150,6 +150,7 @@ void ordered_events__delete(struct ordered_events *oe, >> struct ordered_event *eve >> list_move(&event->list, &oe->cache); >> oe->nr_events--; >> free_dup_event(oe, event->event); >> + event->event = NULL; > > based on the changelog I understand the need for the change below, > but I dont get why do we need this cleanu and check above > > thanks, > jirka > >> } >> >> int ordered_events__queue(struct ordered_events *oe, union perf_event >> *event, >> diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c >> index 24259bc2c598..a25302bc55a8 100644 >> --- a/tools/perf/util/session.c >> +++ b/tools/perf/util/session.c >> @@ -1656,6 +1656,7 @@ static int __perf_session__process_pipe_events(struct >> perf_session *session) >> buf = malloc(cur_size); >> if (!buf) >> return -errno; >> + ordered_events__set_copy_on_queue(oe, true); >> more: >> event = buf; >> err = readn(fd, event, sizeof(struct perf_event_header)); >> -- >> 2.12.2.715.g7642488e1d-goog >>