Commit ae74c3b6 authored by Linus Torvalds's avatar Linus Torvalds

Fix force_sig_info() semantics after cleanups

Suresh points out that commit b0423a0d
broke the semantics of a synchronous signal like SIGSEGV occurring
recursively inside its own handler handler (or, indeed, any other
context when the signal was blocked).

That was unintentional, and this fixes things up by reinstating the old
semantics, but without reverting the cleanups.

Cc: Paul E. McKenney <paulmck@us.ibm.com>
Acked-by: default avatarSuresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 202668ec
...@@ -791,22 +791,31 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) ...@@ -791,22 +791,31 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
/* /*
* Force a signal that the process can't ignore: if necessary * Force a signal that the process can't ignore: if necessary
* we unblock the signal and change any SIG_IGN to SIG_DFL. * we unblock the signal and change any SIG_IGN to SIG_DFL.
*
* Note: If we unblock the signal, we always reset it to SIG_DFL,
* since we do not want to have a signal handler that was blocked
* be invoked when user space had explicitly blocked it.
*
* We don't want to have recursive SIGSEGV's etc, for example.
*/ */
int int
force_sig_info(int sig, struct siginfo *info, struct task_struct *t) force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
{ {
unsigned long int flags; unsigned long int flags;
int ret; int ret, blocked, ignored;
struct k_sigaction *action;
spin_lock_irqsave(&t->sighand->siglock, flags); spin_lock_irqsave(&t->sighand->siglock, flags);
if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) { action = &t->sighand->action[sig-1];
t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; ignored = action->sa.sa_handler == SIG_IGN;
} blocked = sigismember(&t->blocked, sig);
if (sigismember(&t->blocked, sig)) { if (blocked || ignored) {
sigdelset(&t->blocked, sig); action->sa.sa_handler = SIG_DFL;
if (blocked) {
sigdelset(&t->blocked, sig);
recalc_sigpending_tsk(t);
}
} }
recalc_sigpending_tsk(t);
ret = specific_send_sig_info(sig, info, t); ret = specific_send_sig_info(sig, info, t);
spin_unlock_irqrestore(&t->sighand->siglock, flags); spin_unlock_irqrestore(&t->sighand->siglock, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment