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
This commit is contained in:
commit
c3a0651422
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user