summaryrefslogtreecommitdiff
path: root/tools/perf/util
diff options
context:
space:
mode:
authorLevi Yun <yeoreum.yun@arm.com>2024-09-25 14:20:21 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-12-09 10:32:24 +0100
commit035c6b7a13aca5b8c6ed604f40e8101a498ab8d2 (patch)
tree5fc68982ffd81cb8eb3aac41da2e442006cc0cb3 /tools/perf/util
parent8e098baf6bc3f3a6aefc383509aba07e202f7ee0 (diff)
perf stat: Close cork_fd when create_perf_stat_counter() failed
[ Upstream commit e880a70f8046df0dd9089fa60dcb866a2cc69194 ] When create_perf_stat_counter() failed, it doesn't close workload.cork_fd open in evlist__prepare_workload(). This could make too many open file error while __run_perf_stat() repeats. Introduce evlist__cancel_workload to close workload.cork_fd and wait workload.child_pid until exit to clear child process when create_perf_stat_counter() is failed. Signed-off-by: Levi Yun <yeoreum.yun@arm.com> Reviewed-by: James Clark <james.clark@linaro.org> Reviewed-by: Andi Kleen <ak@linux.intel.com> Cc: nd@arm.com Cc: howardchu95@gmail.com Link: https://lore.kernel.org/r/20240925132022.2650180-2-yeoreum.yun@arm.com Signed-off-by: Namhyung Kim <namhyung@kernel.org> Stable-dep-of: 7f6ccb70e465 ("perf stat: Fix affinity memory leaks on error path") Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/evlist.c19
-rw-r--r--tools/perf/util/evlist.h1
2 files changed, 18 insertions, 2 deletions
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index eb1dd29c538d..1eadb4f7c1b9 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -46,6 +46,7 @@
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/timerfd.h>
+#include <sys/wait.h>
#include <linux/bitops.h>
#include <linux/hash.h>
@@ -1412,6 +1413,8 @@ int evlist__prepare_workload(struct evlist *evlist, struct target *target, const
int child_ready_pipe[2], go_pipe[2];
char bf;
+ evlist->workload.cork_fd = -1;
+
if (pipe(child_ready_pipe) < 0) {
perror("failed to create 'ready' pipe");
return -1;
@@ -1464,7 +1467,7 @@ int evlist__prepare_workload(struct evlist *evlist, struct target *target, const
* For cancelling the workload without actually running it,
* the parent will just close workload.cork_fd, without writing
* anything, i.e. read will return zero and we just exit()
- * here.
+ * here (See evlist__cancel_workload()).
*/
if (ret != 1) {
if (ret == -1)
@@ -1528,7 +1531,7 @@ out_close_ready_pipe:
int evlist__start_workload(struct evlist *evlist)
{
- if (evlist->workload.cork_fd > 0) {
+ if (evlist->workload.cork_fd >= 0) {
char bf = 0;
int ret;
/*
@@ -1539,12 +1542,24 @@ int evlist__start_workload(struct evlist *evlist)
perror("unable to write to pipe");
close(evlist->workload.cork_fd);
+ evlist->workload.cork_fd = -1;
return ret;
}
return 0;
}
+void evlist__cancel_workload(struct evlist *evlist)
+{
+ int status;
+
+ if (evlist->workload.cork_fd >= 0) {
+ close(evlist->workload.cork_fd);
+ evlist->workload.cork_fd = -1;
+ waitpid(evlist->workload.pid, &status, WNOHANG);
+ }
+}
+
int evlist__parse_sample(struct evlist *evlist, union perf_event *event, struct perf_sample *sample)
{
struct evsel *evsel = evlist__event2evsel(evlist, event);
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index cb91dc9117a2..12f929ffdf92 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -184,6 +184,7 @@ int evlist__prepare_workload(struct evlist *evlist, struct target *target,
const char *argv[], bool pipe_output,
void (*exec_error)(int signo, siginfo_t *info, void *ucontext));
int evlist__start_workload(struct evlist *evlist);
+void evlist__cancel_workload(struct evlist *evlist);
struct option;