diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2008-04-30 03:52:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:36 -0400 |
commit | 5fcd835bf8c2cde06404559b1904e2f1dfcb4567 (patch) | |
tree | c370d13b34d7c516c449427aebfde5bd29c83489 /kernel/signal.c | |
parent | 2ca3515aa57224edf0151e05a8c9f21a76bf5957 (diff) |
signals: use __group_complete_signal() for the specific signals too
Based on Pavel Emelyanov's suggestion.
Rename __group_complete_signal() to complete_signal() and use it to process
the specific signals too. To do this we simply add the "int group" argument.
This allows us to greatly simply the signal-sending code and adds a useful
behaviour change. We can avoid the unneeded wakeups for the private signals
because wants_signal() is more clever than sigismember(blocked), but more
importantly we now take into account the fatal specific signals too.
The latter allows us to kill some subtle checks in handle_stop_signal() and
makes the specific/group signal's behaviour more consistent. For example,
currently sigtimedwait(FATAL_SIGNAL) behaves differently depending on was the
signal sent by kill() or tkill() if the signal was not blocked.
And. This allows us to tweak/fix the behaviour when the specific signal is
sent to the dying/dead ->group_leader.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
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.c | 15 |
1 files changed, 6 insertions, 9 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index f2fc3a9ea8fc..fc1cb03c241c 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -673,8 +673,7 @@ static inline int wants_signal(int sig, struct task_struct *p) | |||
673 | return task_curr(p) || !signal_pending(p); | 673 | return task_curr(p) || !signal_pending(p); |
674 | } | 674 | } |
675 | 675 | ||
676 | static void | 676 | static void complete_signal(int sig, struct task_struct *p, int group) |
677 | __group_complete_signal(int sig, struct task_struct *p) | ||
678 | { | 677 | { |
679 | struct signal_struct *signal = p->signal; | 678 | struct signal_struct *signal = p->signal; |
680 | struct task_struct *t; | 679 | struct task_struct *t; |
@@ -687,7 +686,7 @@ __group_complete_signal(int sig, struct task_struct *p) | |||
687 | */ | 686 | */ |
688 | if (wants_signal(sig, p)) | 687 | if (wants_signal(sig, p)) |
689 | t = p; | 688 | t = p; |
690 | else if (thread_group_empty(p)) | 689 | else if (!group || thread_group_empty(p)) |
691 | /* | 690 | /* |
692 | * There is just one thread and it does not need to be woken. | 691 | * There is just one thread and it does not need to be woken. |
693 | * It will dequeue unblocked signals before it runs again. | 692 | * It will dequeue unblocked signals before it runs again. |
@@ -871,8 +870,7 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) | |||
871 | if (ret <= 0) | 870 | if (ret <= 0) |
872 | return ret; | 871 | return ret; |
873 | 872 | ||
874 | if (!sigismember(&t->blocked, sig)) | 873 | complete_signal(sig, t, 0); |
875 | signal_wake_up(t, sig == SIGKILL); | ||
876 | return 0; | 874 | return 0; |
877 | } | 875 | } |
878 | 876 | ||
@@ -930,7 +928,7 @@ __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | |||
930 | if (ret <= 0) | 928 | if (ret <= 0) |
931 | return ret; | 929 | return ret; |
932 | 930 | ||
933 | __group_complete_signal(sig, p); | 931 | complete_signal(sig, p, 1); |
934 | return 0; | 932 | return 0; |
935 | } | 933 | } |
936 | 934 | ||
@@ -1309,8 +1307,7 @@ int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) | |||
1309 | 1307 | ||
1310 | ret = do_send_sigqueue(sig, q, p, 0); | 1308 | ret = do_send_sigqueue(sig, q, p, 0); |
1311 | 1309 | ||
1312 | if (!sigismember(&p->blocked, sig)) | 1310 | complete_signal(sig, p, 0); |
1313 | signal_wake_up(p, sig == SIGKILL); | ||
1314 | 1311 | ||
1315 | unlock_task_sighand(p, &flags); | 1312 | unlock_task_sighand(p, &flags); |
1316 | out_err: | 1313 | out_err: |
@@ -1330,7 +1327,7 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) | |||
1330 | 1327 | ||
1331 | ret = do_send_sigqueue(sig, q, p, 1); | 1328 | ret = do_send_sigqueue(sig, q, p, 1); |
1332 | 1329 | ||
1333 | __group_complete_signal(sig, p); | 1330 | complete_signal(sig, p, 1); |
1334 | 1331 | ||
1335 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | 1332 | spin_unlock_irqrestore(&p->sighand->siglock, flags); |
1336 | 1333 | ||