diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 3479a118ba1c..f2fc3a9ea8fc 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -754,18 +754,21 @@ static inline int legacy_queue(struct sigpending *signals, int sig) | |||
754 | } | 754 | } |
755 | 755 | ||
756 | static int send_signal(int sig, struct siginfo *info, struct task_struct *t, | 756 | static int send_signal(int sig, struct siginfo *info, struct task_struct *t, |
757 | struct sigpending *signals) | 757 | int group) |
758 | { | 758 | { |
759 | struct sigpending *pending; | ||
759 | struct sigqueue *q; | 760 | struct sigqueue *q; |
760 | 761 | ||
761 | assert_spin_locked(&t->sighand->siglock); | 762 | assert_spin_locked(&t->sighand->siglock); |
762 | handle_stop_signal(sig, t); | 763 | handle_stop_signal(sig, t); |
764 | |||
765 | pending = group ? &t->signal->shared_pending : &t->pending; | ||
763 | /* | 766 | /* |
764 | * Short-circuit ignored signals and support queuing | 767 | * Short-circuit ignored signals and support queuing |
765 | * exactly one non-rt signal, so that we can get more | 768 | * exactly one non-rt signal, so that we can get more |
766 | * detailed information about the cause of the signal. | 769 | * detailed information about the cause of the signal. |
767 | */ | 770 | */ |
768 | if (sig_ignored(t, sig) || legacy_queue(signals, sig)) | 771 | if (sig_ignored(t, sig) || legacy_queue(pending, sig)) |
769 | return 0; | 772 | return 0; |
770 | 773 | ||
771 | /* | 774 | /* |
@@ -793,7 +796,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
793 | (is_si_special(info) || | 796 | (is_si_special(info) || |
794 | info->si_code >= 0))); | 797 | info->si_code >= 0))); |
795 | if (q) { | 798 | if (q) { |
796 | list_add_tail(&q->list, &signals->list); | 799 | list_add_tail(&q->list, &pending->list); |
797 | switch ((unsigned long) info) { | 800 | switch ((unsigned long) info) { |
798 | case (unsigned long) SEND_SIG_NOINFO: | 801 | case (unsigned long) SEND_SIG_NOINFO: |
799 | q->info.si_signo = sig; | 802 | q->info.si_signo = sig; |
@@ -823,7 +826,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
823 | } | 826 | } |
824 | 827 | ||
825 | out_set: | 828 | out_set: |
826 | sigaddset(&signals->signal, sig); | 829 | sigaddset(&pending->signal, sig); |
827 | return 1; | 830 | return 1; |
828 | } | 831 | } |
829 | 832 | ||
@@ -864,7 +867,7 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) | |||
864 | { | 867 | { |
865 | int ret; | 868 | int ret; |
866 | 869 | ||
867 | ret = send_signal(sig, info, t, &t->pending); | 870 | ret = send_signal(sig, info, t, 0); |
868 | if (ret <= 0) | 871 | if (ret <= 0) |
869 | return ret; | 872 | return ret; |
870 | 873 | ||
@@ -923,7 +926,7 @@ __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | |||
923 | * We always use the shared queue for process-wide signals, | 926 | * We always use the shared queue for process-wide signals, |
924 | * to avoid several races. | 927 | * to avoid several races. |
925 | */ | 928 | */ |
926 | ret = send_signal(sig, info, p, &p->signal->shared_pending); | 929 | ret = send_signal(sig, info, p, 1); |
927 | if (ret <= 0) | 930 | if (ret <= 0) |
928 | return ret; | 931 | return ret; |
929 | 932 | ||
@@ -1258,8 +1261,10 @@ void sigqueue_free(struct sigqueue *q) | |||
1258 | } | 1261 | } |
1259 | 1262 | ||
1260 | static int do_send_sigqueue(int sig, struct sigqueue *q, struct task_struct *t, | 1263 | static int do_send_sigqueue(int sig, struct sigqueue *q, struct task_struct *t, |
1261 | struct sigpending *pending) | 1264 | int group) |
1262 | { | 1265 | { |
1266 | struct sigpending *pending; | ||
1267 | |||
1263 | handle_stop_signal(sig, t); | 1268 | handle_stop_signal(sig, t); |
1264 | 1269 | ||
1265 | if (unlikely(!list_empty(&q->list))) { | 1270 | if (unlikely(!list_empty(&q->list))) { |
@@ -1277,8 +1282,10 @@ static int do_send_sigqueue(int sig, struct sigqueue *q, struct task_struct *t, | |||
1277 | return 1; | 1282 | return 1; |
1278 | 1283 | ||
1279 | signalfd_notify(t, sig); | 1284 | signalfd_notify(t, sig); |
1285 | pending = group ? &t->signal->shared_pending : &t->pending; | ||
1280 | list_add_tail(&q->list, &pending->list); | 1286 | list_add_tail(&q->list, &pending->list); |
1281 | sigaddset(&pending->signal, sig); | 1287 | sigaddset(&pending->signal, sig); |
1288 | |||
1282 | return 0; | 1289 | return 0; |
1283 | } | 1290 | } |
1284 | 1291 | ||
@@ -1300,7 +1307,7 @@ int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) | |||
1300 | if (!likely(lock_task_sighand(p, &flags))) | 1307 | if (!likely(lock_task_sighand(p, &flags))) |
1301 | goto out_err; | 1308 | goto out_err; |
1302 | 1309 | ||
1303 | ret = do_send_sigqueue(sig, q, p, &p->pending); | 1310 | ret = do_send_sigqueue(sig, q, p, 0); |
1304 | 1311 | ||
1305 | if (!sigismember(&p->blocked, sig)) | 1312 | if (!sigismember(&p->blocked, sig)) |
1306 | signal_wake_up(p, sig == SIGKILL); | 1313 | signal_wake_up(p, sig == SIGKILL); |
@@ -1321,7 +1328,7 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) | |||
1321 | /* Since it_lock is held, p->sighand cannot be NULL. */ | 1328 | /* Since it_lock is held, p->sighand cannot be NULL. */ |
1322 | spin_lock_irqsave(&p->sighand->siglock, flags); | 1329 | spin_lock_irqsave(&p->sighand->siglock, flags); |
1323 | 1330 | ||
1324 | ret = do_send_sigqueue(sig, q, p, &p->signal->shared_pending); | 1331 | ret = do_send_sigqueue(sig, q, p, 1); |
1325 | 1332 | ||
1326 | __group_complete_signal(sig, p); | 1333 | __group_complete_signal(sig, p); |
1327 | 1334 | ||