Back to index

php5  5.3.10
fpm_signals.c
Go to the documentation of this file.
00001 
00002        /* $Id: fpm_signals.c,v 1.24 2008/08/26 15:09:15 anight Exp $ */
00003        /* (c) 2007,2008 Andrei Nigmatulin */
00004 
00005 #include "fpm_config.h"
00006 
00007 #include <signal.h>
00008 #include <stdio.h>
00009 #include <sys/types.h>
00010 #include <sys/socket.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013 #include <fcntl.h>
00014 #include <unistd.h>
00015 #include <errno.h>
00016 
00017 #include "fpm.h"
00018 #include "fpm_signals.h"
00019 #include "fpm_sockets.h"
00020 #include "fpm_php.h"
00021 #include "zlog.h"
00022 
00023 static int sp[2];
00024 
00025 const char *fpm_signal_names[NSIG + 1] = {
00026 #ifdef SIGHUP
00027        [SIGHUP]             = "SIGHUP",
00028 #endif
00029 #ifdef SIGINT
00030        [SIGINT]             = "SIGINT",
00031 #endif
00032 #ifdef SIGQUIT
00033        [SIGQUIT]            = "SIGQUIT",
00034 #endif
00035 #ifdef SIGILL
00036        [SIGILL]             = "SIGILL",
00037 #endif
00038 #ifdef SIGTRAP
00039        [SIGTRAP]            = "SIGTRAP",
00040 #endif
00041 #ifdef SIGABRT
00042        [SIGABRT]            = "SIGABRT",
00043 #endif
00044 #ifdef SIGEMT
00045        [SIGEMT]             = "SIGEMT",
00046 #endif
00047 #ifdef SIGBUS
00048        [SIGBUS]             = "SIGBUS",
00049 #endif
00050 #ifdef SIGFPE
00051        [SIGFPE]             = "SIGFPE",
00052 #endif
00053 #ifdef SIGKILL
00054        [SIGKILL]            = "SIGKILL",
00055 #endif
00056 #ifdef SIGUSR1
00057        [SIGUSR1]            = "SIGUSR1",
00058 #endif
00059 #ifdef SIGSEGV
00060        [SIGSEGV]            = "SIGSEGV",
00061 #endif
00062 #ifdef SIGUSR2
00063        [SIGUSR2]            = "SIGUSR2",
00064 #endif
00065 #ifdef SIGPIPE
00066        [SIGPIPE]            = "SIGPIPE",
00067 #endif
00068 #ifdef SIGALRM
00069        [SIGALRM]            = "SIGALRM",
00070 #endif
00071 #ifdef SIGTERM
00072        [SIGTERM]            = "SIGTERM",
00073 #endif
00074 #ifdef SIGCHLD
00075        [SIGCHLD]            = "SIGCHLD",
00076 #endif
00077 #ifdef SIGCONT
00078        [SIGCONT]            = "SIGCONT",
00079 #endif
00080 #ifdef SIGSTOP
00081        [SIGSTOP]            = "SIGSTOP",
00082 #endif
00083 #ifdef SIGTSTP
00084        [SIGTSTP]            = "SIGTSTP",
00085 #endif
00086 #ifdef SIGTTIN
00087        [SIGTTIN]            = "SIGTTIN",
00088 #endif
00089 #ifdef SIGTTOU
00090        [SIGTTOU]            = "SIGTTOU",
00091 #endif
00092 #ifdef SIGURG
00093        [SIGURG]             = "SIGURG",
00094 #endif
00095 #ifdef SIGXCPU
00096        [SIGXCPU]            = "SIGXCPU",
00097 #endif
00098 #ifdef SIGXFSZ
00099        [SIGXFSZ]            = "SIGXFSZ",
00100 #endif
00101 #ifdef SIGVTALRM
00102        [SIGVTALRM]   = "SIGVTALRM",
00103 #endif
00104 #ifdef SIGPROF
00105        [SIGPROF]            = "SIGPROF",
00106 #endif
00107 #ifdef SIGWINCH
00108        [SIGWINCH]           = "SIGWINCH",
00109 #endif
00110 #ifdef SIGINFO
00111        [SIGINFO]            = "SIGINFO",
00112 #endif
00113 #ifdef SIGIO
00114        [SIGIO]              = "SIGIO",
00115 #endif
00116 #ifdef SIGPWR
00117        [SIGPWR]             = "SIGPWR",
00118 #endif
00119 #ifdef SIGSYS
00120        [SIGSYS]             = "SIGSYS",
00121 #endif
00122 #ifdef SIGWAITING
00123        [SIGWAITING]  = "SIGWAITING",
00124 #endif
00125 #ifdef SIGLWP
00126        [SIGLWP]             = "SIGLWP",
00127 #endif
00128 #ifdef SIGFREEZE
00129        [SIGFREEZE]   = "SIGFREEZE",
00130 #endif
00131 #ifdef SIGTHAW
00132        [SIGTHAW]            = "SIGTHAW",
00133 #endif
00134 #ifdef SIGCANCEL
00135        [SIGCANCEL]   = "SIGCANCEL",
00136 #endif
00137 #ifdef SIGLOST
00138        [SIGLOST]            = "SIGLOST",
00139 #endif
00140 };
00141 
00142 static void sig_soft_quit(int signo) /* {{{ */
00143 {
00144        int saved_errno = errno;
00145 
00146        /* closing fastcgi listening socket will force fcgi_accept() exit immediately */
00147        close(0);
00148        socket(AF_UNIX, SOCK_STREAM, 0);
00149        fpm_php_soft_quit();
00150        errno = saved_errno;
00151 }
00152 /* }}} */
00153 
00154 static void sig_handler(int signo) /* {{{ */
00155 {
00156        static const char sig_chars[NSIG + 1] = {
00157               [SIGTERM] = 'T',
00158               [SIGINT]  = 'I',
00159               [SIGUSR1] = '1',
00160               [SIGUSR2] = '2',
00161               [SIGQUIT] = 'Q',
00162               [SIGCHLD] = 'C'
00163        };
00164        char s;
00165        int saved_errno;
00166 
00167        if (fpm_globals.parent_pid != getpid()) {
00168               /* prevent a signal race condition when child process
00169                      have not set up it's own signal handler yet */
00170               return;
00171        }
00172 
00173        saved_errno = errno;
00174        s = sig_chars[signo];
00175        write(sp[1], &s, sizeof(s));
00176        errno = saved_errno;
00177 }
00178 /* }}} */
00179 
00180 int fpm_signals_init_main() /* {{{ */
00181 {
00182        struct sigaction act;
00183 
00184        if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) {
00185               zlog(ZLOG_SYSERROR, "failed to init signals: socketpair()");
00186               return -1;
00187        }
00188 
00189        if (0 > fd_set_blocked(sp[0], 0) || 0 > fd_set_blocked(sp[1], 0)) {
00190               zlog(ZLOG_SYSERROR, "failed to init signals: fd_set_blocked()");
00191               return -1;
00192        }
00193 
00194        if (0 > fcntl(sp[0], F_SETFD, FD_CLOEXEC) || 0 > fcntl(sp[1], F_SETFD, FD_CLOEXEC)) {
00195               zlog(ZLOG_SYSERROR, "falied to init signals: fcntl(F_SETFD, FD_CLOEXEC)");
00196               return -1;
00197        }
00198 
00199        memset(&act, 0, sizeof(act));
00200        act.sa_handler = sig_handler;
00201        sigfillset(&act.sa_mask);
00202 
00203        if (0 > sigaction(SIGTERM,  &act, 0) ||
00204            0 > sigaction(SIGINT,   &act, 0) ||
00205            0 > sigaction(SIGUSR1,  &act, 0) ||
00206            0 > sigaction(SIGUSR2,  &act, 0) ||
00207            0 > sigaction(SIGCHLD,  &act, 0) ||
00208            0 > sigaction(SIGQUIT,  &act, 0)) {
00209 
00210               zlog(ZLOG_SYSERROR, "failed to init signals: sigaction()");
00211               return -1;
00212        }
00213        return 0;
00214 }
00215 /* }}} */
00216 
00217 int fpm_signals_init_child() /* {{{ */
00218 {
00219        struct sigaction act, act_dfl;
00220 
00221        memset(&act, 0, sizeof(act));
00222        memset(&act_dfl, 0, sizeof(act_dfl));
00223 
00224        act.sa_handler = &sig_soft_quit;
00225        act.sa_flags |= SA_RESTART;
00226 
00227        act_dfl.sa_handler = SIG_DFL;
00228 
00229        close(sp[0]);
00230        close(sp[1]);
00231 
00232        if (0 > sigaction(SIGTERM,  &act_dfl,  0) ||
00233            0 > sigaction(SIGINT,   &act_dfl,  0) ||
00234            0 > sigaction(SIGUSR1,  &act_dfl,  0) ||
00235            0 > sigaction(SIGUSR2,  &act_dfl,  0) ||
00236            0 > sigaction(SIGCHLD,  &act_dfl,  0) ||
00237            0 > sigaction(SIGQUIT,  &act,      0)) {
00238 
00239               zlog(ZLOG_SYSERROR, "failed to init child signals: sigaction()");
00240               return -1;
00241        }
00242        return 0;
00243 }
00244 /* }}} */
00245 
00246 int fpm_signals_get_fd() /* {{{ */
00247 {
00248        return sp[0];
00249 }
00250 /* }}} */
00251