From 022d24cac1c0c7f210ff5d4723d44b682b8fbf0e Mon Sep 17 00:00:00 2001 From: Dragan Dosen Date: Fri, 4 Jan 2008 00:57:06 +0000 Subject: [PATCH] r6: --- apc_signal.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ apc_signal.h | 50 +++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 apc_signal.c create mode 100644 apc_signal.h diff --git a/apc_signal.c b/apc_signal.c new file mode 100644 index 0000000..406fc47 --- /dev/null +++ b/apc_signal.c @@ -0,0 +1,178 @@ +/* + +----------------------------------------------------------------------+ + | APC | + +----------------------------------------------------------------------+ + | Copyright (c) 2006 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Lucas Nealan | + +----------------------------------------------------------------------+ + + This software was contributed to PHP by Facebook Inc. in 2007. + + Future revisions and derivatives of this source code must acknowledge + Facebook Inc. as the original contributor of this module by leaving + this note intact in the source code. + + All other licensing and usage conditions are those of the PHP Group. + */ + + /* $Id: apc_signal.c,v 1.2 2007/12/26 22:38:43 rasmus Exp $ */ + + /* Allows apc to install signal handlers and maintain signalling + to already registered handlers. Registers all signals that + coredump by default and unmaps the shared memory segment + before the coredump. Note: PHP module init is called before + signals are set by Apache and thus apc_set_signals should + be called in request init (RINIT) + */ + +#include +#include "apc_globals.h" +#include "apc_sma.h" +#include "apc_signal.h" + +static apc_signal_info_t apc_signal_info = {0}; + +static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*)); +static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context); +static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context); + +/* {{{ apc_core_unmap + * Coredump signal handler, unmaps shm and calls previously installed handlers + */ +static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context) +{ + apc_sma_cleanup(); + apc_rehandle_signal(signo, siginfo, context); + +#if !defined(WIN32) && !defined(NETWARE) + kill(getpid(), signo); +#else + raise(signo); +#endif +} /* }}} */ + +/* {{{ apc_rehandle_signal + * Call the previously registered handler for a signal + */ +static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context) +{ + int i; + apc_signal_entry_t p_sig = {0}; + + for (i=0; (i < apc_signal_info.installed && p_sig.signo != signo); i++) { + p_sig = *apc_signal_info.prev[i]; + if (p_sig.signo == signo) { + if (p_sig.siginfo) { + (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context); + } else { + (*(void (*)(int))p_sig.handler)(signo); + } + } + } + +} /* }}} */ + +/* {{{ apc_register_signal + * Set a handler for a previously installed signal and save so we can + * callback when handled + */ +static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*)) +{ +#if HAVE_SIGACTION + struct sigaction sa = {0}; + apc_signal_entry_t p_sig = {0}; + + if (sigaction(signo, NULL, &sa) == 0) { + if ((void*)sa.sa_handler == (void*)handler) { + return SUCCESS; + } + + if (sa.sa_handler != SIG_ERR && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) { + p_sig.signo = signo; + p_sig.siginfo = ((sa.sa_flags & SA_SIGINFO) == SA_SIGINFO); + p_sig.handler = (void *)sa.sa_handler; + + apc_signal_info.prev = (apc_signal_entry_t **)apc_erealloc(apc_signal_info.prev, (apc_signal_info.installed+1)*sizeof(apc_signal_entry_t *)); + apc_signal_info.prev[apc_signal_info.installed] = (apc_signal_entry_t *)apc_emalloc(sizeof(apc_signal_entry_t)); + *apc_signal_info.prev[apc_signal_info.installed++] = p_sig; + } else { + /* inherit flags and mask if already set */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_flags |= SA_SIGINFO; /* we'll use a siginfo handler */ +#if defined(SA_ONESHOT) + sa.sa_flags = SA_ONESHOT; +#elif defined(SA_RESETHAND) + sa.sa_flags = SA_RESETHAND; +#endif + } + sa.sa_handler = (void*)handler; + + if (sigaction(signo, &sa, NULL) < 0) { + apc_wprint("Error installing apc signal handler for %d", signo); + } + + return SUCCESS; + } +#endif + return FAILURE; +} /* }}} */ + +/* {{{ apc_set_signals + * Install our signal handlers */ +void apc_set_signals(TSRMLS_D) +{ + if (APCG(coredump_unmap) && apc_signal_info.installed == 0) { + /* ISO C standard signals that coredump */ + apc_register_signal(SIGSEGV, apc_core_unmap); + apc_register_signal(SIGABRT, apc_core_unmap); + apc_register_signal(SIGFPE, apc_core_unmap); + apc_register_signal(SIGILL, apc_core_unmap); + /* extended signals that coredump */ +#ifdef SIGBUS + apc_register_signal(SIGBUS, apc_core_unmap); +#endif +#ifdef SIGABORT + apc_register_signal(SIGABORT, apc_core_unmap); +#endif +#ifdef SIGEMT + apc_register_signal(SIGEMT, apc_core_unmap); +#endif +#ifdef SIGIOT + apc_register_signal(SIGIOT, apc_core_unmap); +#endif +#ifdef SIGQUIT + apc_register_signal(SIGQUIT, apc_core_unmap); +#endif +#ifdef SIGSYS + apc_register_signal(SIGSYS, apc_core_unmap); +#endif +#ifdef SIGTRAP + apc_register_signal(SIGTRAP, apc_core_unmap); +#endif +#ifdef SIGXCPU + apc_register_signal(SIGXCPU, apc_core_unmap); +#endif +#ifdef SIGXFSZ + apc_register_signal(SIGXFSZ, apc_core_unmap); +#endif + } +} /* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker + * vim<600: expandtab sw=4 ts=4 sts=4 + */ diff --git a/apc_signal.h b/apc_signal.h new file mode 100644 index 0000000..6503cdd --- /dev/null +++ b/apc_signal.h @@ -0,0 +1,50 @@ +/* + +----------------------------------------------------------------------+ + | APC | + +----------------------------------------------------------------------+ + | Copyright (c) 2006 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Lucas Nealan | + +----------------------------------------------------------------------+ + + */ + +/* $Id: apc_signal.h,v 1.1 2007/12/26 22:36:06 rasmus Exp $ */ + +#ifndef APC_SIGNAL_H +#define APC_SIGNAL_H + +#include "apc.h" +#include "apc_php.h" + +typedef struct apc_signal_entry_t { + int signo; /* signal number */ + int siginfo; /* siginfo style handler calling */ + void* handler; /* signal handler */ +} apc_signal_entry_t; + +typedef struct apc_signal_info_t { + int installed; /* How many signals we've installed handles for */ + apc_signal_entry_t **prev; /* Previous signal handlers */ +} apc_signal_info_t; + +void apc_set_signals(TSRMLS_D); + +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker + * vim<600: expandtab sw=4 ts=4 sts=4 + */ -- 1.7.10.4