diff options
author | kib <kib@FreeBSD.org> | 2012-04-12 10:48:43 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2012-04-12 10:48:43 +0000 |
commit | 319ab382ef5fd326d3fab25c60ffe55702438a37 (patch) | |
tree | b11cc6ba65a78e38d9da1d9122832b5385fa56c5 | |
parent | aed1b833cf616d6a716d2a947c77fe99d6f3f925 (diff) | |
download | FreeBSD-src-319ab382ef5fd326d3fab25c60ffe55702438a37.zip FreeBSD-src-319ab382ef5fd326d3fab25c60ffe55702438a37.tar.gz |
Add thread-private flag to indicate that error value is already placed
in td_errno. Flag is supposed to be used by syscalls returning
EJUSTRETURN because errno was already placed into the usermode frame
by a call to set_syscall_retval(9). Both ktrace and dtrace get errno
value from td_errno if the flag is set.
Use the flag to fix sigsuspend(2) error return ktrace records.
Requested by: bde
MFC after: 1 week
-rw-r--r-- | sys/kern/kern_sig.c | 2 | ||||
-rw-r--r-- | sys/kern/subr_syscall.c | 10 | ||||
-rw-r--r-- | sys/sys/proc.h | 1 |
3 files changed, 10 insertions, 3 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 5460ffd..52a0c40 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1465,6 +1465,8 @@ kern_sigsuspend(struct thread *td, sigset_t mask) mtx_unlock(&p->p_sigacts->ps_mtx); } PROC_UNLOCK(p); + td->td_errno = EINTR; + td->td_pflags |= TDP_NERRNO; return (EJUSTRETURN); } diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c index 367ea67..5b48595 100644 --- a/sys/kern/subr_syscall.c +++ b/sys/kern/subr_syscall.c @@ -136,7 +136,8 @@ syscallenter(struct thread *td, struct syscall_args *sa) AUDIT_SYSCALL_EXIT(error, td); /* Save the latest error return value. */ - td->td_errno = error; + if ((td->td_pflags & TDP_NERRNO) == 0) + td->td_errno = error; #ifdef KDTRACE_HOOKS /* @@ -191,9 +192,12 @@ syscallret(struct thread *td, int error, struct syscall_args *sa __unused) syscallname(p, sa->code), td, td->td_proc->p_pid, td->td_name); #ifdef KTRACE - if (KTRPOINT(td, KTR_SYSRET)) - ktrsysret(sa->code, error, td->td_retval[0]); + if (KTRPOINT(td, KTR_SYSRET)) { + ktrsysret(sa->code, (td->td_pflags & TDP_NERRNO) == 0 ? + error : td->td_errno, td->td_retval[0]); + } #endif + td->td_pflags &= ~TDP_NERRNO; if (p->p_flag & P_TRACED) { traced = 1; diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 6dad36b..2e9016c 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -418,6 +418,7 @@ do { \ #define TDP_AUDITREC 0x01000000 /* Audit record pending on thread */ #define TDP_RFPPWAIT 0x02000000 /* Handle RFPPWAIT on syscall exit */ #define TDP_RESETSPUR 0x04000000 /* Reset spurious page fault history. */ +#define TDP_NERRNO 0x08000000 /* Last errno is already in td_errno */ /* * Reasons that the current thread can not be run yet. |