Commit cbdfb9ff authored by Al Viro's avatar Al Viro

alpha: tidy signal delivery up

* move force_sigsegv() (from setup...frame()) and clearing RESTART_SIGMASK
(from do_signal()) into hanlde_signal()
* get rid of handle_signal() return value and oldset argument
* checking for TIF_SIGPENDING is enough; set_restart_sigmask() sets this
one as well.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent cf4a0ce4
...@@ -34,9 +34,6 @@ ...@@ -34,9 +34,6 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage void ret_from_sys_call(void); asmlinkage void ret_from_sys_call(void);
static void do_signal(struct pt_regs *, struct switch_stack *,
unsigned long, unsigned long);
/* /*
* The OSF/1 sigprocmask calling sequence is different from the * The OSF/1 sigprocmask calling sequence is different from the
...@@ -367,11 +364,11 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -367,11 +364,11 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
oldsp = rdusp(); oldsp = rdusp();
frame = get_sigframe(ka, oldsp, sizeof(*frame)); frame = get_sigframe(ka, oldsp, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Set up to return from userspace. If provided, use a stub /* Set up to return from userspace. If provided, use a stub
already in userspace. */ already in userspace. */
...@@ -387,7 +384,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -387,7 +384,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
/* Check that everything was written properly. */ /* Check that everything was written properly. */
if (err) if (err)
goto give_sigsegv; return err;
/* "Return" to the handler */ /* "Return" to the handler */
regs->r26 = r26; regs->r26 = r26;
...@@ -401,12 +398,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -401,12 +398,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
current->comm, current->pid, frame, regs->pc, regs->r26); current->comm, current->pid, frame, regs->pc, regs->r26);
#endif #endif
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static int static int
...@@ -419,7 +411,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -419,7 +411,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
oldsp = rdusp(); oldsp = rdusp();
frame = get_sigframe(ka, oldsp, sizeof(*frame)); frame = get_sigframe(ka, oldsp, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, info);
...@@ -434,7 +426,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -434,7 +426,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
set->sig[0], oldsp); set->sig[0], oldsp);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Set up to return from userspace. If provided, use a stub /* Set up to return from userspace. If provided, use a stub
already in userspace. */ already in userspace. */
...@@ -450,7 +442,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -450,7 +442,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} }
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* "Return" to the handler */ /* "Return" to the handler */
regs->r26 = r26; regs->r26 = r26;
...@@ -466,31 +458,37 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -466,31 +458,37 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif #endif
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
/* /*
* OK, we're invoking a handler. * OK, we're invoking a handler.
*/ */
static inline int static inline void
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw) struct pt_regs * regs, struct switch_stack *sw)
{ {
sigset_t *oldset = &current->blocked;
int ret; int ret;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
else else
ret = setup_frame(sig, ka, oldset, regs, sw); ret = setup_frame(sig, ka, oldset, regs, sw);
if (ret == 0) if (ret) {
block_sigmask(ka, sig); force_sigsegv(sig, current);
return;
return ret; }
block_sigmask(ka, sig);
/* A signal was successfully delivered, and the
saved sigmask was stored on the signal frame,
and will be restored by sigreturn. So we can
simply clear the restore sigmask flag. */
clear_thread_flag(TIF_RESTORE_SIGMASK);
} }
static inline void static inline void
...@@ -538,12 +536,6 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, ...@@ -538,12 +536,6 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
int signr; int signr;
unsigned long single_stepping = ptrace_cancel_bpt(current); unsigned long single_stepping = ptrace_cancel_bpt(current);
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
/* This lets the debugger run, ... */ /* This lets the debugger run, ... */
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
...@@ -555,14 +547,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, ...@@ -555,14 +547,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (r0) if (r0)
syscall_restart(r0, r19, regs, &ka); syscall_restart(r0, r19, regs, &ka);
if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) { handle_signal(signr, &ka, &info, regs, sw);
/* A signal was successfully delivered, and the
saved sigmask was stored on the signal frame,
and will be restored by sigreturn. So we can
simply clear the restore sigmask flag. */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
if (single_stepping) if (single_stepping)
ptrace_set_bpt(current); /* re-set bpt */ ptrace_set_bpt(current); /* re-set bpt */
return; return;
...@@ -587,10 +572,8 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, ...@@ -587,10 +572,8 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
} }
/* If there's no signal to deliver, we just restore the saved mask. */ /* If there's no signal to deliver, we just restore the saved mask. */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK); set_current_blocked(&current->saved_sigmask);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
if (single_stepping) if (single_stepping)
ptrace_set_bpt(current); /* re-set breakpoint */ ptrace_set_bpt(current); /* re-set breakpoint */
...@@ -601,7 +584,7 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, ...@@ -601,7 +584,7 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
unsigned long thread_info_flags, unsigned long thread_info_flags,
unsigned long r0, unsigned long r19) unsigned long r0, unsigned long r19)
{ {
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs, sw, r0, r19); do_signal(regs, sw, r0, r19);
if (thread_info_flags & _TIF_NOTIFY_RESUME) { if (thread_info_flags & _TIF_NOTIFY_RESUME) {
......
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