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
565#define PERF_RECORD_MISC_GUEST_KERNEL (4 << 0)565#define PERF_RECORD_MISC_GUEST_KERNEL (4 << 0)
566#define PERF_RECORD_MISC_GUEST_USER (5 << 0)566#define PERF_RECORD_MISC_GUEST_USER (5 << 0)
567 567
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)
568/*572/*
569 * PERF_RECORD_MISC_MMAP_DATA and PERF_RECORD_MISC_COMM_EXEC are used on573 * PERF_RECORD_MISC_MMAP_DATA and PERF_RECORD_MISC_COMM_EXEC are used on
570 * different events so can reuse the same bit position.574 * 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
213 return 0;213 return 0;
214}214}
215 215
216#define PROC_MAP_PARSE_TIMEOUT (500 * 1000000ULL)
217
216int perf_event__synthesize_mmap_events(struct perf_tool *tool,218int perf_event__synthesize_mmap_events(struct perf_tool *tool,
217 union perf_event *event,219 union perf_event *event,
218 pid_t pid, pid_t tgid,220 pid_t pid, pid_t tgid,
@@ -222,6 +224,8 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool, · 3 unmodified lines
222{224{
223 char filename[PATH_MAX];225 char filename[PATH_MAX];
224 FILE *fp;226 FILE *fp;
227 unsigned long long t;
228 bool truncation = false;
225 int rc = 0;229 int rc = 0;
226 230
227 if (machine__is_default_guest(machine))231 if (machine__is_default_guest(machine))
@@ -240,6 +244,7 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool, · 12 unmodified lines
240 }244 }
241 245
242 event->header.type = PERF_RECORD_MMAP2;246 event->header.type = PERF_RECORD_MMAP2;
247 t = rdclock();
243 248
244 while (1) {249 while (1) {
245 char bf[BUFSIZ];250 char bf[BUFSIZ];
@@ -253,6 +258,12 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool, · 7 unmodified lines
253 if (fgets(bf, sizeof(bf), fp) == NULL)258 if (fgets(bf, sizeof(bf), fp) == NULL)
254 break;259 break;
255 260
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
256 /* ensure null termination since stack will be reused. */267 /* ensure null termination since stack will be reused. */
257 strcpy(execname, "");268 strcpy(execname, "");
258 269
@@ -301,6 +312,10 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool, · 42 unmodified lines
301 event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;312 event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
302 }313 }
303 314
315out:
316 if (truncation)
317 event->header.misc |= PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT;
318
304 if (!strcmp(execname, ""))319 if (!strcmp(execname, ""))
305 strcpy(execname, anonstr);320 strcpy(execname, anonstr);
306 321
@@ -319,6 +334,9 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool, · 12 unmodified lines
319 rc = -1;334 rc = -1;
320 break;335 break;
321 }336 }
337
338 if (truncation)
339 break;
322 }340 }
323 341
324 fclose(fp);342 fclose(fp);
tools/perf/util/event.h+1−0
@@ -265,6 +265,7 @@ struct events_stats { · 264 unmodified lines
265 u32 nr_unknown_id;265 u32 nr_unknown_id;
266 u32 nr_unprocessable_samples;266 u32 nr_unprocessable_samples;
267 u32 nr_auxtrace_errors[PERF_AUXTRACE_ERROR_MAX];267 u32 nr_auxtrace_errors[PERF_AUXTRACE_ERROR_MAX];
268 u32 nr_proc_map_timeout;
268};269};
269 270
270struct attr_event {271struct attr_event {
tools/perf/util/session.c+11−0
@@ -1064,6 +1064,8 @@ static int machines__deliver_event(struct machines *machines, · 1063 unmodified lines
1064 case PERF_RECORD_MMAP:1064 case PERF_RECORD_MMAP:
1065 return tool->mmap(tool, event, sample, machine);1065 return tool->mmap(tool, event, sample, machine);
1066 case PERF_RECORD_MMAP2:1066 case PERF_RECORD_MMAP2:
1067 if (event->header.misc & PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT)
1068 ++evlist->stats.nr_proc_map_timeout;
1067 return tool->mmap2(tool, event, sample, machine);1069 return tool->mmap2(tool, event, sample, machine);
1068 case PERF_RECORD_COMM:1070 case PERF_RECORD_COMM:
1069 return tool->comm(tool, event, sample, machine);1071 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
1360 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);1362 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
1361 1363
1362 events_stats__auxtrace_error_warn(stats);1364 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 }
1363}1374}
1364 1375
1365static int perf_session__flush_thread_stack(struct thread *thread,1376static int perf_session__flush_thread_stack(struct thread *thread,