diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/signal.c | 46 |
1 files changed, 11 insertions, 35 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index fc1cb03c241c..87424f7a4f3d 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -826,7 +826,8 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
826 | 826 | ||
827 | out_set: | 827 | out_set: |
828 | sigaddset(&pending->signal, sig); | 828 | sigaddset(&pending->signal, sig); |
829 | return 1; | 829 | complete_signal(sig, t, group); |
830 | return 0; | ||
830 | } | 831 | } |
831 | 832 | ||
832 | int print_fatal_signals; | 833 | int print_fatal_signals; |
@@ -861,17 +862,16 @@ static int __init setup_print_fatal_signals(char *str) | |||
861 | 862 | ||
862 | __setup("print-fatal-signals=", setup_print_fatal_signals); | 863 | __setup("print-fatal-signals=", setup_print_fatal_signals); |
863 | 864 | ||
865 | int | ||
866 | __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | ||
867 | { | ||
868 | return send_signal(sig, info, p, 1); | ||
869 | } | ||
870 | |||
864 | static int | 871 | static int |
865 | specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) | 872 | specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) |
866 | { | 873 | { |
867 | int ret; | 874 | return send_signal(sig, info, t, 0); |
868 | |||
869 | ret = send_signal(sig, info, t, 0); | ||
870 | if (ret <= 0) | ||
871 | return ret; | ||
872 | |||
873 | complete_signal(sig, t, 0); | ||
874 | return 0; | ||
875 | } | 875 | } |
876 | 876 | ||
877 | /* | 877 | /* |
@@ -914,24 +914,6 @@ force_sig_specific(int sig, struct task_struct *t) | |||
914 | force_sig_info(sig, SEND_SIG_FORCED, t); | 914 | force_sig_info(sig, SEND_SIG_FORCED, t); |
915 | } | 915 | } |
916 | 916 | ||
917 | int | ||
918 | __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | ||
919 | { | ||
920 | int ret; | ||
921 | |||
922 | /* | ||
923 | * Put this signal on the shared-pending queue, or fail with EAGAIN. | ||
924 | * We always use the shared queue for process-wide signals, | ||
925 | * to avoid several races. | ||
926 | */ | ||
927 | ret = send_signal(sig, info, p, 1); | ||
928 | if (ret <= 0) | ||
929 | return ret; | ||
930 | |||
931 | complete_signal(sig, p, 1); | ||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | /* | 917 | /* |
936 | * Nuke all other threads in the group. | 918 | * Nuke all other threads in the group. |
937 | */ | 919 | */ |
@@ -1263,6 +1245,7 @@ static int do_send_sigqueue(int sig, struct sigqueue *q, struct task_struct *t, | |||
1263 | { | 1245 | { |
1264 | struct sigpending *pending; | 1246 | struct sigpending *pending; |
1265 | 1247 | ||
1248 | BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); | ||
1266 | handle_stop_signal(sig, t); | 1249 | handle_stop_signal(sig, t); |
1267 | 1250 | ||
1268 | if (unlikely(!list_empty(&q->list))) { | 1251 | if (unlikely(!list_empty(&q->list))) { |
@@ -1283,6 +1266,7 @@ static int do_send_sigqueue(int sig, struct sigqueue *q, struct task_struct *t, | |||
1283 | pending = group ? &t->signal->shared_pending : &t->pending; | 1266 | pending = group ? &t->signal->shared_pending : &t->pending; |
1284 | list_add_tail(&q->list, &pending->list); | 1267 | list_add_tail(&q->list, &pending->list); |
1285 | sigaddset(&pending->signal, sig); | 1268 | sigaddset(&pending->signal, sig); |
1269 | complete_signal(sig, t, group); | ||
1286 | 1270 | ||
1287 | return 0; | 1271 | return 0; |
1288 | } | 1272 | } |
@@ -1292,8 +1276,6 @@ int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) | |||
1292 | unsigned long flags; | 1276 | unsigned long flags; |
1293 | int ret = -1; | 1277 | int ret = -1; |
1294 | 1278 | ||
1295 | BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); | ||
1296 | |||
1297 | /* | 1279 | /* |
1298 | * The rcu based delayed sighand destroy makes it possible to | 1280 | * The rcu based delayed sighand destroy makes it possible to |
1299 | * run this without tasklist lock held. The task struct itself | 1281 | * run this without tasklist lock held. The task struct itself |
@@ -1307,8 +1289,6 @@ int send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) | |||
1307 | 1289 | ||
1308 | ret = do_send_sigqueue(sig, q, p, 0); | 1290 | ret = do_send_sigqueue(sig, q, p, 0); |
1309 | 1291 | ||
1310 | complete_signal(sig, p, 0); | ||
1311 | |||
1312 | unlock_task_sighand(p, &flags); | 1292 | unlock_task_sighand(p, &flags); |
1313 | out_err: | 1293 | out_err: |
1314 | return ret; | 1294 | return ret; |
@@ -1320,15 +1300,11 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) | |||
1320 | unsigned long flags; | 1300 | unsigned long flags; |
1321 | int ret; | 1301 | int ret; |
1322 | 1302 | ||
1323 | BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); | ||
1324 | |||
1325 | /* Since it_lock is held, p->sighand cannot be NULL. */ | 1303 | /* Since it_lock is held, p->sighand cannot be NULL. */ |
1326 | spin_lock_irqsave(&p->sighand->siglock, flags); | 1304 | spin_lock_irqsave(&p->sighand->siglock, flags); |
1327 | 1305 | ||
1328 | ret = do_send_sigqueue(sig, q, p, 1); | 1306 | ret = do_send_sigqueue(sig, q, p, 1); |
1329 | 1307 | ||
1330 | complete_signal(sig, p, 1); | ||
1331 | |||
1332 | spin_unlock_irqrestore(&p->sighand->siglock, flags); | 1308 | spin_unlock_irqrestore(&p->sighand->siglock, flags); |
1333 | 1309 | ||
1334 | return ret; | 1310 | return ret; |