X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fparisc%2Fkernel%2Fsignal.c;h=4a0a8adbc79d7ca68ee0e8146c221ac65de8f73a;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=b220bb22f79cfc78ed5e89e6da5b123ecb331edf;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index b220bb22f..4a0a8adbc 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -494,11 +494,9 @@ give_sigsegv: */ static long -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs *regs, int in_syscall) +handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, + sigset_t *oldset, struct pt_regs *regs, int in_syscall) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n", sig, ka, info, oldset, regs); @@ -506,9 +504,6 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) return 0; - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -535,7 +530,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) { siginfo_t info; - struct k_sigaction *ka; + struct k_sigaction ka; int signr; DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n", @@ -553,10 +548,15 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) oldset->sig[0], oldset->sig[1]); - signr = get_signal_to_deliver(&info, regs, NULL); - DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); + /* May need to force signal if handle_signal failed to deliver */ + while (1) { + + signr = get_signal_to_deliver(&info, &ka, regs, NULL); + DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); - if (signr > 0) { + if (signr <= 0) + break; + /* Restart a system call if necessary. */ if (in_syscall) { /* Check the return code */ @@ -569,8 +569,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) break; case -ERESTARTSYS: - ka = ¤t->sighand->action[signr-1]; - if (!(ka->sa.sa_flags & SA_RESTART)) { + if (!(ka.sa.sa_flags & SA_RESTART)) { DBG(1,"ERESTARTSYS: putting -EINTR\n"); regs->gr[28] = -EINTR; break; @@ -578,8 +577,7 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) /* fallthrough */ case -ERESTARTNOINTR: /* A syscall is just a branch, so all - we have to do is fiddle the return - pointer. */ + we have to do is fiddle the return pointer. */ regs->gr[31] -= 8; /* delayed branching */ /* Preserve original r28. */ regs->gr[28] = regs->orig_r28; @@ -589,12 +587,13 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) /* Whee! Actually deliver the signal. If the delivery failed, we need to continue to iterate in this loop so we can deliver the SIGSEGV... */ - if (handle_signal(signr, &info, oldset, regs, in_syscall)) { + if (handle_signal(signr, &info, &ka, oldset, regs, in_syscall)) { DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", regs->gr[28]); return 1; } } + /* end of while(1) looping forever if we can't force a signal */ /* Did we come from a system call? */ if (in_syscall) {