History

perf tools: Add time out to force stop proc map processing

System wide sampling like 'perf top' or 'perf record -a' read all threads /proc/xxx/maps before sampling. If there are any threads which generating a keeping growing huge maps, perf will do infinite loop during synthesizing. Nothing will be sampled. This patch fixes this issue by adding per-thread timeout to force stop this kind of endless proc map processing. PERF_RECORD_MISC_PROC_MAP_PARSE_TIME_OUT is introduced to indicate that the mmap record are truncated by time out. User will get warning notification when truncated mmap records are detected.

Kan Liang committed 11 years ago

Commit 930e6fc1 parent c05676c4 files · +34 −0Browse files

Unified · Split

4 files
  1. include/uapi/linux/perf_event.h +4 −0
  2. tools/perf/util/event.c +18 −0
  3. tools/perf/util/event.h +1 −0
  4. tools/perf/util/session.c +11 −0
include/uapi/linux/perf_event.h+4−0
@@ -565,6 +565,10 @@ struct perf_event_mmap_page { · 564 unmodified lines
565565 #define PERF_RECORD_MISC_GUEST_KERNEL (4 << 0)
566566 #define PERF_RECORD_MISC_GUEST_USER (5 << 0)
567567
568+/*
569+ * Indicates that /proc/PID/maps parsing are truncated by time out.
570+ */
571+#define PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT (1 << 12)
568572 /*
569573 * PERF_RECORD_MISC_MMAP_DATA and PERF_RECORD_MISC_COMM_EXEC are used on
570574 * different events so can reuse the same bit position.
tools/perf/util/event.c+18−0
@@ -213,6 +213,8 @@ static int perf_event__synthesize_fork(struct perf_tool *tool, · 212 unmodified lines
213213 return 0;
214214 }
215215
216+#define PROC_MAP_PARSE_TIMEOUT (500 * 1000000ULL)
217+
216218 int perf_event__synthesize_mmap_events(struct perf_tool *tool,
217219 union perf_event *event,
218220 pid_t pid, pid_t tgid,
@@ -222,6 +224,8 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool, · 3 unmodified lines
222224 {
223225 char filename[PATH_MAX];
224226 FILE *fp;
227+ unsigned long long t;
228+ bool truncation = false;
225229 int rc = 0;
226230
227231 if (machine__is_default_guest(machine))
@@ -240,6 +244,7 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool, · 12 unmodified lines
240244 }
241245
242246 event->header.type = PERF_RECORD_MMAP2;
247+ t = rdclock();
243248
244249 while (1) {
245250 char bf[BUFSIZ];
@@ -253,6 +258,12 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool, · 7 unmodified lines
253258 if (fgets(bf, sizeof(bf), fp) == NULL)
254259 break;
255260
261+ if ((rdclock() - t) > PROC_MAP_PARSE_TIMEOUT) {
262+ pr_warning("Reading %s time out.\n", filename);
263+ truncation = true;
264+ goto out;
265+ }
266+
256267 /* ensure null termination since stack will be reused. */
257268 strcpy(execname, "");
258269
@@ -301,6 +312,10 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool, · 42 unmodified lines
301312 event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
302313 }
303314
315+out:
316+ if (truncation)
317+ event->header.misc |= PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT;
318+
304319 if (!strcmp(execname, ""))
305320 strcpy(execname, anonstr);
306321
@@ -319,6 +334,9 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool, · 12 unmodified lines
319334 rc = -1;
320335 break;
321336 }
337+
338+ if (truncation)
339+ break;
322340 }
323341
324342 fclose(fp);
tools/perf/util/event.h+1−0
@@ -265,6 +265,7 @@ struct events_stats { · 264 unmodified lines
265265 u32 nr_unknown_id;
266266 u32 nr_unprocessable_samples;
267267 u32 nr_auxtrace_errors[PERF_AUXTRACE_ERROR_MAX];
268+ u32 nr_proc_map_timeout;
268269 };
269270
270271 struct attr_event {
tools/perf/util/session.c+11−0
@@ -1064,6 +1064,8 @@ static int machines__deliver_event(struct machines *machines, · 1063 unmodified lines
10641064 case PERF_RECORD_MMAP:
10651065 return tool->mmap(tool, event, sample, machine);
10661066 case PERF_RECORD_MMAP2:
1067+ if (event->header.misc & PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT)
1068+ ++evlist->stats.nr_proc_map_timeout;
10671069 return tool->mmap2(tool, event, sample, machine);
10681070 case PERF_RECORD_COMM:
10691071 return tool->comm(tool, event, sample, machine);
@@ -1360,6 +1362,15 @@ static void perf_session__warn_about_errors(const struct perf_session *session) · 290 unmodified lines
13601362 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
13611363
13621364 events_stats__auxtrace_error_warn(stats);
1365+
1366+ if (stats->nr_proc_map_timeout != 0) {
1367+ ui__warning("%d map information files for pre-existing threads were\n"
1368+ "not processed, if there are samples for addresses they\n"
1369+ "will not be resolved, you may find out which are these\n"
1370+ "threads by running with -v and redirecting the output\n"
1371+ "to a file.\n",
1372+ stats->nr_proc_map_timeout);
1373+ }
13631374 }
13641375
13651376 static int perf_session__flush_thread_stack(struct thread *thread,