aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKan Liang <kan.liang@intel.com>2015-06-17 09:51:10 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-06-19 17:20:15 -0400
commit930e6fcd2bcce9bcd9d4aa7e755678d33f3fe6f4 (patch)
tree5f85d268437a01f2a2982be31c82cb00a81efd85
parentc05676c06232e6459a6106ddf0d4e154ce6cd859 (diff)
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. Reported-by: Ying Huang <ying.huang@intel.com> Signed-off-by: Kan Liang <kan.liang@intel.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: David Ahern <dsahern@gmail.com> Cc: Ying Huang <ying.huang@intel.com> Link: http://lkml.kernel.org/r/1434549071-25611-1-git-send-email-kan.liang@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--include/uapi/linux/perf_event.h4
-rw-r--r--tools/perf/util/event.c18
-rw-r--r--tools/perf/util/event.h1
-rw-r--r--tools/perf/util/session.c11
4 files changed, 34 insertions, 0 deletions
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 613ed9ad588f..d97f84c080da 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -566,6 +566,10 @@ struct perf_event_mmap_page {
566#define PERF_RECORD_MISC_GUEST_USER (5 << 0) 566#define PERF_RECORD_MISC_GUEST_USER (5 << 0)
567 567
568/* 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)
572/*
569 * PERF_RECORD_MISC_MMAP_DATA and PERF_RECORD_MISC_COMM_EXEC are used on 573 * 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.
571 */ 575 */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 793b1503d437..416ba80c628f 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -213,6 +213,8 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
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,
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,
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,
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,
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,
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);
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 5dc51ada05df..39868f529cab 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -265,6 +265,7 @@ struct events_stats {
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 {
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index c371336d1eb2..2d882fd1f1b9 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1064,6 +1064,8 @@ static int machines__deliver_event(struct machines *machines,
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)
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,