/* {{{ zend_sigaction * Register a signal handler that will be deferred in critical sections */ ZEND_API int zend_sigaction(int signo, const struct sigaction *act, struct sigaction *oldact) { struct sigaction sa = {{0}}; sigset_t sigset; if (oldact != NULL) { oldact->sa_flags = SIGG(handlers)[signo-1].flags; oldact->sa_handler = (void *) SIGG(handlers)[signo-1].handler; oldact->sa_mask = global_sigmask; } if (act != NULL) { SIGG(handlers)[signo-1].flags = act->sa_flags; if (act->sa_flags & SA_SIGINFO) { SIGG(handlers)[signo-1].handler = (void *) act->sa_sigaction; } else { SIGG(handlers)[signo-1].handler = (void *) act->sa_handler; } sa.sa_flags = SA_SIGINFO | (act->sa_flags & SA_FLAGS_MASK); sa.sa_sigaction = zend_signal_handler_defer; sa.sa_mask = global_sigmask; if (sigaction(signo, &sa, NULL) < 0) { zend_error_noreturn(E_ERROR, "Error installing signal handler for %d", signo); } /* unsure this signal is not blocked */ sigemptyset(&sigset); sigaddset(&sigset, signo); zend_sigprocmask(SIG_UNBLOCK, &sigset, NULL); } return SUCCESS; }
/* {{{ zend_signal_handler * Call the previously registered handler for a signal */ static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context) { int errno_save = errno; struct sigaction sa; sigset_t sigset; zend_signal_entry_t p_sig = SIGG(handlers)[signo-1]; if (p_sig.handler == SIG_DFL) { /* raise default handler */ if (sigaction(signo, NULL, &sa) == 0) { sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); sigemptyset(&sigset); sigaddset(&sigset, signo); if (sigaction(signo, &sa, NULL) == 0) { /* throw away any blocked signals */ zend_sigprocmask(SIG_UNBLOCK, &sigset, NULL); #ifdef ZTS # define RAISE_ERROR "raise() failed\n" if (raise(signo) != 0) { /* On some systems raise() fails with errno 3: No such process */ kill(getpid(), signo); } #else kill(getpid(), signo); #endif } } } else { if (p_sig.flags & SA_SIGINFO) { if (p_sig.flags & SA_RESETHAND) { SIGG(handlers)[signo-1].flags = 0; SIGG(handlers)[signo-1].handler = SIG_DFL; } (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context); } else { (*(void (*)(int))p_sig.handler)(signo); } } errno = errno_save; } /* }}} */