diff options
author | Stephane Eranian <eranian@google.com> | 2013-06-04 11:44:26 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-07-08 16:36:33 -0400 |
commit | d07f0b120642f442d81a61f68a9325fb7717004f (patch) | |
tree | 0a0c3e465c98439a4ab98bbdb21892422b994ca1 /tools | |
parent | 079787f209416416383c74ea5d5044be2d586f5e (diff) |
perf stat: Avoid sending SIGTERM to random processes
This patch fixes a problem with perf stat whereby on termination it may
send a SIGTERM signal to random processes on systems with high PID
recycling. I got some actual bug reports on this.
There is race between the SIGCHLD and sig_atexit() handlers. This patch
addresses this problem by clearing child_pid in the SIGCHLD handler.
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20130604154426.GA2928@quad
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-stat.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 7e910bab1097..95768afaae3e 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -87,7 +87,7 @@ static int run_count = 1; | |||
87 | static bool no_inherit = false; | 87 | static bool no_inherit = false; |
88 | static bool scale = true; | 88 | static bool scale = true; |
89 | static enum aggr_mode aggr_mode = AGGR_GLOBAL; | 89 | static enum aggr_mode aggr_mode = AGGR_GLOBAL; |
90 | static pid_t child_pid = -1; | 90 | static volatile pid_t child_pid = -1; |
91 | static bool null_run = false; | 91 | static bool null_run = false; |
92 | static int detailed_run = 0; | 92 | static int detailed_run = 0; |
93 | static bool big_num = true; | 93 | static bool big_num = true; |
@@ -1148,13 +1148,34 @@ static void skip_signal(int signo) | |||
1148 | done = 1; | 1148 | done = 1; |
1149 | 1149 | ||
1150 | signr = signo; | 1150 | signr = signo; |
1151 | /* | ||
1152 | * render child_pid harmless | ||
1153 | * won't send SIGTERM to a random | ||
1154 | * process in case of race condition | ||
1155 | * and fast PID recycling | ||
1156 | */ | ||
1157 | child_pid = -1; | ||
1151 | } | 1158 | } |
1152 | 1159 | ||
1153 | static void sig_atexit(void) | 1160 | static void sig_atexit(void) |
1154 | { | 1161 | { |
1162 | sigset_t set, oset; | ||
1163 | |||
1164 | /* | ||
1165 | * avoid race condition with SIGCHLD handler | ||
1166 | * in skip_signal() which is modifying child_pid | ||
1167 | * goal is to avoid send SIGTERM to a random | ||
1168 | * process | ||
1169 | */ | ||
1170 | sigemptyset(&set); | ||
1171 | sigaddset(&set, SIGCHLD); | ||
1172 | sigprocmask(SIG_BLOCK, &set, &oset); | ||
1173 | |||
1155 | if (child_pid != -1) | 1174 | if (child_pid != -1) |
1156 | kill(child_pid, SIGTERM); | 1175 | kill(child_pid, SIGTERM); |
1157 | 1176 | ||
1177 | sigprocmask(SIG_SETMASK, &oset, NULL); | ||
1178 | |||
1158 | if (signr == -1) | 1179 | if (signr == -1) |
1159 | return; | 1180 | return; |
1160 | 1181 | ||