Commit 5e78c69b authored by He Kuang's avatar He Kuang Committed by Arnaldo Carvalho de Melo

perf buildid-list: Fix segfault when show DSOs with hits

commit: f3b623b8 ("perf tools: Reference count struct thread")
appends every thread->node to dead_threads in machine__remove_thread()
and list_del_init() this node in thread__put().

perf_event__exit_del_thread() releases thread wihout using
machine__remove_thread(), and causes a NULL pointer crash when
list_del_init(&thread->node) is called. Fix this by using
machine_remove_thread() instead of using thread__put() directly.

This problem can be reproduced as following:

  $ perf record ls
  $ perf buildid-list --with-hits
  [ 3874.195070] perf[1018]: segfault at 0 ip 00000000004b0b15 sp
  00007ffc35b44780 error 6 in perf[400000+166000]
  Segmentation fault

After this patch:
  $ perf record ls
  $ perf buildid-list --with-hits
  bc23e7c3281e542650ba4324421d6acf78f4c23e /proc/kcore
  643324cb0e969f30c56d660f167f84a150845511 [vdso]
  0000000000000000000000000000000000000000 /bin/busybox
  ...
Signed-off-by: default avatarHe Kuang <hekuang@huawei.com>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1428658500-6483-1-git-send-email-hekuang@huawei.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 1060ab85
...@@ -59,12 +59,8 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused, ...@@ -59,12 +59,8 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
event->fork.ppid, event->fork.ptid); event->fork.ppid, event->fork.ptid);
if (thread) { if (thread)
rb_erase(&thread->rb_node, &machine->threads); machine__remove_thread(machine, thread);
if (machine->last_match == thread)
thread__zput(machine->last_match);
thread__put(thread);
}
return 0; return 0;
} }
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
#include "unwind.h" #include "unwind.h"
#include "linux/hash.h" #include "linux/hash.h"
static void machine__remove_thread(struct machine *machine, struct thread *th);
static void dsos__init(struct dsos *dsos) static void dsos__init(struct dsos *dsos)
{ {
INIT_LIST_HEAD(&dsos->head); INIT_LIST_HEAD(&dsos->head);
...@@ -1256,7 +1254,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event ...@@ -1256,7 +1254,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
return 0; return 0;
} }
static void machine__remove_thread(struct machine *machine, struct thread *th) void machine__remove_thread(struct machine *machine, struct thread *th)
{ {
if (machine->last_match == th) if (machine->last_match == th)
thread__zput(machine->last_match); thread__zput(machine->last_match);
......
...@@ -120,6 +120,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid); ...@@ -120,6 +120,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
void machine__exit(struct machine *machine); void machine__exit(struct machine *machine);
void machine__delete_threads(struct machine *machine); void machine__delete_threads(struct machine *machine);
void machine__delete(struct machine *machine); void machine__delete(struct machine *machine);
void machine__remove_thread(struct machine *machine, struct thread *th);
struct branch_info *sample__resolve_bstack(struct perf_sample *sample, struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
struct addr_location *al); struct addr_location *al);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment