aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2009-09-23 18:57:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-24 10:21:01 -0400
commit4a30debfb778240a4b1767d4b0c5a5b25ab97160 (patch)
treebc4fed4ebb8368ebbfa719a004b15101b0a71d53 /kernel/signal.c
parent964ee7df90d799e38fb1556c57cd5c45fc736436 (diff)
signals: introduce do_send_sig_info() helper
Introduce do_send_sig_info() and convert group_send_sig_info(), send_sig_info(), do_send_specific() to use this helper. Hopefully it will have more users soon, it allows to specify specific/group behaviour via "bool group" argument. Shaves 80 bytes from .text. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: stephane eranian <eranian@googlemail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Roland McGrath <roland@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c56
1 files changed, 27 insertions, 29 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 5d3b3f8f219b..c6d7a24a86a1 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -971,6 +971,20 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
971 return send_signal(sig, info, t, 0); 971 return send_signal(sig, info, t, 0);
972} 972}
973 973
974int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,
975 bool group)
976{
977 unsigned long flags;
978 int ret = -ESRCH;
979
980 if (lock_task_sighand(p, &flags)) {
981 ret = send_signal(sig, info, p, group);
982 unlock_task_sighand(p, &flags);
983 }
984
985 return ret;
986}
987
974/* 988/*
975 * Force a signal that the process can't ignore: if necessary 989 * Force a signal that the process can't ignore: if necessary
976 * we unblock the signal and change any SIG_IGN to SIG_DFL. 990 * we unblock the signal and change any SIG_IGN to SIG_DFL.
@@ -1068,18 +1082,10 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long
1068 */ 1082 */
1069int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) 1083int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
1070{ 1084{
1071 unsigned long flags; 1085 int ret = check_kill_permission(sig, info, p);
1072 int ret;
1073
1074 ret = check_kill_permission(sig, info, p);
1075 1086
1076 if (!ret && sig) { 1087 if (!ret && sig)
1077 ret = -ESRCH; 1088 ret = do_send_sig_info(sig, info, p, true);
1078 if (lock_task_sighand(p, &flags)) {
1079 ret = __group_send_sig_info(sig, info, p);
1080 unlock_task_sighand(p, &flags);
1081 }
1082 }
1083 1089
1084 return ret; 1090 return ret;
1085} 1091}
@@ -1224,15 +1230,9 @@ static int kill_something_info(int sig, struct siginfo *info, pid_t pid)
1224 * These are for backward compatibility with the rest of the kernel source. 1230 * These are for backward compatibility with the rest of the kernel source.
1225 */ 1231 */
1226 1232
1227/*
1228 * The caller must ensure the task can't exit.
1229 */
1230int 1233int
1231send_sig_info(int sig, struct siginfo *info, struct task_struct *p) 1234send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
1232{ 1235{
1233 int ret;
1234 unsigned long flags;
1235
1236 /* 1236 /*
1237 * Make sure legacy kernel users don't send in bad values 1237 * Make sure legacy kernel users don't send in bad values
1238 * (normal paths check this in check_kill_permission). 1238 * (normal paths check this in check_kill_permission).
@@ -1240,10 +1240,7 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
1240 if (!valid_signal(sig)) 1240 if (!valid_signal(sig))
1241 return -EINVAL; 1241 return -EINVAL;
1242 1242
1243 spin_lock_irqsave(&p->sighand->siglock, flags); 1243 return do_send_sig_info(sig, info, p, false);
1244 ret = specific_send_sig_info(sig, info, p);
1245 spin_unlock_irqrestore(&p->sighand->siglock, flags);
1246 return ret;
1247} 1244}
1248 1245
1249#define __si_special(priv) \ 1246#define __si_special(priv) \
@@ -2278,7 +2275,6 @@ static int
2278do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info) 2275do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
2279{ 2276{
2280 struct task_struct *p; 2277 struct task_struct *p;
2281 unsigned long flags;
2282 int error = -ESRCH; 2278 int error = -ESRCH;
2283 2279
2284 rcu_read_lock(); 2280 rcu_read_lock();
@@ -2288,14 +2284,16 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
2288 /* 2284 /*
2289 * The null signal is a permissions and process existence 2285 * The null signal is a permissions and process existence
2290 * probe. No signal is actually delivered. 2286 * probe. No signal is actually delivered.
2291 *
2292 * If lock_task_sighand() fails we pretend the task dies
2293 * after receiving the signal. The window is tiny, and the
2294 * signal is private anyway.
2295 */ 2287 */
2296 if (!error && sig && lock_task_sighand(p, &flags)) { 2288 if (!error && sig) {
2297 error = specific_send_sig_info(sig, info, p); 2289 error = do_send_sig_info(sig, info, p, false);
2298 unlock_task_sighand(p, &flags); 2290 /*
2291 * If lock_task_sighand() failed we pretend the task
2292 * dies after receiving the signal. The window is tiny,
2293 * and the signal is private anyway.
2294 */
2295 if (unlikely(error == -ESRCH))
2296 error = 0;
2299 } 2297 }
2300 } 2298 }
2301 rcu_read_unlock(); 2299 rcu_read_unlock();