r6:
authorDragan Dosen <ddosen@ffzg.hr>
Fri, 4 Jan 2008 00:57:06 +0000 (00:57 +0000)
committerDragan Dosen <ddosen@ffzg.hr>
Fri, 4 Jan 2008 00:57:06 +0000 (00:57 +0000)
apc_signal.c [new file with mode: 0644]
apc_signal.h [new file with mode: 0644]

diff --git a/apc_signal.c b/apc_signal.c
new file mode 100644 (file)
index 0000000..406fc47
--- /dev/null
@@ -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 <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
+ */
diff --git a/apc_signal.h b/apc_signal.h
new file mode 100644 (file)
index 0000000..6503cdd
--- /dev/null
@@ -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 <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
+ */