aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2014-10-23 14:41:22 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2014-10-29 13:07:04 -0400
commiteca1a08986f622c11b75b3b44d561a1f901c9cec (patch)
tree15a635d885e693d2ee86aed4bcf988e8269d3606
parentd7e29933969e5ca7c112ce1368a07911f4485dc2 (diff)
signal: Exit RCU read-side critical section on each pass through loop
The kill_pid_info() can potentially loop indefinitely if tasks are created and deleted sufficiently quickly, and if this happens, this function will remain in a single RCU read-side critical section indefinitely. This commit therefore exits the RCU read-side critical section on each pass through the loop. Because a race must happen to retry the loop, this should have no performance impact in the common case. Reported-by: Dave Jones <davej@redhat.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Oleg Nesterov <oleg@redhat.com> Reviewed-by: Pranith Kumar <bobby.prani@gmail.com>
-rw-r--r--kernel/signal.c30
1 files changed, 14 insertions, 16 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 8f0876f9f6dd..54820984a872 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1331,23 +1331,21 @@ int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
1331 int error = -ESRCH; 1331 int error = -ESRCH;
1332 struct task_struct *p; 1332 struct task_struct *p;
1333 1333
1334 rcu_read_lock(); 1334 for (;;) {
1335retry: 1335 rcu_read_lock();
1336 p = pid_task(pid, PIDTYPE_PID); 1336 p = pid_task(pid, PIDTYPE_PID);
1337 if (p) { 1337 if (p)
1338 error = group_send_sig_info(sig, info, p); 1338 error = group_send_sig_info(sig, info, p);
1339 if (unlikely(error == -ESRCH)) 1339 rcu_read_unlock();
1340 /* 1340 if (likely(!p || error != -ESRCH))
1341 * The task was unhashed in between, try again. 1341 return error;
1342 * If it is dead, pid_task() will return NULL,
1343 * if we race with de_thread() it will find the
1344 * new leader.
1345 */
1346 goto retry;
1347 }
1348 rcu_read_unlock();
1349 1342
1350 return error; 1343 /*
1344 * The task was unhashed in between, try again. If it
1345 * is dead, pid_task() will return NULL, if we race with
1346 * de_thread() it will find the new leader.
1347 */
1348 }
1351} 1349}
1352 1350
1353int kill_proc_info(int sig, struct siginfo *info, pid_t pid) 1351int kill_proc_info(int sig, struct siginfo *info, pid_t pid)