From 3fb7bc9aecff9a81307b8f072d11a18f9f34f8c9 Mon Sep 17 00:00:00 2001 From: mtm Date: Tue, 9 Dec 2003 11:04:36 +0000 Subject: o Add a wrapper around sigaction(2), so we can insert our own wrapper around signals. o Lock the process global signal action table. --- lib/libthr/thread/Makefile.inc | 1 + lib/libthr/thread/thr_private.h | 3 +++ lib/libthr/thread/thr_syscalls.c | 58 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) (limited to 'lib/libthr') diff --git a/lib/libthr/thread/Makefile.inc b/lib/libthr/thread/Makefile.inc index 9c03def..896374c 100644 --- a/lib/libthr/thread/Makefile.inc +++ b/lib/libthr/thread/Makefile.inc @@ -46,6 +46,7 @@ SRCS+= \ thr_spec.c \ thr_spinlock.c \ thr_stack.c \ + thr_subr.c \ thr_suspend_np.c \ thr_syscalls.c \ thr_yield.c diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index c1e8b0a..41078a5 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -801,6 +801,9 @@ void _thread_critical_enter(pthread_t); void _thread_critical_exit(pthread_t); void _thread_sigblock(); void _thread_sigunblock(); +void proc_sigact_copyin(int, const struct sigaction *); +void proc_sigact_copyout(int, struct sigaction *); +struct sigaction *proc_sigact_sigaction(int); /* #include */ #ifdef _SYS_AIO_H_ 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 -- cgit v1.1