summaryrefslogtreecommitdiff
path: root/arch/sparc64/kernel/signal.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-05-01 03:30:22 -0700
committerDavid S. Miller <davem@davemloft.net>2008-05-02 05:22:52 -0700
commit2678fefedbbc03a3ae6f5c254791bf147d6c52fd (patch)
tree23052dffe4591f06192b8ee9cd17a1160fe4520f /arch/sparc64/kernel/signal.c
parent32039f4954938e4d761032d7046254d08d0db54c (diff)
sparc64: Fix syscall restart, for real...
The change I put into copy_thread() just papered over the real problem. When we are looking to see if we should do a syscall restart, when deliverying a signal, we should only interpret the syscall return value as an error if the carry condition code(s) are set. Otherwise it's a success return. Also, sigreturn paths should do a pt_regs_clear_trap_type(). It turns out that doing a syscall restart when returning from a fork() does and should happen, from time to time. Even if copy_thread() returns success, copy_process() can still unwind and signal -ERESTARTNOINTR in the parent. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/signal.c')
-rw-r--r--arch/sparc64/kernel/signal.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
index f2d88d8f7a42..45d6bf632daa 100644
--- a/arch/sparc64/kernel/signal.c
+++ b/arch/sparc64/kernel/signal.c
@@ -332,6 +332,9 @@ void do_rt_sigreturn(struct pt_regs *regs)
regs->tpc = tpc;
regs->tnpc = tnpc;
+ /* Prevent syscall restart. */
+ pt_regs_clear_trap_type(regs);
+
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
current->blocked = set;
@@ -515,7 +518,8 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
siginfo_t info;
int signr;
- if (pt_regs_is_syscall(regs)) {
+ if (pt_regs_is_syscall(regs) &&
+ (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
pt_regs_clear_trap_type(regs);
cookie.restart_syscall = 1;
} else