aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/signal.c43
1 files changed, 10 insertions, 33 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 251ca9c9d666..19316dc3eb0b 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -728,29 +728,6 @@ static int rm_from_queue_full(sigset_t *mask, struct sigpending *s)
728 } 728 }
729 return 1; 729 return 1;
730} 730}
731/*
732 * Remove signals in mask from the pending set and queue.
733 * Returns 1 if any signals were found.
734 *
735 * All callers must be holding the siglock.
736 */
737static int rm_from_queue(unsigned long mask, struct sigpending *s)
738{
739 struct sigqueue *q, *n;
740
741 if (!sigtestsetmask(&s->signal, mask))
742 return 0;
743
744 sigdelsetmask(&s->signal, mask);
745 list_for_each_entry_safe(q, n, &s->list, list) {
746 if (q->info.si_signo < SIGRTMIN &&
747 (mask & sigmask(q->info.si_signo))) {
748 list_del_init(&q->list);
749 __sigqueue_free(q);
750 }
751 }
752 return 1;
753}
754 731
755static inline int is_si_special(const struct siginfo *info) 732static inline int is_si_special(const struct siginfo *info)
756{ 733{
@@ -862,6 +839,7 @@ static bool prepare_signal(int sig, struct task_struct *p, bool force)
862{ 839{
863 struct signal_struct *signal = p->signal; 840 struct signal_struct *signal = p->signal;
864 struct task_struct *t; 841 struct task_struct *t;
842 sigset_t flush;
865 843
866 if (signal->flags & (SIGNAL_GROUP_EXIT | SIGNAL_GROUP_COREDUMP)) { 844 if (signal->flags & (SIGNAL_GROUP_EXIT | SIGNAL_GROUP_COREDUMP)) {
867 if (signal->flags & SIGNAL_GROUP_COREDUMP) 845 if (signal->flags & SIGNAL_GROUP_COREDUMP)
@@ -873,26 +851,25 @@ static bool prepare_signal(int sig, struct task_struct *p, bool force)
873 /* 851 /*
874 * This is a stop signal. Remove SIGCONT from all queues. 852 * This is a stop signal. Remove SIGCONT from all queues.
875 */ 853 */
876 rm_from_queue(sigmask(SIGCONT), &signal->shared_pending); 854 siginitset(&flush, sigmask(SIGCONT));
877 t = p; 855 rm_from_queue_full(&flush, &signal->shared_pending);
878 do { 856 for_each_thread(p, t)
879 rm_from_queue(sigmask(SIGCONT), &t->pending); 857 rm_from_queue_full(&flush, &t->pending);
880 } while_each_thread(p, t);
881 } else if (sig == SIGCONT) { 858 } else if (sig == SIGCONT) {
882 unsigned int why; 859 unsigned int why;
883 /* 860 /*
884 * Remove all stop signals from all queues, wake all threads. 861 * Remove all stop signals from all queues, wake all threads.
885 */ 862 */
886 rm_from_queue(SIG_KERNEL_STOP_MASK, &signal->shared_pending); 863 siginitset(&flush, SIG_KERNEL_STOP_MASK);
887 t = p; 864 rm_from_queue_full(&flush, &signal->shared_pending);
888 do { 865 for_each_thread(p, t) {
866 rm_from_queue_full(&flush, &t->pending);
889 task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING); 867 task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING);
890 rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending);
891 if (likely(!(t->ptrace & PT_SEIZED))) 868 if (likely(!(t->ptrace & PT_SEIZED)))
892 wake_up_state(t, __TASK_STOPPED); 869 wake_up_state(t, __TASK_STOPPED);
893 else 870 else
894 ptrace_trap_notify(t); 871 ptrace_trap_notify(t);
895 } while_each_thread(p, t); 872 }
896 873
897 /* 874 /*
898 * Notify the parent with CLD_CONTINUED if we were stopped. 875 * Notify the parent with CLD_CONTINUED if we were stopped.