summaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-record.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r--tools/perf/builtin-record.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 6ec0cbc2a5d5..f987d385c6f0 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -341,6 +341,22 @@ static void record__init_features(struct record *rec)
perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
}
+static volatile int workload_exec_errno;
+
+/*
+ * perf_evlist__prepare_workload will send a SIGUSR1
+ * if the fork fails, since we asked by setting its
+ * want_signal to true.
+ */
+static void workload_exec_failed_signal(int signo, siginfo_t *info,
+ void *ucontext __maybe_unused)
+{
+ workload_exec_errno = info->si_value.sival_int;
+ done = 1;
+ signr = signo;
+ child_finished = 1;
+}
+
static int __cmd_record(struct record *rec, int argc, const char **argv)
{
int err;
@@ -359,7 +375,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
on_exit(record__sig_exit, rec);
signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler);
- signal(SIGUSR1, sig_handler);
signal(SIGTERM, sig_handler);
session = perf_session__new(file, false, NULL);
@@ -492,8 +507,20 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
/*
* Let the child rip
*/
- if (forks)
+ if (forks) {
+ struct sigaction act = {
+ .sa_flags = SA_SIGINFO,
+ .sa_sigaction = workload_exec_failed_signal,
+ };
+ /*
+ * perf_evlist__prepare_workload will, after we call
+ * perf_evlist__start_Workload, send a SIGUSR1 if the exec call
+ * fails, that we will catch in workload_signal to flip
+ * workload_exec_errno.
+ */
+ sigaction(SIGUSR1, &act, NULL);
perf_evlist__start_workload(evsel_list);
+ }
for (;;) {
int hits = rec->samples;
@@ -521,6 +548,14 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
}
}
+ if (forks && workload_exec_errno) {
+ char msg[512];
+ const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg));
+ pr_err("Workload failed: %s\n", emsg);
+ err = -1;
+ goto out_delete_session;
+ }
+
if (quiet || signr == SIGUSR1)
return 0;