summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;
static bool no_inherit = false;
static bool scale = true;
static enum aggr_mode aggr_mode = AGGR_GLOBAL;
-static pid_t child_pid = -1;
+static volatile pid_t child_pid = -1;
static bool null_run = false;
static int detailed_run = 0;
static bool big_num = true;
@@ -1148,13 +1148,34 @@ static void skip_signal(int signo)
done = 1;
signr = signo;
+ /*
+ * render child_pid harmless
+ * won't send SIGTERM to a random
+ * process in case of race condition
+ * and fast PID recycling
+ */
+ child_pid = -1;
}
static void sig_atexit(void)
{
+ sigset_t set, oset;
+
+ /*
+ * avoid race condition with SIGCHLD handler
+ * in skip_signal() which is modifying child_pid
+ * goal is to avoid send SIGTERM to a random
+ * process
+ */
+ sigemptyset(&set);
+ sigaddset(&set, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &set, &oset);
+
if (child_pid != -1)
kill(child_pid, SIGTERM);
+ sigprocmask(SIG_SETMASK, &oset, NULL);
+
if (signr == -1)
return;