o Add a wrapper around sigaction(2), so we can insert our own wrapper
around signals. o Lock the process global signal action table.
This commit is contained in:
parent
4e519fdfeb
commit
3fb7bc9aec
@ -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
|
||||
|
@ -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 <sys/aio.h> */
|
||||
#ifdef _SYS_AIO_H_
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user