int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { struct sigaction sa; if (sig == SIGTHR) { errno = EINVAL; return (-1); } if (act != NULL && sigismember(&act->sa_mask, SIGTHR)) { sa = *act; sigdelset(&sa.sa_mask, SIGTHR); act = &sa; } return (_thread_sys_sigaction(sig, act, oact)); }
void _thread_exit(const char *fname, int lineno, const char *string) { char s[256]; /* Prepare an error message string: */ s[0] = '\0'; strlcat(s, "pid ", sizeof s); numlcat(s, (int)_thread_sys_getpid(), sizeof s); strlcat(s, ": Fatal error '", sizeof s); strlcat(s, string, sizeof s); strlcat(s, "' at line ", sizeof s); numlcat(s, lineno, sizeof s); strlcat(s, " in file ", sizeof s); strlcat(s, fname, sizeof s); strlcat(s, " (errno = ", sizeof s); numlcat(s, errno, sizeof s); strlcat(s, ")\n", sizeof s); /* Write the string to the standard error file descriptor: */ _thread_sys_write(2, s, strlen(s)); /* Force this process to exit: */ /* XXX - Do we want abort to be conditional on _PTHREADS_INVARIANTS? */ #if defined(_PTHREADS_INVARIANTS) { struct sigaction sa; sigset_t s; /* Ignore everything except ABORT */ sigfillset(&s); sigdelset(&s, SIGABRT); _thread_sys_sigprocmask(SIG_SETMASK, &s, NULL); /* Set the abort handler to default (dump core) */ sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO; (void)_thread_sys_sigaction(SIGABRT, &sa, NULL); (void)_thread_sys_kill(_thread_sys_getpid(), SIGABRT); for (;;) ; } #else _exit(1); #endif }
sig_t _thread_sys_signal(int s, sig_t a) { struct sigaction sa; struct sigaction osa; /* Initialise the signal action structure: */ sigemptyset(&sa.sa_mask); sa.sa_handler = a; sa.sa_flags = SA_SIGINFO; /* Perform the sigaction syscall: */ if (_thread_sys_sigaction(s, &sa, &osa) < 0) { /* Return an error: */ return (SIG_ERR); } /* Return a pointer to the old signal handler: */ return (osa.sa_handler); }
int sigaction(int sig, const struct sigaction * act, struct sigaction * oact) { int ret = 0; struct sigaction gact; /* Check if the signal number is out of range: */ if (sig < 1 || sig >= NSIG) { /* Return an invalid argument: */ errno = EINVAL; ret = -1; } else { /* * Check if the existing signal action structure contents are * to be returned: */ if (oact != NULL) { /* Return the existing signal action contents: */ oact->sa_handler = _thread_sigact[sig - 1].sa_handler; oact->sa_mask = _thread_sigact[sig - 1].sa_mask; oact->sa_flags = _thread_sigact[sig - 1].sa_flags; } /* Check if a signal action was supplied: */ if (act != NULL) { /* Set the new signal handler: */ _thread_sigact[sig - 1].sa_mask = act->sa_mask; _thread_sigact[sig - 1].sa_flags = act->sa_flags; _thread_sigact[sig - 1].sa_handler = act->sa_handler; } /* * Check if the kernel needs to be advised of a change * in signal action: */ if (act != NULL && sig != _SCHED_SIGNAL && sig != SIGCHLD && sig != SIGINFO) { gact.sa_mask = act->sa_mask; sigaddset(&gact.sa_mask, _SCHED_SIGNAL); gact.sa_flags = act->sa_flags | SA_SIGINFO; /* * Check if the signal handler is being set to * the default or ignore handlers: */ if (act->sa_handler == SIG_DFL || act->sa_handler == SIG_IGN) /* Specify the built in handler: */ gact.sa_handler = act->sa_handler; else /* Specify the thread kernel signal handler */ gact.sa_handler = (void (*) (int)) _thread_sig_handler; /* Change the signal action in the kernel: */ if (_thread_sys_sigaction(sig, &gact, NULL) != 0) ret = -1; } } /* Return the completion status: */ return (ret); }