diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/signal.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 7fe874d12fae..bfdb5686fa3e 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -791,22 +791,31 @@ out: | |||
791 | /* | 791 | /* |
792 | * Force a signal that the process can't ignore: if necessary | 792 | * Force a signal that the process can't ignore: if necessary |
793 | * we unblock the signal and change any SIG_IGN to SIG_DFL. | 793 | * we unblock the signal and change any SIG_IGN to SIG_DFL. |
794 | * | ||
795 | * Note: If we unblock the signal, we always reset it to SIG_DFL, | ||
796 | * since we do not want to have a signal handler that was blocked | ||
797 | * be invoked when user space had explicitly blocked it. | ||
798 | * | ||
799 | * We don't want to have recursive SIGSEGV's etc, for example. | ||
794 | */ | 800 | */ |
795 | |||
796 | int | 801 | int |
797 | force_sig_info(int sig, struct siginfo *info, struct task_struct *t) | 802 | force_sig_info(int sig, struct siginfo *info, struct task_struct *t) |
798 | { | 803 | { |
799 | unsigned long int flags; | 804 | unsigned long int flags; |
800 | int ret; | 805 | int ret, blocked, ignored; |
806 | struct k_sigaction *action; | ||
801 | 807 | ||
802 | spin_lock_irqsave(&t->sighand->siglock, flags); | 808 | spin_lock_irqsave(&t->sighand->siglock, flags); |
803 | if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) { | 809 | action = &t->sighand->action[sig-1]; |
804 | t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; | 810 | ignored = action->sa.sa_handler == SIG_IGN; |
805 | } | 811 | blocked = sigismember(&t->blocked, sig); |
806 | if (sigismember(&t->blocked, sig)) { | 812 | if (blocked || ignored) { |
807 | sigdelset(&t->blocked, sig); | 813 | action->sa.sa_handler = SIG_DFL; |
814 | if (blocked) { | ||
815 | sigdelset(&t->blocked, sig); | ||
816 | recalc_sigpending_tsk(t); | ||
817 | } | ||
808 | } | 818 | } |
809 | recalc_sigpending_tsk(t); | ||
810 | ret = specific_send_sig_info(sig, info, t); | 819 | ret = specific_send_sig_info(sig, info, t); |
811 | spin_unlock_irqrestore(&t->sighand->siglock, flags); | 820 | spin_unlock_irqrestore(&t->sighand->siglock, flags); |
812 | 821 | ||