diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 3d3adb94561d..b0b43a4ad8dd 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -1050,17 +1050,26 @@ int kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp) | |||
1050 | 1050 | ||
1051 | int kill_pid_info(int sig, struct siginfo *info, struct pid *pid) | 1051 | int kill_pid_info(int sig, struct siginfo *info, struct pid *pid) |
1052 | { | 1052 | { |
1053 | int error; | 1053 | int error = -ESRCH; |
1054 | struct task_struct *p; | 1054 | struct task_struct *p; |
1055 | 1055 | ||
1056 | rcu_read_lock(); | 1056 | rcu_read_lock(); |
1057 | if (unlikely(sig_needs_tasklist(sig))) | 1057 | if (unlikely(sig_needs_tasklist(sig))) |
1058 | read_lock(&tasklist_lock); | 1058 | read_lock(&tasklist_lock); |
1059 | 1059 | ||
1060 | retry: | ||
1060 | p = pid_task(pid, PIDTYPE_PID); | 1061 | p = pid_task(pid, PIDTYPE_PID); |
1061 | error = -ESRCH; | 1062 | if (p) { |
1062 | if (p) | ||
1063 | error = group_send_sig_info(sig, info, p); | 1063 | error = group_send_sig_info(sig, info, p); |
1064 | if (unlikely(error == -ESRCH)) | ||
1065 | /* | ||
1066 | * The task was unhashed in between, try again. | ||
1067 | * If it is dead, pid_task() will return NULL, | ||
1068 | * if we race with de_thread() it will find the | ||
1069 | * new leader. | ||
1070 | */ | ||
1071 | goto retry; | ||
1072 | } | ||
1064 | 1073 | ||
1065 | if (unlikely(sig_needs_tasklist(sig))) | 1074 | if (unlikely(sig_needs_tasklist(sig))) |
1066 | read_unlock(&tasklist_lock); | 1075 | read_unlock(&tasklist_lock); |