diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-01-02 15:11:25 -0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2014-01-13 10:06:21 -0300 |
commit | f33cbe72e6166b97d6fa2400cb00a885b47999d7 (patch) | |
tree | 838b627d593e8ddc2b26db819bda78ec88d00a9c /tools/perf/builtin-record.c | |
parent | 6af206fd911c825b83dd4efb2534a3a34ce77072 (diff) | |
download | op-kernel-dev-f33cbe72e6166b97d6fa2400cb00a885b47999d7.zip op-kernel-dev-f33cbe72e6166b97d6fa2400cb00a885b47999d7.tar.gz |
perf evlist: Send the errno in the signal when workload fails
When a tool uses perf_evlist__start_workload and the supplied workload
fails (e.g.: its binary wasn't found), perror was being used to print
the error reason.
This is undesirable, as the caller may be a GUI, when it wants to have
total control of the error reporting process.
So move to using sigaction(SA_SIGINFO) + siginfo_t->sa_value->sival_int
to communicate to the caller the errno and let it print it using the UI
of its choosing.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-epgcv7kjq8ll2udqfken92pz@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
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 6ec0cbc..f987d38 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; |