Commit d07f0b12 authored by Stephane Eranian's avatar Stephane Eranian Committed by Arnaldo Carvalho de Melo
Browse files

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: default avatarStephane 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 079787f2
Loading
Loading
Loading
Loading
+22 −1
Original line number Diff line number Diff line
@@ -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;