--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | 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 <lucas@php.net> |
+ +----------------------------------------------------------------------+
+
+ 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 <signal.h>
+#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
+ */
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | 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 <lucas@php.net> |
+ +----------------------------------------------------------------------+
+
+ */
+
+/* $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
+ */