From 0d7e7acc47133e82911e24758178815cfee309e9 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 19 Aug 2015 17:29:19 +0300 Subject: perf tools: Avoid deadlock when map_groups are broken Attempting to clone map groups onto themselves will deadlock. It only happens because of other bugs, but the code should protect itself anyway. Reported-by: Linus Torvalds Signed-off-by: Adrian Hunter Tested-by: Jiri Olsa Link: http://lkml.kernel.org/r/1439994561-27436-2-git-send-email-adrian.hunter@intel.com [ Use pr_debug() instead of dump_fprintf() ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/thread.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tools') diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 28c4b74..0a9ae80 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -191,6 +191,12 @@ static int thread__clone_map_groups(struct thread *thread, if (thread->pid_ == parent->pid_) return 0; + if (thread->mg == parent->mg) { + pr_debug("broken map groups on thread %d/%d parent %d/%d\n", + thread->pid_, thread->tid, parent->pid_, parent->tid); + return 0; + } + /* But this one is new process, copy maps. */ for (i = 0; i < MAP__NR_TYPES; ++i) if (map_groups__clone(thread->mg, parent->mg, i) < 0) -- cgit v1.1 From 5cb73340d92a716fd2776700742c3558206ae298 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 19 Aug 2015 17:29:20 +0300 Subject: perf tools: Make fork event processing more resilient 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 Signed-off-by: Adrian Hunter Tested-by: Jiri Olsa Cc: Linus Torvalds Link: http://lkml.kernel.org/r/1439994561-27436-3-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/machine.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 7ff6827..f1a4c83 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -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); @@ -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) { -- cgit v1.1 From cca8482c0651cea97aade58cc22109ce9fffbfa2 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 19 Aug 2015 17:29:21 +0300 Subject: perf tools: Fix buildid processing After recording, 'perf record' post-processes the data to determine which buildids are needed. That processing must process the data in time order, if possible, because otherwise dependent events, like forks and mmaps, will not make sense. Signed-off-by: Adrian Hunter Tested-by: Jiri Olsa Cc: Linus Torvalds Link: http://lkml.kernel.org/r/1439994561-27436-4-git-send-email-adrian.hunter@intel.com [ Moved the sample_id_add to after trying to open the events, use pr_warning ] Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-record.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'tools') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index de165a1..20b56eb 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -521,6 +521,15 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) goto out_child; } + /* + * Normally perf_session__new would do this, but it doesn't have the + * evlist. + */ + if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { + pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); + rec->tool.ordered_events = false; + } + if (!rec->evlist->nr_groups) perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); @@ -965,9 +974,11 @@ static struct record record = { .tool = { .sample = process_sample_event, .fork = perf_event__process_fork, + .exit = perf_event__process_exit, .comm = perf_event__process_comm, .mmap = perf_event__process_mmap, .mmap2 = perf_event__process_mmap2, + .ordered_events = true, }, }; -- cgit v1.1 From 09f4d78ab0af0973e1a49c10eb7bf977c68cc3aa Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Wed, 19 Aug 2015 15:16:08 -0300 Subject: perf top: Show backtrace when handling a SIGSEGV on --stdio mode It was just freezing instead of informing about the SEGV, fix it and also print a backtrace, just like in the TUI mode and in 'perf trace'. Tested by provoking a NULL deref when pressing 'z': 0.31% libc-2.20.so [.] malloc_consolidate 0.31% ld-2.20.so [.] _dl_relocate_object 0.28% cc1 [.] ht_lookup 0.28% cc1 [.] ira_init_register_move_cost perf: Segmentation fault Obtained 7 stack frames. perf(dump_stack+0x32) [0x4d69f2] perf(sighandler_dump_stack+0x29) [0x4d6a89] /lib64/libc.so.6(+0x34960) [0x7f5064333960] perf() [0x438790] /lib64/libpthread.so.0(+0x752a) [0x7f50663dd52a] /lib64/libc.so.6(clone+0x6d) [0x7f50643ff22d] # Reported-by: Linus Torvalds Cc: Adrian Hunter Cc: Borislav Petkov Cc: David Ahern Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Namhyung Kim Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-pewrpzqd29rgmhu2wkk7fhww@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-top.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools') diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index ecf3197..6135cc0 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -601,8 +601,8 @@ static void display_sig(int sig __maybe_unused) static void display_setup_sig(void) { - signal(SIGSEGV, display_sig); - signal(SIGFPE, display_sig); + signal(SIGSEGV, sighandler_dump_stack); + signal(SIGFPE, sighandler_dump_stack); signal(SIGINT, display_sig); signal(SIGQUIT, display_sig); signal(SIGTERM, display_sig); -- cgit v1.1