diff options
-rw-r--r-- | kernel/signal.c | 43 |
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 | */ | ||
737 | static 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 | ||
755 | static inline int is_si_special(const struct siginfo *info) | 732 | static 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. |