123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- #define _GNU_SOURCE
- #include <string.h>
- #include "zend.h"
- #include "zend_globals.h"
- #include <signal.h>
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #ifdef ZEND_SIGNALS
- #include "zend_signal.h"
- #ifdef ZTS
- ZEND_API int zend_signal_globals_id;
- ZEND_API size_t zend_signal_globals_offset;
- #else
- ZEND_API zend_signal_globals_t zend_signal_globals;
- #endif
- #define SIGNAL_BEGIN_CRITICAL() \
- sigset_t oldmask; \
- zend_sigprocmask(SIG_BLOCK, &global_sigmask, &oldmask);
- #define SIGNAL_END_CRITICAL() \
- zend_sigprocmask(SIG_SETMASK, &oldmask, NULL);
- #ifdef ZTS
- # define zend_sigprocmask(signo, set, oldset) tsrm_sigmask((signo), (set), (oldset))
- #else
- # define zend_sigprocmask(signo, set, oldset) sigprocmask((signo), (set), (oldset))
- #endif
- static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context);
- static int zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void*));
- #if defined(__CYGWIN__) || defined(__PASE__)
- #define TIMEOUT_SIG SIGALRM
- #else
- #define TIMEOUT_SIG SIGPROF
- #endif
- static int zend_sigs[] = { TIMEOUT_SIG, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGUSR2 };
- #define SA_FLAGS_MASK ~(SA_NODEFER | SA_RESETHAND)
- static zend_signal_entry_t global_orig_handlers[NSIG];
- static sigset_t global_sigmask;
- void zend_signal_handler_defer(int signo, siginfo_t *siginfo, void *context)
- {
- int errno_save = errno;
- zend_signal_queue_t *queue, *qtmp;
- #ifdef ZTS
-
- if (tsrm_is_shutdown()) {
-
- zend_signal_handler(signo, siginfo, context);
- return;
- }
- #endif
- if (EXPECTED(SIGG(active))) {
- if (UNEXPECTED(SIGG(depth) == 0)) {
- if (UNEXPECTED(SIGG(blocked))) {
- SIGG(blocked) = 0;
- }
- if (EXPECTED(SIGG(running) == 0)) {
- SIGG(running) = 1;
- zend_signal_handler(signo, siginfo, context);
- queue = SIGG(phead);
- SIGG(phead) = NULL;
- while (queue) {
- zend_signal_handler(queue->zend_signal.signo, queue->zend_signal.siginfo, queue->zend_signal.context);
- qtmp = queue->next;
- queue->next = SIGG(pavail);
- queue->zend_signal.signo = 0;
- SIGG(pavail) = queue;
- queue = qtmp;
- }
- SIGG(running) = 0;
- }
- } else {
- SIGG(blocked) = 1;
- if ((queue = SIGG(pavail))) {
- SIGG(pavail) = queue->next;
- queue->zend_signal.signo = signo;
- queue->zend_signal.siginfo = siginfo;
- queue->zend_signal.context = context;
- queue->next = NULL;
- if (SIGG(phead) && SIGG(ptail)) {
- SIGG(ptail)->next = queue;
- } else {
- SIGG(phead) = queue;
- }
- SIGG(ptail) = queue;
- }
- #if ZEND_DEBUG
- else {
- zend_output_debug_string(0, "zend_signal: not enough queue storage, lost signal (%d)", signo);
- }
- #endif
- }
- } else {
-
- zend_signal_handler(signo, siginfo, context);
- }
- errno = errno_save;
- }
- ZEND_API void zend_signal_handler_unblock(void)
- {
- zend_signal_queue_t *queue;
- zend_signal_t zend_signal;
- if (EXPECTED(SIGG(active))) {
- SIGNAL_BEGIN_CRITICAL();
- queue = SIGG(phead);
- SIGG(phead) = queue->next;
- zend_signal = queue->zend_signal;
- queue->next = SIGG(pavail);
- queue->zend_signal.signo = 0;
- SIGG(pavail) = queue;
- zend_signal_handler_defer(zend_signal.signo, zend_signal.siginfo, zend_signal.context);
- SIGNAL_END_CRITICAL();
- }
- }
- 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;
- #ifdef ZTS
- if (tsrm_is_shutdown()) {
- p_sig.flags = 0;
- p_sig.handler = SIG_DFL;
- } else
- #endif
- p_sig = SIGG(handlers)[signo-1];
- if (p_sig.handler == SIG_DFL) {
- 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) {
-
- zend_sigprocmask(SIG_UNBLOCK, &sigset, NULL);
- #ifdef ZTS
- # define RAISE_ERROR "raise() failed\n"
- if (raise(signo) != 0) {
-
- kill(getpid(), signo);
- }
- #else
- kill(getpid(), signo);
- #endif
- }
- }
- } else if (p_sig.handler != SIG_IGN) {
- 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;
- }
- ZEND_API void zend_sigaction(int signo, const struct sigaction *act, struct sigaction *oldact)
- {
- struct sigaction sa;
- 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;
- }
- memset(&sa, 0, sizeof(sa));
- if (SIGG(handlers)[signo-1].handler == (void *) SIG_IGN) {
- sa.sa_sigaction = (void *) SIG_IGN;
- } else {
- 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);
- }
-
- sigemptyset(&sigset);
- sigaddset(&sigset, signo);
- zend_sigprocmask(SIG_UNBLOCK, &sigset, NULL);
- }
- }
- ZEND_API void zend_signal(int signo, void (*handler)(int))
- {
- struct sigaction sa;
- memset(&sa, 0, sizeof(sa));
- sa.sa_flags = 0;
- sa.sa_handler = handler;
- sa.sa_mask = global_sigmask;
- zend_sigaction(signo, &sa, NULL);
- }
- static zend_result zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void*))
- {
- struct sigaction sa;
- if (sigaction(signo, NULL, &sa) == 0) {
- if ((sa.sa_flags & SA_SIGINFO) && sa.sa_sigaction == handler) {
- return FAILURE;
- }
- SIGG(handlers)[signo-1].flags = sa.sa_flags;
- if (sa.sa_flags & SA_SIGINFO) {
- SIGG(handlers)[signo-1].handler = (void *)sa.sa_sigaction;
- } else {
- SIGG(handlers)[signo-1].handler = (void *)sa.sa_handler;
- }
- sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = handler;
- sa.sa_mask = global_sigmask;
- if (sigaction(signo, &sa, NULL) < 0) {
- zend_error_noreturn(E_ERROR, "Error installing signal handler for %d", signo);
- }
- return SUCCESS;
- }
- return FAILURE;
- }
- void zend_signal_activate(void)
- {
- size_t x;
- memcpy(&SIGG(handlers), &global_orig_handlers, sizeof(global_orig_handlers));
- if (SIGG(reset)) {
- for (x = 0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
- zend_signal_register(zend_sigs[x], zend_signal_handler_defer);
- }
- }
- SIGG(active) = 1;
- SIGG(depth) = 0;
- }
- void zend_signal_deactivate(void)
- {
- if (SIGG(check)) {
- size_t x;
- struct sigaction sa;
- if (SIGG(depth) != 0) {
- zend_error(E_CORE_WARNING, "zend_signal: shutdown with non-zero blocking depth (%d)", SIGG(depth));
- }
-
- for (x = 0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
- sigaction(zend_sigs[x], NULL, &sa);
- if (sa.sa_sigaction != zend_signal_handler_defer &&
- sa.sa_sigaction != (void *) SIG_IGN) {
- zend_error(E_CORE_WARNING, "zend_signal: handler was replaced for signal (%d) after startup", zend_sigs[x]);
- }
- }
- }
-
- *((volatile int *) &SIGG(active)) = 0;
- SIGG(running) = 0;
- SIGG(blocked) = 0;
- SIGG(depth) = 0;
-
- if (SIGG(phead) && SIGG(ptail)) {
- SIGG(ptail)->next = SIGG(pavail);
- SIGG(pavail) = SIGG(phead);
- SIGG(phead) = NULL;
- SIGG(ptail) = NULL;
- }
- }
- static void zend_signal_globals_ctor(zend_signal_globals_t *zend_signal_globals)
- {
- size_t x;
- memset(zend_signal_globals, 0, sizeof(*zend_signal_globals));
- zend_signal_globals->reset = 1;
- for (x = 0; x < sizeof(zend_signal_globals->pstorage) / sizeof(*zend_signal_globals->pstorage); ++x) {
- zend_signal_queue_t *queue = &zend_signal_globals->pstorage[x];
- queue->zend_signal.signo = 0;
- queue->next = zend_signal_globals->pavail;
- zend_signal_globals->pavail = queue;
- }
- }
- void zend_signal_init(void)
- {
- int signo;
- struct sigaction sa;
-
- memset(&global_orig_handlers, 0, sizeof(global_orig_handlers));
- for (signo = 1; signo < NSIG; ++signo) {
- if (sigaction(signo, NULL, &sa) == 0) {
- global_orig_handlers[signo-1].flags = sa.sa_flags;
- if (sa.sa_flags & SA_SIGINFO) {
- global_orig_handlers[signo-1].handler = (void *) sa.sa_sigaction;
- } else {
- global_orig_handlers[signo-1].handler = (void *) sa.sa_handler;
- }
- }
- }
- }
- ZEND_API void zend_signal_startup(void)
- {
- #ifdef ZTS
- ts_allocate_fast_id(&zend_signal_globals_id, &zend_signal_globals_offset, sizeof(zend_signal_globals_t), (ts_allocate_ctor) zend_signal_globals_ctor, NULL);
- #else
- zend_signal_globals_ctor(&zend_signal_globals);
- #endif
-
- sigfillset(&global_sigmask);
- sigdelset(&global_sigmask, SIGILL);
- sigdelset(&global_sigmask, SIGABRT);
- sigdelset(&global_sigmask, SIGFPE);
- sigdelset(&global_sigmask, SIGKILL);
- sigdelset(&global_sigmask, SIGSEGV);
- sigdelset(&global_sigmask, SIGCONT);
- sigdelset(&global_sigmask, SIGSTOP);
- sigdelset(&global_sigmask, SIGTSTP);
- sigdelset(&global_sigmask, SIGTTIN);
- sigdelset(&global_sigmask, SIGTTOU);
- #ifdef SIGBUS
- sigdelset(&global_sigmask, SIGBUS);
- #endif
- #ifdef SIGSYS
- sigdelset(&global_sigmask, SIGSYS);
- #endif
- #ifdef SIGTRAP
- sigdelset(&global_sigmask, SIGTRAP);
- #endif
- zend_signal_init();
- }
- #endif
|