if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
goto badframe;
err |= restore_i387(buf);
+ } else {
+ struct task_struct *me = current;
+ if (me->used_math) {
+ clear_fpu(me);
+ me->used_math = 0;
+ }
}
}
err |= __put_user(current->thread.error_code, &sc->err);
err |= __put_user(regs->eip, &sc->eip);
err |= __put_user(regs->xcs, (unsigned int __user *)&sc->cs);
+
+ /*
+ * Iff TF was set because the program is being single-stepped by a
+ * debugger, don't save that information on the signal stack.. We
+ * don't want debugging to change state.
+ */
eflags = regs->eflags;
- if (current->ptrace & PT_PTRACED) {
+ if (current->ptrace & PT_DTRACE)
eflags &= ~TF_MASK;
- }
err |= __put_user(eflags, &sc->eflags);
err |= __put_user(regs->esp, &sc->esp_at_signal);
err |= __put_user(regs->xss, (unsigned int __user *)&sc->ss);
regs->xes = __USER_DS;
regs->xss = __USER_DS;
regs->xcs = __USER_CS;
+
+ /*
+ * Clear TF when entering the signal handler, but
+ * notify any tracer that was single-stepping it.
+ * The tracer may want to single-step inside the
+ * handler too.
+ */
if (regs->eflags & TF_MASK) {
- if (current->ptrace & PT_PTRACED) {
+ regs->eflags &= ~TF_MASK;
+ if (current->ptrace & PT_DTRACE)
ptrace_notify(SIGTRAP);
- } else {
- regs->eflags &= ~TF_MASK;
- }
}
#if DEBUG_SIG
regs->xes = __USER_DS;
regs->xss = __USER_DS;
regs->xcs = __USER_CS;
+
+ /*
+ * Clear TF when entering the signal handler, but
+ * notify any tracer that was single-stepping it.
+ * The tracer may want to single-step inside the
+ * handler too.
+ */
if (regs->eflags & TF_MASK) {
- if (current->ptrace & PT_PTRACED) {
+ regs->eflags &= ~TF_MASK;
+ if (current->ptrace & PT_DTRACE)
ptrace_notify(SIGTRAP);
- } else {
- regs->eflags &= ~TF_MASK;
- }
}
#if DEBUG_SIG