diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-10-23 14:41:22 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2014-10-29 13:07:04 -0400 |
commit | eca1a08986f622c11b75b3b44d561a1f901c9cec (patch) | |
tree | 15a635d885e693d2ee86aed4bcf988e8269d3606 | |
parent | d7e29933969e5ca7c112ce1368a07911f4485dc2 (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.c | 30 |
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 (;;) { |
1335 | retry: | 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 | ||
1353 | int kill_proc_info(int sig, struct siginfo *info, pid_t pid) | 1351 | int kill_proc_info(int sig, struct siginfo *info, pid_t pid) |