if (forks) {
err = perf_evlist__prepare_workload(evsel_list, &opts->target,
argv, file->is_pipe,
- true);
+ workload_exec_failed_signal);
if (err < 0) {
pr_err("Couldn't run the workload!\n");
goto out_delete_session;
/*
* Let the child rip
*/
- 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);
+ if (forks)
perf_evlist__start_workload(evsel_list);
- }
for (;;) {
int hits = rec->samples;
#include "util/thread.h"
#include "util/thread_map.h"
-#include <signal.h>
#include <stdlib.h>
#include <sys/prctl.h>
#include <locale.h>
}
if (forks) {
- if (perf_evlist__prepare_workload(evsel_list, &target, argv,
- false, true) < 0) {
+ if (perf_evlist__prepare_workload(evsel_list, &target, argv, false,
+ workload_exec_failed_signal) < 0) {
perror("failed to prepare workload");
return -1;
}
clock_gettime(CLOCK_MONOTONIC, &ref_time);
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);
handle_initial_delay();
if (forks) {
err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
- argv, false, false);
+ argv, false, NULL);
if (err < 0) {
fprintf(trace->output, "Couldn't run the workload!\n");
goto out_delete_maps;
* so that we have time to open the evlist (calling sys_perf_event_open
* on all the fds) and then mmap them.
*/
- err = perf_evlist__prepare_workload(evlist, &opts.target, argv,
- false, false);
+ err = perf_evlist__prepare_workload(evlist, &opts.target, argv, false, NULL);
if (err < 0) {
pr_debug("Couldn't run the workload!\n");
goto out_delete_maps;
static int exited;
static int nr_exit;
-static void sig_handler(int sig)
+static void sig_handler(int sig __maybe_unused)
{
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;
}
/*
const char *argv[] = { "true", NULL };
signal(SIGCHLD, sig_handler);
- signal(SIGUSR1, sig_handler);
evlist = perf_evlist__new_default();
if (evlist == NULL) {
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) {
pr_debug("Couldn't run the workload!\n");
goto out_delete_maps;
int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target,
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];
char bf;
execvp(argv[0], (char **)argv);
- if (want_signal) {
+ if (exec_error) {
union sigval val;
val.sival_int = errno;
exit(-1);
}
+ if (exec_error) {
+ struct sigaction act = {
+ .sa_flags = SA_SIGINFO,
+ .sa_sigaction = exec_error,
+ };
+ sigaction(SIGUSR1, &act, NULL);
+ }
+
if (target__none(target))
evlist->threads->map[0] = evlist->workload.pid;
int perf_evlist__prepare_workload(struct perf_evlist *evlist,
struct target *target,
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__parse_mmap_pages(const struct option *opt,