summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread/thr_syscalls.c
diff options
context:
space:
mode:
authormtm <mtm@FreeBSD.org>2003-12-09 11:04:36 +0000
committermtm <mtm@FreeBSD.org>2003-12-09 11:04:36 +0000
commit3fb7bc9aecff9a81307b8f072d11a18f9f34f8c9 (patch)
treee35c66d6530f0338c08ba206317bc1a8c857e006 /lib/libthr/thread/thr_syscalls.c
parent4e519fdfebb52ed6f448915d27a897f1740451c8 (diff)
downloadFreeBSD-src-3fb7bc9aecff9a81307b8f072d11a18f9f34f8c9.zip
FreeBSD-src-3fb7bc9aecff9a81307b8f072d11a18f9f34f8c9.tar.gz
o Add a wrapper around sigaction(2), so we can insert our own wrapper
around signals. o Lock the process global signal action table.
Diffstat (limited to 'lib/libthr/thread/thr_syscalls.c')
-rw-r--r--lib/libthr/thread/thr_syscalls.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c
index 1f11e82..badd7cb 100644
--- a/lib/libthr/thread/thr_syscalls.c
+++ b/lib/libthr/thread/thr_syscalls.c
@@ -94,6 +94,7 @@ extern int __creat(const char *, mode_t);
extern int __sleep(unsigned int);
extern int __sys_nanosleep(const struct timespec *, struct timespec *);
extern int __sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+extern int __sys_sigaction(int, const struct sigaction *, struct sigaction *);
extern int __system(const char *);
extern int __tcdrain(int);
extern pid_t __wait(int *);
@@ -314,6 +315,63 @@ _select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
return ret;
}
+__weak_reference(_sigaction, sigaction);
+
+int
+_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
+{
+ struct sigaction *tmpact;
+ struct sigaction oldact, wrapperact;
+ int error;
+
+ /* Detect invalid signals. Signal SIGTHR is silently ignored */
+ if (sig < 1 || sig > NSIG) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (sig == SIGTHR)
+ return (0);
+
+ /*
+ * If act is not NULL the library's signal wrapper is passed into the
+ * kernel only if the action is not SIG_DFL or SIG_IGN.
+ * On the other hand if act is NULL the caller only wants
+ * the old value so there is no need to call into the kernel.
+ */
+ error = 0;
+ tmpact = NULL;
+ proc_sigact_copyout(sig, &oldact);
+ if (act != NULL) {
+ proc_sigact_copyin(sig, act);
+ tmpact = proc_sigact_sigaction(sig);
+ if (tmpact->sa_handler != SIG_DFL &&
+ tmpact->sa_handler != SIG_IGN) {
+ bcopy((const void *)tmpact, (void *)&wrapperact,
+ sizeof(struct sigaction));
+ tmpact->sa_flags &= SA_SIGINFO;
+ wrapperact.sa_sigaction = &_thread_sig_wrapper;
+ tmpact = &wrapperact;
+ }
+ error = __sys_sigaction(sig, tmpact, NULL);
+ }
+ if (error == 0) {
+
+ /* If successful, return the old sigaction to the user */
+ if (oact != NULL )
+ bcopy((const void *)&oldact, (void *)oact,
+ sizeof(struct sigaction));
+ } else {
+
+ /*
+ * The only time error is non-zero is if the syscall failed,
+ * which means the sigaction in the process global list
+ * was altered before the syscall. Return it to it's old value.
+ */
+ proc_sigact_copyin(sig, &oldact);
+ }
+ return (error);
+}
+
__weak_reference(_sleep, sleep);
unsigned int
OpenPOWER on IntegriCloud