Skip to content

Commit

Permalink
perf tools: Make fork event processing more resilient
Browse files Browse the repository at this point in the history
When processing a fork event, the tools lookup the parent thread by its
tid.  In a couple of cases, it is possible for that thread to have the
wrong pid.

That can happen if the data is being processed out of order, or if the
(fork) event that would have removed the erroneous thread was lost.

Assume the latter case, print a dump message, remove the erroneous
thread, create a new one with the correct pid, and keep going.

Reported-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Jiri Olsa <jolsa@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/1439994561-27436-3-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Adrian Hunter authored and Arnaldo Carvalho de Melo committed Aug 19, 2015
1 parent 0d7e7ac commit 5cb7334
Showing 1 changed file with 18 additions and 2 deletions.
20 changes: 18 additions & 2 deletions tools/perf/util/machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,24 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event
event->fork.ptid);
int err = 0;

if (dump_trace)
perf_event__fprintf_task(event, stdout);

/*
* There may be an existing thread that is not actually the parent,
* either because we are processing events out of order, or because the
* (fork) event that would have removed the thread was lost. Assume the
* latter case and continue on as best we can.
*/
if (parent->pid_ != (pid_t)event->fork.ppid) {
dump_printf("removing erroneous parent thread %d/%d\n",
parent->pid_, parent->tid);
machine__remove_thread(machine, parent);
thread__put(parent);
parent = machine__findnew_thread(machine, event->fork.ppid,
event->fork.ptid);
}

/* if a thread currently exists for the thread id remove it */
if (thread != NULL) {
machine__remove_thread(machine, thread);
Expand All @@ -1395,8 +1413,6 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event

thread = machine__findnew_thread(machine, event->fork.pid,
event->fork.tid);
if (dump_trace)
perf_event__fprintf_task(event, stdout);

if (thread == NULL || parent == NULL ||
thread__fork(thread, parent, sample->time) < 0) {
Expand Down

0 comments on commit 5cb7334

Please sign in to comment.