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