From f7b7c26e01e51fe46097e11f179dc71ce7950084 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 10 Jun 2009 15:55:59 +0200 Subject: perf_counter tools: Propagate signals properly Currently report and stat catch SIGINT (and others) without altering their exit state. This means that things like: while :; do perf stat ./foo ; done Loops become hard-to-interrupt, because bash never sees perf terminate due to interruption. Fix this. Signed-off-by: Peter Zijlstra Cc: Mike Galbraith Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo LKML-Reference: Signed-off-by: Ingo Molnar --- tools/perf/builtin-record.c | 12 ++++++++++++ tools/perf/builtin-stat.c | 13 +++++++++++++ 2 files changed, 25 insertions(+) (limited to 'tools/perf') diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index a5698add2fc..c10553c3460 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -169,10 +169,21 @@ static void mmap_read(struct mmap_data *md) } static volatile int done = 0; +static volatile int signr = -1; static void sig_handler(int sig) { done = 1; + signr = sig; +} + +static void sig_atexit(void) +{ + if (signr == -1) + return; + + signal(signr, SIG_DFL); + kill(getpid(), signr); } static void pid_synthesize_comm_event(pid_t pid, int full) @@ -459,6 +470,7 @@ static int __cmd_record(int argc, const char **argv) } else for (i = 0; i < nr_cpus; i++) open_counters(i, target_pid); + atexit(sig_atexit); signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 80855090fd9..6404906924f 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -296,8 +296,20 @@ static int do_perf_stat(int argc, const char **argv) return 0; } +static volatile int signr = -1; + static void skip_signal(int signo) { + signr = signo; +} + +static void sig_atexit(void) +{ + if (signr == -1) + return; + + signal(signr, SIG_DFL); + kill(getpid(), signr); } static const char * const stat_usage[] = { @@ -345,6 +357,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix) * What we want is for Ctrl-C to work in the exec()-ed * task, but being ignored by perf stat itself: */ + atexit(sig_atexit); signal(SIGINT, skip_signal); signal(SIGALRM, skip_signal); signal(SIGABRT, skip_signal); -- cgit v1.2.3