diff options
Diffstat (limited to 'tools/perf/builtin-record.c')
-rw-r--r-- | tools/perf/builtin-record.c | 39 |
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; |