Commit 4a30debf authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Linus Torvalds

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: default avatarOleg 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: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 964ee7df
...@@ -233,6 +233,8 @@ static inline int valid_signal(unsigned long sig) ...@@ -233,6 +233,8 @@ static inline int valid_signal(unsigned long sig)
} }
extern int next_signal(struct sigpending *pending, sigset_t *mask); extern int next_signal(struct sigpending *pending, sigset_t *mask);
extern int do_send_sig_info(int sig, struct siginfo *info,
struct task_struct *p, bool group);
extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p); extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *); extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
extern long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, extern long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig,
......
...@@ -971,6 +971,20 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) ...@@ -971,6 +971,20 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
return send_signal(sig, info, t, 0); return send_signal(sig, info, t, 0);
} }
int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,
bool group)
{
unsigned long flags;
int ret = -ESRCH;
if (lock_task_sighand(p, &flags)) {
ret = send_signal(sig, info, p, group);
unlock_task_sighand(p, &flags);
}
return ret;
}
/* /*
* Force a signal that the process can't ignore: if necessary * Force a signal that the process can't ignore: if necessary
* we unblock the signal and change any SIG_IGN to SIG_DFL. * 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,18 +1082,10 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long
*/ */
int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{ {
unsigned long flags; int ret = check_kill_permission(sig, info, p);
int ret;
ret = check_kill_permission(sig, info, p); if (!ret && sig)
ret = do_send_sig_info(sig, info, p, true);
if (!ret && sig) {
ret = -ESRCH;
if (lock_task_sighand(p, &flags)) {
ret = __group_send_sig_info(sig, info, p);
unlock_task_sighand(p, &flags);
}
}
return ret; return ret;
} }
...@@ -1224,15 +1230,9 @@ static int kill_something_info(int sig, struct siginfo *info, pid_t pid) ...@@ -1224,15 +1230,9 @@ static int kill_something_info(int sig, struct siginfo *info, pid_t pid)
* These are for backward compatibility with the rest of the kernel source. * These are for backward compatibility with the rest of the kernel source.
*/ */
/*
* The caller must ensure the task can't exit.
*/
int int
send_sig_info(int sig, struct siginfo *info, struct task_struct *p) send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{ {
int ret;
unsigned long flags;
/* /*
* Make sure legacy kernel users don't send in bad values * Make sure legacy kernel users don't send in bad values
* (normal paths check this in check_kill_permission). * (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,10 +1240,7 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
if (!valid_signal(sig)) if (!valid_signal(sig))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&p->sighand->siglock, flags); return do_send_sig_info(sig, info, p, false);
ret = specific_send_sig_info(sig, info, p);
spin_unlock_irqrestore(&p->sighand->siglock, flags);
return ret;
} }
#define __si_special(priv) \ #define __si_special(priv) \
...@@ -2278,7 +2275,6 @@ static int ...@@ -2278,7 +2275,6 @@ static int
do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info) do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
{ {
struct task_struct *p; struct task_struct *p;
unsigned long flags;
int error = -ESRCH; int error = -ESRCH;
rcu_read_lock(); rcu_read_lock();
...@@ -2288,14 +2284,16 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info) ...@@ -2288,14 +2284,16 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
/* /*
* The null signal is a permissions and process existence * The null signal is a permissions and process existence
* probe. No signal is actually delivered. * probe. No signal is actually delivered.
*
* If lock_task_sighand() fails we pretend the task dies
* after receiving the signal. The window is tiny, and the
* signal is private anyway.
*/ */
if (!error && sig && lock_task_sighand(p, &flags)) { if (!error && sig) {
error = specific_send_sig_info(sig, info, p); error = do_send_sig_info(sig, info, p, false);
unlock_task_sighand(p, &flags); /*
* If lock_task_sighand() failed we pretend the task
* dies after receiving the signal. The window is tiny,
* and the signal is private anyway.
*/
if (unlikely(error == -ESRCH))
error = 0;
} }
} }
rcu_read_unlock(); rcu_read_unlock();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment