aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephane Eranian <eranian@google.com>2013-06-04 11:44:26 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-07-08 16:36:33 -0400
commitd07f0b120642f442d81a61f68a9325fb7717004f (patch)
tree0a0c3e465c98439a4ab98bbdb21892422b994ca1
parent079787f209416416383c74ea5d5044be2d586f5e (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>
-rw-r--r--tools/perf/builtin-stat.c23
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;
87static bool no_inherit = false; 87static bool no_inherit = false;
88static bool scale = true; 88static bool scale = true;
89static enum aggr_mode aggr_mode = AGGR_GLOBAL; 89static enum aggr_mode aggr_mode = AGGR_GLOBAL;
90static pid_t child_pid = -1; 90static volatile pid_t child_pid = -1;
91static bool null_run = false; 91static bool null_run = false;
92static int detailed_run = 0; 92static int detailed_run = 0;
93static bool big_num = true; 93static 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
1153static void sig_atexit(void) 1160static 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