2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Lucas Nealan <lucas@php.net> |
16 +----------------------------------------------------------------------+
18 This software was contributed to PHP by Facebook Inc. in 2007.
20 Future revisions and derivatives of this source code must acknowledge
21 Facebook Inc. as the original contributor of this module by leaving
22 this note intact in the source code.
24 All other licensing and usage conditions are those of the PHP Group.
27 /* $Id: apc_signal.c,v 1.2 2007/12/26 22:38:43 rasmus Exp $ */
29 /* Allows apc to install signal handlers and maintain signalling
30 to already registered handlers. Registers all signals that
31 coredump by default and unmaps the shared memory segment
32 before the coredump. Note: PHP module init is called before
33 signals are set by Apache and thus apc_set_signals should
34 be called in request init (RINIT)
38 #include "apc_globals.h"
40 #include "apc_signal.h"
42 static apc_signal_info_t apc_signal_info = {0};
44 static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*));
45 static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context);
46 static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context);
49 * Coredump signal handler, unmaps shm and calls previously installed handlers
51 static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context)
54 apc_rehandle_signal(signo, siginfo, context);
56 #if !defined(WIN32) && !defined(NETWARE)
57 kill(getpid(), signo);
63 /* {{{ apc_rehandle_signal
64 * Call the previously registered handler for a signal
66 static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context)
69 apc_signal_entry_t p_sig = {0};
71 for (i=0; (i < apc_signal_info.installed && p_sig.signo != signo); i++) {
72 p_sig = *apc_signal_info.prev[i];
73 if (p_sig.signo == signo) {
75 (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context);
77 (*(void (*)(int))p_sig.handler)(signo);
84 /* {{{ apc_register_signal
85 * Set a handler for a previously installed signal and save so we can
86 * callback when handled
88 static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*))
91 struct sigaction sa = {0};
92 apc_signal_entry_t p_sig = {0};
94 if (sigaction(signo, NULL, &sa) == 0) {
95 if ((void*)sa.sa_handler == (void*)handler) {
99 if (sa.sa_handler != SIG_ERR && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) {
101 p_sig.siginfo = ((sa.sa_flags & SA_SIGINFO) == SA_SIGINFO);
102 p_sig.handler = (void *)sa.sa_handler;
104 apc_signal_info.prev = (apc_signal_entry_t **)apc_erealloc(apc_signal_info.prev, (apc_signal_info.installed+1)*sizeof(apc_signal_entry_t *));
105 apc_signal_info.prev[apc_signal_info.installed] = (apc_signal_entry_t *)apc_emalloc(sizeof(apc_signal_entry_t));
106 *apc_signal_info.prev[apc_signal_info.installed++] = p_sig;
108 /* inherit flags and mask if already set */
109 sigemptyset(&sa.sa_mask);
111 sa.sa_flags |= SA_SIGINFO; /* we'll use a siginfo handler */
112 #if defined(SA_ONESHOT)
113 sa.sa_flags = SA_ONESHOT;
114 #elif defined(SA_RESETHAND)
115 sa.sa_flags = SA_RESETHAND;
118 sa.sa_handler = (void*)handler;
120 if (sigaction(signo, &sa, NULL) < 0) {
121 apc_wprint("Error installing apc signal handler for %d", signo);
130 /* {{{ apc_set_signals
131 * Install our signal handlers */
132 void apc_set_signals(TSRMLS_D)
134 if (APCG(coredump_unmap) && apc_signal_info.installed == 0) {
135 /* ISO C standard signals that coredump */
136 apc_register_signal(SIGSEGV, apc_core_unmap);
137 apc_register_signal(SIGABRT, apc_core_unmap);
138 apc_register_signal(SIGFPE, apc_core_unmap);
139 apc_register_signal(SIGILL, apc_core_unmap);
140 /* extended signals that coredump */
142 apc_register_signal(SIGBUS, apc_core_unmap);
145 apc_register_signal(SIGABORT, apc_core_unmap);
148 apc_register_signal(SIGEMT, apc_core_unmap);
151 apc_register_signal(SIGIOT, apc_core_unmap);
154 apc_register_signal(SIGQUIT, apc_core_unmap);
157 apc_register_signal(SIGSYS, apc_core_unmap);
160 apc_register_signal(SIGTRAP, apc_core_unmap);
163 apc_register_signal(SIGXCPU, apc_core_unmap);
166 apc_register_signal(SIGXFSZ, apc_core_unmap);
176 * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
177 * vim<600: expandtab sw=4 ts=4 sts=4