Example #1
0
/*
 * If act is not NULL, set the action for signum.
 * If oact is not NULL. store the old action to oact.
 */
int
sigaction(int signum, const struct sigaction *act, struct sigaction *oact)
{
	struct sigaction *sa;

	if (signum <= 0 || signum >= NSIG ||
	    signum == SIGSTOP || signum == SIGKILL) {
		errno = EINVAL;
		return -1;
	}

	SIGNAL_LOCK();

	sa = &__sig_act[signum];

	if (oact != NULL)
		*oact = *sa;

	if (act != NULL)
		*sa = *act;

	/* Discard pending signal in some cases */
	if (sa->sa_handler == SIG_IGN ||
	    (sa->sa_handler == SIG_DFL && signum == SIGCHLD))
		__sig_pending &= ~sigmask(signum);

	SIGNAL_UNLOCK();

	/* Process pending signal */
	__sig_flush();

	return 0;
}
Example #2
0
/*
 * Exception handler for signal emulation
 */
static void
__exception_handler(int excpt)
{

	if (excpt > 0 && excpt <= NSIG) {

		SIGNAL_LOCK();

		if (__sig_act[excpt].sa_handler != SIG_IGN)
			__sig_pending |= sigmask(excpt);

		SIGNAL_UNLOCK();
	}
	__sig_flush();
	exception_return();
}
Example #3
0
int
pause(void)
{
	int sig, wait;

	/* Wait signal if no pending singal */
	if (__sig_flush()) {
		wait = 1;
		while (wait) {
			exception_wait(&sig);
			SIGNAL_LOCK();
			/* It is ok if processed signal is not masked and not pending */
			if (!(__sig_mask & sigmask(sig)) &&
			    !(__sig_pending & sigmask(sig)))
				wait = 0;
			SIGNAL_UNLOCK();
		}
	}
	/* Always returns error */
	errno = EINTR;
	return -1;
}
Example #4
0
/*
 * Process all pending and unmasked signal
 *
 * return 0 if at least one pending signal was processed.
 * return -1 if no signal was processed.
 */
int
__sig_flush(void)
{
	int sig;
	sigset_t active, org_mask;
	struct sigaction action;
	struct siginfo si;
	int rc = -1;

	sig = 1;
	for (;;) {
		SIGNAL_LOCK();
		active = __sig_pending & ~__sig_mask;
		action = __sig_act[sig];
		SIGNAL_UNLOCK();

		if (active == 0)
			break;
		if (active & sigmask(sig)) {

			SIGNAL_LOCK();
			org_mask = __sig_mask;
			__sig_mask |= action.sa_mask;
			SIGNAL_UNLOCK();

			if (action.sa_handler == SIG_DFL) {
				/* Default */
				switch (sig) {
				case SIGCHLD:
					/* XXX: */
					break;
				default:
					exit(0);
				}
			} else if (action.sa_handler != SIG_IGN) {
				/* User defined */
				if (action.sa_flags & SA_SIGINFO) {
					si.si_signo = sig;
					si.si_code = 0;
					si.si_value.sival_int = 0;
					action.sa_sigaction(sig, &si, NULL);
				} else {
					action.sa_handler(sig);
				}
			}
			SIGNAL_LOCK();
			__sig_pending &= ~sigmask(sig);
			__sig_mask = org_mask;
			SIGNAL_UNLOCK();

			switch (sig) {
			case SIGILL:
			case SIGTRAP:
			case SIGFPE:
			case SIGSEGV:
				for (;;);	/* exception from kernel */
				break;
			}
			if (action.sa_handler != SIG_IGN)
				rc = 0;	/* Signal is processed */
		}

		if (++sig >= NSIG)
			sig = 1;
	}
	return rc;
}