|
@@ -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;
|