perf evlist: Move the SIGUSR1 error reporting logic to prepare_workload

So that we have the boilerplate in the preparation method, instead of
open coded in tools wanting the reporting when the exec fails.

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-purbdzcphdveskh7wwmnm4t7@git.kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent f33cbe72
...@@ -390,7 +390,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) ...@@ -390,7 +390,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
if (forks) { if (forks) {
err = perf_evlist__prepare_workload(evsel_list, &opts->target, err = perf_evlist__prepare_workload(evsel_list, &opts->target,
argv, file->is_pipe, argv, file->is_pipe,
true); workload_exec_failed_signal);
if (err < 0) { if (err < 0) {
pr_err("Couldn't run the workload!\n"); pr_err("Couldn't run the workload!\n");
goto out_delete_session; goto out_delete_session;
...@@ -507,20 +507,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) ...@@ -507,20 +507,8 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
/* /*
* Let the child rip * 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); perf_evlist__start_workload(evsel_list);
}
for (;;) { for (;;) {
int hits = rec->samples; int hits = rec->samples;
......
...@@ -58,7 +58,6 @@ ...@@ -58,7 +58,6 @@
#include "util/thread.h" #include "util/thread.h"
#include "util/thread_map.h" #include "util/thread_map.h"
#include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <locale.h> #include <locale.h>
...@@ -542,8 +541,8 @@ static int __run_perf_stat(int argc, const char **argv) ...@@ -542,8 +541,8 @@ static int __run_perf_stat(int argc, const char **argv)
} }
if (forks) { if (forks) {
if (perf_evlist__prepare_workload(evsel_list, &target, argv, if (perf_evlist__prepare_workload(evsel_list, &target, argv, false,
false, true) < 0) { workload_exec_failed_signal) < 0) {
perror("failed to prepare workload"); perror("failed to prepare workload");
return -1; return -1;
} }
...@@ -598,18 +597,6 @@ static int __run_perf_stat(int argc, const char **argv) ...@@ -598,18 +597,6 @@ static int __run_perf_stat(int argc, const char **argv)
clock_gettime(CLOCK_MONOTONIC, &ref_time); clock_gettime(CLOCK_MONOTONIC, &ref_time);
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); perf_evlist__start_workload(evsel_list);
handle_initial_delay(); handle_initial_delay();
......
...@@ -1895,7 +1895,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -1895,7 +1895,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
if (forks) { if (forks) {
err = perf_evlist__prepare_workload(evlist, &trace->opts.target, err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
argv, false, false); argv, false, NULL);
if (err < 0) { if (err < 0) {
fprintf(trace->output, "Couldn't run the workload!\n"); fprintf(trace->output, "Couldn't run the workload!\n");
goto out_delete_maps; goto out_delete_maps;
......
...@@ -83,8 +83,7 @@ int test__PERF_RECORD(void) ...@@ -83,8 +83,7 @@ int test__PERF_RECORD(void)
* so that we have time to open the evlist (calling sys_perf_event_open * so that we have time to open the evlist (calling sys_perf_event_open
* on all the fds) and then mmap them. * on all the fds) and then mmap them.
*/ */
err = perf_evlist__prepare_workload(evlist, &opts.target, argv, err = perf_evlist__prepare_workload(evlist, &opts.target, argv, false, NULL);
false, false);
if (err < 0) { if (err < 0) {
pr_debug("Couldn't run the workload!\n"); pr_debug("Couldn't run the workload!\n");
goto out_delete_maps; goto out_delete_maps;
......
...@@ -9,12 +9,21 @@ ...@@ -9,12 +9,21 @@
static int exited; static int exited;
static int nr_exit; static int nr_exit;
static void sig_handler(int sig) static void sig_handler(int sig __maybe_unused)
{ {
exited = 1; exited = 1;
}
if (sig == SIGUSR1) /*
nr_exit = -1; * perf_evlist__prepare_workload will send a SIGUSR1 if the fork fails, since
* we asked by setting its exec_error to this handler.
*/
static void workload_exec_failed_signal(int signo __maybe_unused,
siginfo_t *info __maybe_unused,
void *ucontext __maybe_unused)
{
exited = 1;
nr_exit = -1;
} }
/* /*
...@@ -35,7 +44,6 @@ int test__task_exit(void) ...@@ -35,7 +44,6 @@ int test__task_exit(void)
const char *argv[] = { "true", NULL }; const char *argv[] = { "true", NULL };
signal(SIGCHLD, sig_handler); signal(SIGCHLD, sig_handler);
signal(SIGUSR1, sig_handler);
evlist = perf_evlist__new_default(); evlist = perf_evlist__new_default();
if (evlist == NULL) { if (evlist == NULL) {
...@@ -57,7 +65,8 @@ int test__task_exit(void) ...@@ -57,7 +65,8 @@ int test__task_exit(void)
goto out_delete_maps; goto out_delete_maps;
} }
err = perf_evlist__prepare_workload(evlist, &target, argv, false, true); err = perf_evlist__prepare_workload(evlist, &target, argv, false,
workload_exec_failed_signal);
if (err < 0) { if (err < 0) {
pr_debug("Couldn't run the workload!\n"); pr_debug("Couldn't run the workload!\n");
goto out_delete_maps; goto out_delete_maps;
......
...@@ -1029,7 +1029,7 @@ int perf_evlist__open(struct perf_evlist *evlist) ...@@ -1029,7 +1029,7 @@ int perf_evlist__open(struct perf_evlist *evlist)
int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target, int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target,
const char *argv[], bool pipe_output, const char *argv[], bool pipe_output,
bool want_signal) void (*exec_error)(int signo, siginfo_t *info, void *ucontext))
{ {
int child_ready_pipe[2], go_pipe[2]; int child_ready_pipe[2], go_pipe[2];
char bf; char bf;
...@@ -1073,7 +1073,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar ...@@ -1073,7 +1073,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
execvp(argv[0], (char **)argv); execvp(argv[0], (char **)argv);
if (want_signal) { if (exec_error) {
union sigval val; union sigval val;
val.sival_int = errno; val.sival_int = errno;
...@@ -1084,6 +1084,14 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar ...@@ -1084,6 +1084,14 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
exit(-1); exit(-1);
} }
if (exec_error) {
struct sigaction act = {
.sa_flags = SA_SIGINFO,
.sa_sigaction = exec_error,
};
sigaction(SIGUSR1, &act, NULL);
}
if (target__none(target)) if (target__none(target))
evlist->threads->map[0] = evlist->workload.pid; evlist->threads->map[0] = evlist->workload.pid;
......
...@@ -103,7 +103,8 @@ int record_opts__config(struct record_opts *opts); ...@@ -103,7 +103,8 @@ int record_opts__config(struct record_opts *opts);
int perf_evlist__prepare_workload(struct perf_evlist *evlist, int perf_evlist__prepare_workload(struct perf_evlist *evlist,
struct target *target, struct target *target,
const char *argv[], bool pipe_output, const char *argv[], bool pipe_output,
bool want_signal); void (*exec_error)(int signo, siginfo_t *info,
void *ucontext));
int perf_evlist__start_workload(struct perf_evlist *evlist); int perf_evlist__start_workload(struct perf_evlist *evlist);
int perf_evlist__parse_mmap_pages(const struct option *opt, int perf_evlist__parse_mmap_pages(const struct option *opt,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment