diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-22 11:06:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-08-22 11:06:28 -0400 |
commit | c3a0651422ec84ebd25647c7002664bf7248ccc6 (patch) | |
tree | 9cb852043465966305d87c9bb67f1997b932c892 | |
parent | 84f3fe460838df2ecd80bf9ed943a1b557e81354 (diff) | |
parent | 196676497f2507966f99abef63bede6a8550f8b3 (diff) |
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar:
"Tooling fixes: a 'perf record' deadlock fix plus debuggability fixes"
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
perf top: Show backtrace when handling a SIGSEGV on --stdio mode
perf tools: Fix buildid processing
perf tools: Make fork event processing more resilient
perf tools: Avoid deadlock when map_groups are broken
-rw-r--r-- | tools/perf/builtin-record.c | 11 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 4 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 20 | ||||
-rw-r--r-- | tools/perf/util/thread.c | 6 |
4 files changed, 37 insertions, 4 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index de165a1b9240..20b56eb987f8 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) | |||
521 | goto out_child; | 521 | goto out_child; |
522 | } | 522 | } |
523 | 523 | ||
524 | /* | ||
525 | * Normally perf_session__new would do this, but it doesn't have the | ||
526 | * evlist. | ||
527 | */ | ||
528 | if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) { | ||
529 | pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n"); | ||
530 | rec->tool.ordered_events = false; | ||
531 | } | ||
532 | |||
524 | if (!rec->evlist->nr_groups) | 533 | if (!rec->evlist->nr_groups) |
525 | perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); | 534 | perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); |
526 | 535 | ||
@@ -965,9 +974,11 @@ static struct record record = { | |||
965 | .tool = { | 974 | .tool = { |
966 | .sample = process_sample_event, | 975 | .sample = process_sample_event, |
967 | .fork = perf_event__process_fork, | 976 | .fork = perf_event__process_fork, |
977 | .exit = perf_event__process_exit, | ||
968 | .comm = perf_event__process_comm, | 978 | .comm = perf_event__process_comm, |
969 | .mmap = perf_event__process_mmap, | 979 | .mmap = perf_event__process_mmap, |
970 | .mmap2 = perf_event__process_mmap2, | 980 | .mmap2 = perf_event__process_mmap2, |
981 | .ordered_events = true, | ||
971 | }, | 982 | }, |
972 | }; | 983 | }; |
973 | 984 | ||
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index ecf319728f25..6135cc07213c 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) | |||
601 | 601 | ||
602 | static void display_setup_sig(void) | 602 | static void display_setup_sig(void) |
603 | { | 603 | { |
604 | signal(SIGSEGV, display_sig); | 604 | signal(SIGSEGV, sighandler_dump_stack); |
605 | signal(SIGFPE, display_sig); | 605 | signal(SIGFPE, sighandler_dump_stack); |
606 | signal(SIGINT, display_sig); | 606 | signal(SIGINT, display_sig); |
607 | signal(SIGQUIT, display_sig); | 607 | signal(SIGQUIT, display_sig); |
608 | signal(SIGTERM, display_sig); | 608 | signal(SIGTERM, display_sig); |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 7ff682770fdb..f1a4c833121e 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 | |||
1387 | event->fork.ptid); | 1387 | event->fork.ptid); |
1388 | int err = 0; | 1388 | int err = 0; |
1389 | 1389 | ||
1390 | if (dump_trace) | ||
1391 | perf_event__fprintf_task(event, stdout); | ||
1392 | |||
1393 | /* | ||
1394 | * There may be an existing thread that is not actually the parent, | ||
1395 | * either because we are processing events out of order, or because the | ||
1396 | * (fork) event that would have removed the thread was lost. Assume the | ||
1397 | * latter case and continue on as best we can. | ||
1398 | */ | ||
1399 | if (parent->pid_ != (pid_t)event->fork.ppid) { | ||
1400 | dump_printf("removing erroneous parent thread %d/%d\n", | ||
1401 | parent->pid_, parent->tid); | ||
1402 | machine__remove_thread(machine, parent); | ||
1403 | thread__put(parent); | ||
1404 | parent = machine__findnew_thread(machine, event->fork.ppid, | ||
1405 | event->fork.ptid); | ||
1406 | } | ||
1407 | |||
1390 | /* if a thread currently exists for the thread id remove it */ | 1408 | /* if a thread currently exists for the thread id remove it */ |
1391 | if (thread != NULL) { | 1409 | if (thread != NULL) { |
1392 | machine__remove_thread(machine, thread); | 1410 | machine__remove_thread(machine, thread); |
@@ -1395,8 +1413,6 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event | |||
1395 | 1413 | ||
1396 | thread = machine__findnew_thread(machine, event->fork.pid, | 1414 | thread = machine__findnew_thread(machine, event->fork.pid, |
1397 | event->fork.tid); | 1415 | event->fork.tid); |
1398 | if (dump_trace) | ||
1399 | perf_event__fprintf_task(event, stdout); | ||
1400 | 1416 | ||
1401 | if (thread == NULL || parent == NULL || | 1417 | if (thread == NULL || parent == NULL || |
1402 | thread__fork(thread, parent, sample->time) < 0) { | 1418 | thread__fork(thread, parent, sample->time) < 0) { |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 28c4b746baa1..0a9ae8014729 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, | |||
191 | if (thread->pid_ == parent->pid_) | 191 | if (thread->pid_ == parent->pid_) |
192 | return 0; | 192 | return 0; |
193 | 193 | ||
194 | if (thread->mg == parent->mg) { | ||
195 | pr_debug("broken map groups on thread %d/%d parent %d/%d\n", | ||
196 | thread->pid_, thread->tid, parent->pid_, parent->tid); | ||
197 | return 0; | ||
198 | } | ||
199 | |||
194 | /* But this one is new process, copy maps. */ | 200 | /* But this one is new process, copy maps. */ |
195 | for (i = 0; i < MAP__NR_TYPES; ++i) | 201 | for (i = 0; i < MAP__NR_TYPES; ++i) |
196 | if (map_groups__clone(thread->mg, parent->mg, i) < 0) | 202 | if (map_groups__clone(thread->mg, parent->mg, i) < 0) |