xref: /PHP-5.5/sapi/fpm/fpm/fpm_signals.c (revision 0549e55d)
1 
2 	/* $Id: fpm_signals.c,v 1.24 2008/08/26 15:09:15 anight Exp $ */
3 	/* (c) 2007,2008 Andrei Nigmatulin */
4 
5 #include "fpm_config.h"
6 
7 #include <signal.h>
8 #include <stdio.h>
9 #include <sys/types.h>
10 #include <sys/socket.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include <errno.h>
16 
17 #include "fpm.h"
18 #include "fpm_signals.h"
19 #include "fpm_sockets.h"
20 #include "fpm_php.h"
21 #include "zlog.h"
22 
23 static int sp[2];
24 
25 const char *fpm_signal_names[NSIG + 1] = {
26 #ifdef SIGHUP
27 	[SIGHUP] 		= "SIGHUP",
28 #endif
29 #ifdef SIGINT
30 	[SIGINT] 		= "SIGINT",
31 #endif
32 #ifdef SIGQUIT
33 	[SIGQUIT] 		= "SIGQUIT",
34 #endif
35 #ifdef SIGILL
36 	[SIGILL] 		= "SIGILL",
37 #endif
38 #ifdef SIGTRAP
39 	[SIGTRAP] 		= "SIGTRAP",
40 #endif
41 #ifdef SIGABRT
42 	[SIGABRT] 		= "SIGABRT",
43 #endif
44 #ifdef SIGEMT
45 	[SIGEMT] 		= "SIGEMT",
46 #endif
47 #ifdef SIGBUS
48 	[SIGBUS] 		= "SIGBUS",
49 #endif
50 #ifdef SIGFPE
51 	[SIGFPE] 		= "SIGFPE",
52 #endif
53 #ifdef SIGKILL
54 	[SIGKILL] 		= "SIGKILL",
55 #endif
56 #ifdef SIGUSR1
57 	[SIGUSR1] 		= "SIGUSR1",
58 #endif
59 #ifdef SIGSEGV
60 	[SIGSEGV] 		= "SIGSEGV",
61 #endif
62 #ifdef SIGUSR2
63 	[SIGUSR2] 		= "SIGUSR2",
64 #endif
65 #ifdef SIGPIPE
66 	[SIGPIPE] 		= "SIGPIPE",
67 #endif
68 #ifdef SIGALRM
69 	[SIGALRM] 		= "SIGALRM",
70 #endif
71 #ifdef SIGTERM
72 	[SIGTERM] 		= "SIGTERM",
73 #endif
74 #ifdef SIGCHLD
75 	[SIGCHLD] 		= "SIGCHLD",
76 #endif
77 #ifdef SIGCONT
78 	[SIGCONT] 		= "SIGCONT",
79 #endif
80 #ifdef SIGSTOP
81 	[SIGSTOP] 		= "SIGSTOP",
82 #endif
83 #ifdef SIGTSTP
84 	[SIGTSTP] 		= "SIGTSTP",
85 #endif
86 #ifdef SIGTTIN
87 	[SIGTTIN] 		= "SIGTTIN",
88 #endif
89 #ifdef SIGTTOU
90 	[SIGTTOU] 		= "SIGTTOU",
91 #endif
92 #ifdef SIGURG
93 	[SIGURG] 		= "SIGURG",
94 #endif
95 #ifdef SIGXCPU
96 	[SIGXCPU] 		= "SIGXCPU",
97 #endif
98 #ifdef SIGXFSZ
99 	[SIGXFSZ] 		= "SIGXFSZ",
100 #endif
101 #ifdef SIGVTALRM
102 	[SIGVTALRM] 	= "SIGVTALRM",
103 #endif
104 #ifdef SIGPROF
105 	[SIGPROF] 		= "SIGPROF",
106 #endif
107 #ifdef SIGWINCH
108 	[SIGWINCH] 		= "SIGWINCH",
109 #endif
110 #ifdef SIGINFO
111 	[SIGINFO] 		= "SIGINFO",
112 #endif
113 #ifdef SIGIO
114 	[SIGIO] 		= "SIGIO",
115 #endif
116 #ifdef SIGPWR
117 	[SIGPWR] 		= "SIGPWR",
118 #endif
119 #ifdef SIGSYS
120 	[SIGSYS] 		= "SIGSYS",
121 #endif
122 #ifdef SIGWAITING
123 	[SIGWAITING] 	= "SIGWAITING",
124 #endif
125 #ifdef SIGLWP
126 	[SIGLWP] 		= "SIGLWP",
127 #endif
128 #ifdef SIGFREEZE
129 	[SIGFREEZE] 	= "SIGFREEZE",
130 #endif
131 #ifdef SIGTHAW
132 	[SIGTHAW] 		= "SIGTHAW",
133 #endif
134 #ifdef SIGCANCEL
135 	[SIGCANCEL] 	= "SIGCANCEL",
136 #endif
137 #ifdef SIGLOST
138 	[SIGLOST] 		= "SIGLOST",
139 #endif
140 };
141 
sig_soft_quit(int signo)142 static void sig_soft_quit(int signo) /* {{{ */
143 {
144 	int saved_errno = errno;
145 
146 	/* closing fastcgi listening socket will force fcgi_accept() exit immediately */
147 	close(0);
148 	if (0 > socket(AF_UNIX, SOCK_STREAM, 0)) {
149 		zlog(ZLOG_WARNING, "failed to create a new socket");
150 	}
151 	fpm_php_soft_quit();
152 	errno = saved_errno;
153 }
154 /* }}} */
155 
sig_handler(int signo)156 static void sig_handler(int signo) /* {{{ */
157 {
158 	static const char sig_chars[NSIG + 1] = {
159 		[SIGTERM] = 'T',
160 		[SIGINT]  = 'I',
161 		[SIGUSR1] = '1',
162 		[SIGUSR2] = '2',
163 		[SIGQUIT] = 'Q',
164 		[SIGCHLD] = 'C'
165 	};
166 	char s;
167 	int saved_errno;
168 
169 	if (fpm_globals.parent_pid != getpid()) {
170 		/* prevent a signal race condition when child process
171 			have not set up it's own signal handler yet */
172 		return;
173 	}
174 
175 	saved_errno = errno;
176 	s = sig_chars[signo];
177 	write(sp[1], &s, sizeof(s));
178 	errno = saved_errno;
179 }
180 /* }}} */
181 
fpm_signals_init_main()182 int fpm_signals_init_main() /* {{{ */
183 {
184 	struct sigaction act;
185 
186 	if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) {
187 		zlog(ZLOG_SYSERROR, "failed to init signals: socketpair()");
188 		return -1;
189 	}
190 
191 	if (0 > fd_set_blocked(sp[0], 0) || 0 > fd_set_blocked(sp[1], 0)) {
192 		zlog(ZLOG_SYSERROR, "failed to init signals: fd_set_blocked()");
193 		return -1;
194 	}
195 
196 	if (0 > fcntl(sp[0], F_SETFD, FD_CLOEXEC) || 0 > fcntl(sp[1], F_SETFD, FD_CLOEXEC)) {
197 		zlog(ZLOG_SYSERROR, "falied to init signals: fcntl(F_SETFD, FD_CLOEXEC)");
198 		return -1;
199 	}
200 
201 	memset(&act, 0, sizeof(act));
202 	act.sa_handler = sig_handler;
203 	sigfillset(&act.sa_mask);
204 
205 	if (0 > sigaction(SIGTERM,  &act, 0) ||
206 	    0 > sigaction(SIGINT,   &act, 0) ||
207 	    0 > sigaction(SIGUSR1,  &act, 0) ||
208 	    0 > sigaction(SIGUSR2,  &act, 0) ||
209 	    0 > sigaction(SIGCHLD,  &act, 0) ||
210 	    0 > sigaction(SIGQUIT,  &act, 0)) {
211 
212 		zlog(ZLOG_SYSERROR, "failed to init signals: sigaction()");
213 		return -1;
214 	}
215 	return 0;
216 }
217 /* }}} */
218 
fpm_signals_init_child()219 int fpm_signals_init_child() /* {{{ */
220 {
221 	struct sigaction act, act_dfl;
222 
223 	memset(&act, 0, sizeof(act));
224 	memset(&act_dfl, 0, sizeof(act_dfl));
225 
226 	act.sa_handler = &sig_soft_quit;
227 	act.sa_flags |= SA_RESTART;
228 
229 	act_dfl.sa_handler = SIG_DFL;
230 
231 	close(sp[0]);
232 	close(sp[1]);
233 
234 	if (0 > sigaction(SIGTERM,  &act_dfl,  0) ||
235 	    0 > sigaction(SIGINT,   &act_dfl,  0) ||
236 	    0 > sigaction(SIGUSR1,  &act_dfl,  0) ||
237 	    0 > sigaction(SIGUSR2,  &act_dfl,  0) ||
238 	    0 > sigaction(SIGCHLD,  &act_dfl,  0) ||
239 	    0 > sigaction(SIGQUIT,  &act,      0)) {
240 
241 		zlog(ZLOG_SYSERROR, "failed to init child signals: sigaction()");
242 		return -1;
243 	}
244 	return 0;
245 }
246 /* }}} */
247 
fpm_signals_get_fd()248 int fpm_signals_get_fd() /* {{{ */
249 {
250 	return sp[0];
251 }
252 /* }}} */
253 
254