perf evsel: Allow to ignore missing pid
authorJiri Olsa <jolsa@redhat.com>
Tue, 13 Dec 2016 07:46:22 +0000 (08:46 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 15 Dec 2016 19:25:46 +0000 (16:25 -0300)
Adding perf_evsel::ignore_missing_cpu_thread bool.

When set true, it allows perf to ignore error of missing pid of perf
event syscall.

We remove missing thread id from the thread_map, so the rest of the
processing like ioctl and mmap won't get disturbed with -1 fd.

The reason for supporting this is to ease up monitoring group of pids,
that 'disappear' before perf opens their event. This currently leads
perf to report error and exit and makes perf record's -u option unusable
under certain setup.

With this change we will allow this race and ignore such failure with
following warning:

  WARNING: Ignored open failure for pid 8605

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/20161213074622.GA3084@krava
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/perf.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h

index 9a0236a4cf95fb7226af43e33b88e351359b8a2b..1c27d947c2fe55c9f0d0390695e6b586d839ec0b 100644 (file)
@@ -55,6 +55,7 @@ struct record_opts {
        bool         all_user;
        bool         tail_synthesize;
        bool         overwrite;
+       bool         ignore_missing_thread;
        unsigned int freq;
        unsigned int mmap_pages;
        unsigned int auxtrace_mmap_pages;
index fd61ebd77c262ba099986f1738cbb5c22cdecb1b..04e536ae4d88423e3c05a98fd1bd97ff64379b14 100644 (file)
@@ -990,6 +990,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
         * it overloads any global configuration.
         */
        apply_config_terms(evsel, opts);
+
+       evsel->ignore_missing_thread = opts->ignore_missing_thread;
 }
 
 static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
@@ -1419,6 +1421,33 @@ static int __open_attr__fprintf(FILE *fp, const char *name, const char *val,
        return fprintf(fp, "  %-32s %s\n", name, val);
 }
 
+static bool ignore_missing_thread(struct perf_evsel *evsel,
+                                 struct thread_map *threads,
+                                 int thread, int err)
+{
+       if (!evsel->ignore_missing_thread)
+               return false;
+
+       /* The system wide setup does not work with threads. */
+       if (evsel->system_wide)
+               return false;
+
+       /* The -ESRCH is perf event syscall errno for pid's not found. */
+       if (err != -ESRCH)
+               return false;
+
+       /* If there's only one thread, let it fail. */
+       if (threads->nr == 1)
+               return false;
+
+       if (thread_map__remove(threads, thread))
+               return false;
+
+       pr_warning("WARNING: Ignored open failure for pid %d\n",
+                  thread_map__pid(threads, thread));
+       return true;
+}
+
 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
                              struct thread_map *threads)
 {
@@ -1491,6 +1520,21 @@ retry_open:
 
                        if (fd < 0) {
                                err = -errno;
+
+                               if (ignore_missing_thread(evsel, threads, thread, err)) {
+                                       /*
+                                        * We just removed 1 thread, so take a step
+                                        * back on thread index and lower the upper
+                                        * nthreads limit.
+                                        */
+                                       nthreads--;
+                                       thread--;
+
+                                       /* ... and pretend like nothing have happened. */
+                                       err = 0;
+                                       continue;
+                               }
+
                                pr_debug2("\nsys_perf_event_open failed, error %d\n",
                                          err);
                                goto try_fallback;
index 6abb89cd27f95e1c11cdd25786b0cade3a804fe6..06ef6f29efa12a6c1300eca641e9446a0a4d17f8 100644 (file)
@@ -120,6 +120,7 @@ struct perf_evsel {
        bool                    tracking;
        bool                    per_pkg;
        bool                    precise_max;
+       bool                    ignore_missing_thread;
        /* parse modifier helper */
        int                     exclude_GH;
        int                     nr_members;