]>
Commit | Line | Data |
---|---|---|
08e9ce79 ER |
1 | diff -Naur php-src-vanilla/sapi/fpm/ac/fpm_build.m4 php-src/sapi/fpm/ac/fpm_build.m4 |
2 | --- php-src-vanilla/sapi/fpm/ac/fpm_build.m4 1970-01-01 01:00:00.000000000 +0100 | |
3 | +++ php-src/sapi/fpm/ac/fpm_build.m4 2009-10-18 21:05:39.310440424 +0100 | |
4 | @@ -0,0 +1,47 @@ | |
5 | + | |
6 | +AC_DEFUN([AC_FPM_BUILD_SAPI], | |
7 | +[ | |
8 | + PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/fpm/ac/Makefile.frag,$abs_srcdir/sapi/fpm,sapi/fpm) | |
9 | + | |
10 | + SAPI_FPM_PATH=sapi/fpm/$php_fpm_bin | |
11 | + PHP_SUBST(SAPI_FPM_PATH) | |
12 | + | |
13 | + mkdir -p sapi/fpm/cgi | |
14 | + PHP_FPM_SAPI_FILES=`cd $abs_srcdir/sapi/fpm && find cgi/ \( -name *.c \) -exec printf "{} " \;` | |
15 | + # PHP_FPM_SAPI_FILES="cgi/cgi_main.c cgi/fastcgi.c" | |
16 | + | |
17 | + mkdir -p sapi/fpm/fpm | |
18 | + PHP_FPM_CORE_FILES=`cd $abs_srcdir/sapi/fpm && find fpm/ \( -name *.c -not -name fpm_trace*.c \) -exec printf "{} " \;` | |
19 | + # PHP_FPM_CORE_FILES="fpm/fpm_process_ctl.c fpm/fpm_signals.c fpm/fpm_shm.c fpm/fpm.c fpm/fpm_worker_pool.c fpm/fpm_clock.c fpm/fpm_env.c fpm/fpm_shm_slots.c fpm/fpm_children.c fpm/fpm_events.c fpm/fpm_php.c fpm/fpm_unix.c fpm/fpm_request.c fpm/fpm_sockets.c fpm/fpm_php_trace.c fpm/zlog.c fpm/fpm_cleanup.c fpm/fpm_conf.c fpm/xml_config.c fpm/fpm_stdio.c" | |
20 | + | |
21 | + if test "$fpm_trace_type" ; then | |
22 | + PHP_FPM_TRACE_FILES=`cd $abs_srcdir/sapi/fpm && find fpm/ \( -name fpm_trace.c -or -name fpm_trace_$fpm_trace_type.c \) -exec printf "{} " \;` | |
23 | + fi | |
24 | + | |
25 | + PHP_FPM_CFLAGS="$LIBEVENT_CFLAGS -I$abs_srcdir/sapi/fpm" | |
26 | + | |
27 | + SAPI_EXTRA_LIBS="$LIBEVENT_LIBS" | |
28 | + PHP_SUBST(SAPI_EXTRA_LIBS) | |
29 | + | |
30 | + dnl Set install target and select SAPI | |
31 | + INSTALL_IT=":" | |
32 | + | |
33 | + PHP_SELECT_SAPI(fpm, program, $PHP_FPM_SAPI_FILES $PHP_FPM_CORE_FILES $PHP_FPM_TRACE_FILES, $PHP_FPM_CFLAGS, '$(SAPI_FPM_PATH)') | |
34 | + | |
35 | + case $host_alias in | |
36 | + *aix*) | |
37 | + BUILD_FPM="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" | |
38 | + ;; | |
39 | + *darwin*) | |
40 | + BUILD_FPM="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_SAPI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" | |
41 | + ;; | |
42 | + *) | |
43 | + BUILD_FPM="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)" | |
44 | + ;; | |
45 | + esac | |
46 | + | |
47 | + ENDIF=endif | |
48 | + PHP_SUBST(ENDIF) | |
49 | + PHP_SUBST(BUILD_FPM) | |
50 | + | |
51 | +]) | |
52 | diff -Naur php-src-vanilla/sapi/fpm/ac/fpm_checks.m4 php-src/sapi/fpm/ac/fpm_checks.m4 | |
53 | --- php-src-vanilla/sapi/fpm/ac/fpm_checks.m4 1970-01-01 01:00:00.000000000 +0100 | |
54 | +++ php-src/sapi/fpm/ac/fpm_checks.m4 2009-10-18 21:05:39.310440424 +0100 | |
55 | @@ -0,0 +1,299 @@ | |
56 | +dnl | |
57 | +dnl $Id$ | |
58 | +dnl | |
59 | + | |
60 | +AC_DEFUN([AC_FPM_CHECKS], | |
61 | +[ | |
62 | + AC_FPM_STDLIBS | |
63 | + AC_FPM_PRCTL | |
64 | + AC_FPM_CLOCK | |
65 | + AC_FPM_TRACE | |
66 | +]) | |
67 | + | |
68 | +AC_DEFUN([AC_FPM_STDLIBS], | |
69 | +[ | |
70 | + AC_CHECK_FUNCS(setenv clearenv) | |
71 | + | |
72 | + AC_SEARCH_LIBS(socket, socket) | |
73 | + AC_SEARCH_LIBS(inet_addr, nsl) | |
74 | + | |
75 | + AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h]) | |
76 | + AC_CHECK_HEADERS([sys/select.h sys/socket.h sys/time.h]) | |
77 | + AC_CHECK_HEADERS([arpa/inet.h netinet/in.h]) | |
78 | +]) | |
79 | + | |
80 | +AC_DEFUN([AC_FPM_PRCTL], | |
81 | +[ | |
82 | + AC_MSG_CHECKING([for prctl]) | |
83 | + | |
84 | + AC_TRY_COMPILE([ #include <sys/prctl.h> ], [prctl(0, 0, 0, 0, 0);], [ | |
85 | + AC_DEFINE([HAVE_PRCTL], 1, [do we have prctl?]) | |
86 | + AC_MSG_RESULT([yes]) | |
87 | + ], [ | |
88 | + AC_MSG_RESULT([no]) | |
89 | + ]) | |
90 | +]) | |
91 | + | |
92 | +AC_DEFUN([AC_FPM_CLOCK], | |
93 | +[ | |
94 | + have_clock_gettime=no | |
95 | + | |
96 | + AC_MSG_CHECKING([for clock_gettime]) | |
97 | + | |
98 | + AC_TRY_LINK([ #include <time.h> ], [struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);], [ | |
99 | + have_clock_gettime=yes | |
100 | + AC_MSG_RESULT([yes]) | |
101 | + ], [ | |
102 | + AC_MSG_RESULT([no]) | |
103 | + ]) | |
104 | + | |
105 | + if test "$have_clock_gettime" = "no"; then | |
106 | + AC_MSG_CHECKING([for clock_gettime in -lrt]) | |
107 | + | |
108 | + SAVED_LIBS="$LIBS" | |
109 | + LIBS="$LIBS -lrt" | |
110 | + | |
111 | + AC_TRY_LINK([ #include <time.h> ], [struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);], [ | |
112 | + have_clock_gettime=yes | |
113 | + AC_MSG_RESULT([yes]) | |
114 | + ], [ | |
115 | + LIBS="$SAVED_LIBS" | |
116 | + AC_MSG_RESULT([no]) | |
117 | + ]) | |
118 | + fi | |
119 | + | |
120 | + if test "$have_clock_gettime" = "yes"; then | |
121 | + AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [do we have clock_gettime?]) | |
122 | + fi | |
123 | + | |
124 | + have_clock_get_time=no | |
125 | + | |
126 | + if test "$have_clock_gettime" = "no"; then | |
127 | + AC_MSG_CHECKING([for clock_get_time]) | |
128 | + | |
129 | + AC_TRY_RUN([ #include <mach/mach.h> | |
130 | + #include <mach/clock.h> | |
131 | + #include <mach/mach_error.h> | |
132 | + | |
133 | + int main() | |
134 | + { | |
135 | + kern_return_t ret; clock_serv_t aClock; mach_timespec_t aTime; | |
136 | + ret = host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &aClock); | |
137 | + | |
138 | + if (ret != KERN_SUCCESS) { | |
139 | + return 1; | |
140 | + } | |
141 | + | |
142 | + ret = clock_get_time(aClock, &aTime); | |
143 | + if (ret != KERN_SUCCESS) { | |
144 | + return 2; | |
145 | + } | |
146 | + | |
147 | + return 0; | |
148 | + } | |
149 | + ], [ | |
150 | + have_clock_get_time=yes | |
151 | + AC_MSG_RESULT([yes]) | |
152 | + ], [ | |
153 | + AC_MSG_RESULT([no]) | |
154 | + ]) | |
155 | + fi | |
156 | + | |
157 | + if test "$have_clock_get_time" = "yes"; then | |
158 | + AC_DEFINE([HAVE_CLOCK_GET_TIME], 1, [do we have clock_get_time?]) | |
159 | + fi | |
160 | +]) | |
161 | + | |
162 | +AC_DEFUN([AC_FPM_TRACE], | |
163 | +[ | |
164 | + have_ptrace=no | |
165 | + have_broken_ptrace=no | |
166 | + | |
167 | + AC_MSG_CHECKING([for ptrace]) | |
168 | + | |
169 | + AC_TRY_COMPILE([ | |
170 | + #include <sys/types.h> | |
171 | + #include <sys/ptrace.h> ], [ptrace(0, 0, (void *) 0, 0);], [ | |
172 | + have_ptrace=yes | |
173 | + AC_MSG_RESULT([yes]) | |
174 | + ], [ | |
175 | + AC_MSG_RESULT([no]) | |
176 | + ]) | |
177 | + | |
178 | + if test "$have_ptrace" = "yes"; then | |
179 | + AC_MSG_CHECKING([whether ptrace works]) | |
180 | + | |
181 | + AC_TRY_RUN([ | |
182 | + #include <unistd.h> | |
183 | + #include <signal.h> | |
184 | + #include <sys/wait.h> | |
185 | + #include <sys/types.h> | |
186 | + #include <sys/ptrace.h> | |
187 | + #include <errno.h> | |
188 | + | |
189 | + #if !defined(PTRACE_ATTACH) && defined(PT_ATTACH) | |
190 | + #define PTRACE_ATTACH PT_ATTACH | |
191 | + #endif | |
192 | + | |
193 | + #if !defined(PTRACE_DETACH) && defined(PT_DETACH) | |
194 | + #define PTRACE_DETACH PT_DETACH | |
195 | + #endif | |
196 | + | |
197 | + #if !defined(PTRACE_PEEKDATA) && defined(PT_READ_D) | |
198 | + #define PTRACE_PEEKDATA PT_READ_D | |
199 | + #endif | |
200 | + | |
201 | + int main() | |
202 | + { | |
203 | + long v1 = (unsigned int) -1; /* copy will fail if sizeof(long) == 8 and we've got "int ptrace()" */ | |
204 | + long v2; | |
205 | + pid_t child; | |
206 | + int status; | |
207 | + | |
208 | + if ( (child = fork()) ) { /* parent */ | |
209 | + int ret = 0; | |
210 | + | |
211 | + if (0 > ptrace(PTRACE_ATTACH, child, 0, 0)) { | |
212 | + return 1; | |
213 | + } | |
214 | + | |
215 | + waitpid(child, &status, 0); | |
216 | + | |
217 | + #ifdef PT_IO | |
218 | + struct ptrace_io_desc ptio = { | |
219 | + .piod_op = PIOD_READ_D, | |
220 | + .piod_offs = &v1, | |
221 | + .piod_addr = &v2, | |
222 | + .piod_len = sizeof(v1) | |
223 | + }; | |
224 | + | |
225 | + if (0 > ptrace(PT_IO, child, (void *) &ptio, 0)) { | |
226 | + ret = 1; | |
227 | + } | |
228 | + #else | |
229 | + errno = 0; | |
230 | + | |
231 | + v2 = ptrace(PTRACE_PEEKDATA, child, (void *) &v1, 0); | |
232 | + | |
233 | + if (errno) { | |
234 | + ret = 1; | |
235 | + } | |
236 | + #endif | |
237 | + ptrace(PTRACE_DETACH, child, (void *) 1, 0); | |
238 | + | |
239 | + kill(child, SIGKILL); | |
240 | + | |
241 | + return ret ? ret : (v1 != v2); | |
242 | + } | |
243 | + else { /* child */ | |
244 | + sleep(10); | |
245 | + return 0; | |
246 | + } | |
247 | + } | |
248 | + ], [ | |
249 | + AC_MSG_RESULT([yes]) | |
250 | + ], [ | |
251 | + have_ptrace=no | |
252 | + have_broken_ptrace=yes | |
253 | + AC_MSG_RESULT([no]) | |
254 | + ]) | |
255 | + fi | |
256 | + | |
257 | + if test "$have_ptrace" = "yes"; then | |
258 | + AC_DEFINE([HAVE_PTRACE], 1, [do we have ptrace?]) | |
259 | + fi | |
260 | + | |
261 | + have_mach_vm_read=no | |
262 | + | |
263 | + if test "$have_broken_ptrace" = "yes"; then | |
264 | + AC_MSG_CHECKING([for mach_vm_read]) | |
265 | + | |
266 | + AC_TRY_COMPILE([ #include <mach/mach.h> | |
267 | + #include <mach/mach_vm.h> | |
268 | + ], [ | |
269 | + mach_vm_read((vm_map_t)0, (mach_vm_address_t)0, (mach_vm_size_t)0, (vm_offset_t *)0, (mach_msg_type_number_t*)0); | |
270 | + ], [ | |
271 | + have_mach_vm_read=yes | |
272 | + AC_MSG_RESULT([yes]) | |
273 | + ], [ | |
274 | + AC_MSG_RESULT([no]) | |
275 | + ]) | |
276 | + fi | |
277 | + | |
278 | + if test "$have_mach_vm_read" = "yes"; then | |
279 | + AC_DEFINE([HAVE_MACH_VM_READ], 1, [do we have mach_vm_read?]) | |
280 | + fi | |
281 | + | |
282 | + proc_mem_file="" | |
283 | + | |
284 | + if test -r /proc/$$/mem ; then | |
285 | + proc_mem_file="mem" | |
286 | + else | |
287 | + if test -r /proc/$$/as ; then | |
288 | + proc_mem_file="as" | |
289 | + fi | |
290 | + fi | |
291 | + | |
292 | + if test -n "$proc_mem_file" ; then | |
293 | + AC_MSG_CHECKING([for proc mem file]) | |
294 | + | |
295 | + AC_TRY_RUN([ | |
296 | + #define _GNU_SOURCE | |
297 | + #define _FILE_OFFSET_BITS 64 | |
298 | + #if HAVE_INTTYPES_H | |
299 | + #include <inttypes.h> | |
300 | + #else | |
301 | + #include <stdint.h> | |
302 | + #endif | |
303 | + | |
304 | + #include <unistd.h> | |
305 | + #include <sys/types.h> | |
306 | + #include <sys/stat.h> | |
307 | + #include <fcntl.h> | |
308 | + #include <stdio.h> | |
309 | + int main() | |
310 | + { | |
311 | + long v1 = (unsigned int) -1, v2 = 0; | |
312 | + char buf[128]; | |
313 | + int fd; | |
314 | + sprintf(buf, "/proc/%d/$proc_mem_file", getpid()); | |
315 | + fd = open(buf, O_RDONLY); | |
316 | + if (0 > fd) { | |
317 | + return 1; | |
318 | + } | |
319 | + if (sizeof(long) != pread(fd, &v2, sizeof(long), (uintptr_t) &v1)) { | |
320 | + close(fd); | |
321 | + return 1; | |
322 | + } | |
323 | + close(fd); | |
324 | + return v1 != v2; | |
325 | + } | |
326 | + ], [ | |
327 | + AC_MSG_RESULT([$proc_mem_file]) | |
328 | + ], [ | |
329 | + proc_mem_file="" | |
330 | + AC_MSG_RESULT([no]) | |
331 | + ]) | |
332 | + fi | |
333 | + | |
334 | + if test -n "$proc_mem_file"; then | |
335 | + AC_DEFINE_UNQUOTED([PROC_MEM_FILE], "$proc_mem_file", [/proc/pid/mem interface]) | |
336 | + fi | |
337 | + | |
338 | + fpm_trace_type="" | |
339 | + | |
340 | + if test "$have_ptrace" = "yes"; then | |
341 | + fpm_trace_type=ptrace | |
342 | + | |
343 | + elif test -n "$proc_mem_file"; then | |
344 | + fpm_trace_type=pread | |
345 | + | |
346 | + elif test "$have_mach_vm_read" = "yes" ; then | |
347 | + fpm_trace_type=mach | |
348 | + | |
349 | + else | |
350 | + AC_MSG_ERROR([FPM Trace - ptrace, pread, or mach: could not be found]) | |
351 | + fi | |
352 | + | |
353 | +]) | |
354 | + | |
355 | diff -Naur php-src-vanilla/sapi/fpm/ac/fpm_conf.m4 php-src/sapi/fpm/ac/fpm_conf.m4 | |
356 | --- php-src-vanilla/sapi/fpm/ac/fpm_conf.m4 1970-01-01 01:00:00.000000000 +0100 | |
357 | +++ php-src/sapi/fpm/ac/fpm_conf.m4 2009-10-18 21:05:39.310440424 +0100 | |
358 | @@ -0,0 +1,188 @@ | |
359 | + | |
360 | +AC_DEFUN([AC_FPM_ARGS], | |
361 | +[ | |
362 | + PHP_ARG_WITH(fpm-bin,, | |
363 | + [ --with-fpm-bin[=PATH] Set the path for the php-fpm binary [/usr/local/bin/php-fpm]], yes, no) | |
364 | + | |
365 | + PHP_ARG_WITH(fpm-port,, | |
366 | + [ --with-fpm-port[=PORT] Set the tcp port number to listen for cgi requests [9000]], yes, no) | |
367 | + | |
368 | + PHP_ARG_WITH(fpm-conf,, | |
369 | + [ --with-fpm-conf[=PATH] Set the path for php-fpm configuration file [/etc/php-fpm.conf]], yes, no) | |
370 | + | |
371 | + PHP_ARG_WITH(fpm-init,, | |
372 | + [ --with-fpm-init[=PATH] Set the path for php-fpm init file [/etc/init.d/php-fpm]], yes, no) | |
373 | + | |
374 | + PHP_ARG_WITH(fpm-log,, | |
375 | + [ --with-fpm-log[=PATH] Set the path for php-fpm log file [/var/log/php-fpm.log]], yes, no) | |
376 | + | |
377 | + PHP_ARG_WITH(fpm-pid,, | |
378 | + [ --with-fpm-pid[=PATH] Set the path for php-fpm pid file [/var/run/php-fpm.pid]], yes, no) | |
379 | + | |
380 | + PHP_ARG_WITH(fpm-user,, | |
381 | + [ --with-fpm-user[=USER] Set the user for php-fpm to run as [nobody]], yes, no) | |
382 | + | |
383 | + PHP_ARG_WITH(fpm-group,, | |
384 | + [ --with-fpm-group[=GRP] Set the group for php-fpm to run as. For a system user, | |
385 | + this should be set to match the fpm username [nobody]], yes, no) | |
386 | +]) | |
387 | + | |
388 | +AC_DEFUN([AC_FPM_VARS], | |
389 | +[ | |
390 | + fpm_prefix=$ac_default_prefix | |
391 | + if test $prefix != "NONE" -a $prefix != "" -a $prefix != "no" ; then | |
392 | + fpm_prefix=$prefix | |
393 | + else | |
394 | + prefix=$fpm_prefix | |
395 | + fi | |
396 | + | |
397 | + if test $exec_prefix = "NONE" -o $exec_prefix = "" -o $exec_prefix = "no" ; then | |
398 | + exec_prefix=$fpm_prefix | |
399 | + fi | |
400 | + | |
401 | + if test `echo "$bindir" | grep "exec_prefix"` ; then | |
402 | + bindir=$exec_prefix/bin | |
403 | + fi | |
404 | + | |
405 | + fpm_bin_prefix=$fpm_prefix/bin | |
406 | + if test $bindir != "NONE" -a $bindir != "" -a $bindir != "no" ; then | |
407 | + fpm_bin_prefix=$bindir | |
408 | + fi | |
409 | + | |
410 | + if test -z "$PHP_FPM_BIN" -o "$PHP_FPM_BIN" = "yes" -o "$PHP_FPM_BIN" = "no"; then | |
411 | + php_fpm_bin_path="$fpm_bin_prefix/php-fpm" | |
412 | + else | |
413 | + php_fpm_bin_path="$PHP_FPM_BIN" | |
414 | + fi | |
415 | + php_fpm_bin=`basename $php_fpm_bin_path` | |
416 | + php_fpm_bin_dir=`dirname $php_fpm_bin_path` | |
417 | + | |
418 | + if test -z "$PHP_FPM_PORT" -o "$PHP_FPM_PORT" = "yes" -o "$PHP_FPM_PORT" = "no"; then | |
419 | + php_fpm_port="9000" | |
420 | + else | |
421 | + php_fpm_port="$PHP_FPM_PORT" | |
422 | + fi | |
423 | + | |
424 | + if test -z "$PHP_FPM_CONF" -o "$PHP_FPM_CONF" = "yes"; then | |
425 | + case $host_os in | |
426 | + freebsd*|dragonfly*) php_fpm_conf_path="/usr/local/etc/php-fpm.conf" ;; | |
427 | + *) php_fpm_conf_path="/etc/php-fpm.conf" ;; | |
428 | + esac | |
429 | + elif test "$PHP_FPM_CONF" = "no"; then | |
430 | + php_fpm_conf_path="" | |
431 | + else | |
432 | + php_fpm_conf_path="$PHP_FPM_CONF" | |
433 | + fi | |
434 | + if test -z "$php_fpm_conf_path"; then | |
435 | + php_fpm_conf="" | |
436 | + php_fpm_conf_dir="" | |
437 | + else | |
438 | + php_fpm_conf=`basename $php_fpm_conf_path` | |
439 | + php_fpm_conf_dir=`dirname $php_fpm_conf_path` | |
440 | + fi | |
441 | + | |
442 | + if test -z "$PHP_FPM_INIT" -o "$PHP_FPM_INIT" = "yes"; then | |
443 | + case $host_os in | |
444 | + openbsd*) php_fpm_init_path="" ;; | |
445 | + netbsd*) php_fpm_init_path="/etc/rc.d/php-fpm" ;; | |
446 | + *bsd*|dragonfly*) php_fpm_init_path="/usr/local/etc/rc.d/php-fpm" ;; | |
447 | + *) php_fpm_init_path="/etc/init.d/php-fpm" ;; | |
448 | + esac | |
449 | + test -f /etc/arch-release && php_fpm_init_path="/etc/rc.d/php-fpm" # arch linux | |
450 | + | |
451 | + elif test "$PHP_FPM_INIT" = "no"; then | |
452 | + php_fpm_init_path="" | |
453 | + else | |
454 | + php_fpm_init_path="$PHP_FPM_INIT" | |
455 | + fi | |
456 | + if test -z "$php_fpm_init_path"; then | |
457 | + php_fpm_init="" | |
458 | + php_fpm_init_dir="" | |
459 | + else | |
460 | + php_fpm_init=`basename $php_fpm_init_path` | |
461 | + php_fpm_init_dir=`dirname $php_fpm_init_path` | |
462 | + fi | |
463 | + | |
464 | + if test -z "$PHP_FPM_LOG" -o "$PHP_FPM_LOG" = "yes" -o "$PHP_FPM_LOG" = "no"; then | |
465 | + php_fpm_log_path="/var/log/php-fpm.log" | |
466 | + else | |
467 | + php_fpm_log_path="$PHP_FPM_LOG" | |
468 | + fi | |
469 | + php_fpm_log_dir=`dirname $php_fpm_log_path` | |
470 | + | |
471 | + if test -z "$PHP_FPM_PID" -o "$PHP_FPM_PID" = "yes" -o "$PHP_FPM_PID" = "no"; then | |
472 | + php_fpm_pid_path="/var/run/php-fpm.pid" | |
473 | + else | |
474 | + php_fpm_pid_path="$PHP_FPM_PID" | |
475 | + fi | |
476 | + php_fpm_pid_dir=`dirname $php_fpm_pid_path` | |
477 | + | |
478 | + if test -z "$PHP_FPM_USER" -o "$PHP_FPM_USER" = "yes" -o "$PHP_FPM_USER" = "no"; then | |
479 | + php_fpm_user="nobody" | |
480 | + else | |
481 | + php_fpm_user="$PHP_FPM_USER" | |
482 | + fi | |
483 | + | |
484 | + if test -z "$PHP_FPM_GROUP" -o "$PHP_FPM_GROUP" = "yes" -o "$PHP_FPM_GROUP" = "no"; then | |
485 | + php_fpm_group="nobody" | |
486 | + else | |
487 | + php_fpm_group="$PHP_FPM_GROUP" | |
488 | + fi | |
489 | + | |
490 | + | |
491 | + PHP_SUBST_OLD(fpm_version) | |
492 | + PHP_SUBST_OLD(php_fpm_bin) | |
493 | + PHP_SUBST_OLD(php_fpm_bin_dir) | |
494 | + PHP_SUBST_OLD(php_fpm_bin_path) | |
495 | + PHP_SUBST_OLD(php_fpm_port) | |
496 | + PHP_SUBST_OLD(php_fpm_conf) | |
497 | + PHP_SUBST_OLD(php_fpm_conf_dir) | |
498 | + PHP_SUBST_OLD(php_fpm_conf_path) | |
499 | + PHP_SUBST_OLD(php_fpm_init) | |
500 | + PHP_SUBST_OLD(php_fpm_init_dir) | |
501 | + PHP_SUBST_OLD(php_fpm_init_path) | |
502 | + PHP_SUBST_OLD(php_fpm_log_dir) | |
503 | + PHP_SUBST_OLD(php_fpm_log_path) | |
504 | + PHP_SUBST_OLD(php_fpm_pid_dir) | |
505 | + PHP_SUBST_OLD(php_fpm_pid_path) | |
506 | + PHP_SUBST_OLD(php_fpm_user) | |
507 | + PHP_SUBST_OLD(php_fpm_group) | |
508 | + | |
509 | + | |
510 | + AC_DEFINE_UNQUOTED(PHP_FPM_VERSION, "$fpm_version", [fpm version]) | |
511 | + AC_DEFINE_UNQUOTED(PHP_FPM_BIN, "$php_fpm_bin", [fpm binary executable]) | |
512 | + AC_DEFINE_UNQUOTED(PHP_FPM_BIN_DIR, "$php_fpm_bin_dir", [fpm binary dir]) | |
513 | + AC_DEFINE_UNQUOTED(PHP_FPM_BIN_PATH, "$php_fpm_bin_path", [fpm bin file path]) | |
514 | + AC_DEFINE_UNQUOTED(PHP_FPM_PORT, "$php_fpm_port", [tcp port]) | |
515 | + AC_DEFINE_UNQUOTED(PHP_FPM_CONF, "$php_fpm_conf", [fpm conf file]) | |
516 | + AC_DEFINE_UNQUOTED(PHP_FPM_CONF_DIR, "$php_fpm_conf_dir", [fpm conf dir]) | |
517 | + AC_DEFINE_UNQUOTED(PHP_FPM_CONF_PATH, "$php_fpm_conf_path", [fpm conf file path]) | |
518 | + AC_DEFINE_UNQUOTED(PHP_FPM_INIT, "$php_fpm_init", [fpm init file]) | |
519 | + AC_DEFINE_UNQUOTED(PHP_FPM_INIT_DIR, "$php_fpm_init_dir", [fpm init dir]) | |
520 | + AC_DEFINE_UNQUOTED(PHP_FPM_INIT_PATH, "$php_fpm_init_path", [fpm init file path]) | |
521 | + AC_DEFINE_UNQUOTED(PHP_FPM_LOG_DIR, "$php_fpm_log_dir", [fpm log dir]) | |
522 | + AC_DEFINE_UNQUOTED(PHP_FPM_LOG_PATH, "$php_fpm_log_path", [fpm log file path]) | |
523 | + AC_DEFINE_UNQUOTED(PHP_FPM_PID_DIR, "$php_fpm_pid_dir", [fpm pid dir]) | |
524 | + AC_DEFINE_UNQUOTED(PHP_FPM_PID_PATH, "$php_fpm_pid_path", [fpm pid file path]) | |
525 | + AC_DEFINE_UNQUOTED(PHP_FPM_USER, "$php_fpm_user", [fpm user name]) | |
526 | + AC_DEFINE_UNQUOTED(PHP_FPM_GROUP, "$php_fpm_group", [fpm group name]) | |
527 | + | |
528 | +]) | |
529 | + | |
530 | + | |
531 | +AC_DEFUN([AC_FPM_OUTPUT], | |
532 | +[ | |
533 | + PHP_OUTPUT(sapi/fpm/php_fpm.conf:sapi/fpm/conf/php-fpm.conf.in) | |
534 | + PHP_OUTPUT(sapi/fpm/init.d.php_fpm:sapi/fpm/conf/init.d.php-fpm.in) | |
535 | + PHP_OUTPUT(sapi/fpm/nginx-site-conf.sample:sapi/fpm/conf/nginx-site-conf.sample.in) | |
536 | + PHP_OUTPUT(sapi/fpm/$php_fpm_bin.1:sapi/fpm/man/php-fpm.1.in) | |
537 | +]) | |
538 | + | |
539 | + | |
540 | +AC_DEFUN([AC_FPM_CONF], | |
541 | +[ | |
542 | + AC_FPM_ARGS | |
543 | + AC_FPM_VARS | |
544 | + AC_FPM_OUTPUT | |
545 | +]) | |
546 | + | |
547 | diff -Naur php-src-vanilla/sapi/fpm/ac/fpm_libevent.m4 php-src/sapi/fpm/ac/fpm_libevent.m4 | |
548 | --- php-src-vanilla/sapi/fpm/ac/fpm_libevent.m4 1970-01-01 01:00:00.000000000 +0100 | |
549 | +++ php-src/sapi/fpm/ac/fpm_libevent.m4 2009-10-18 21:05:39.310440424 +0100 | |
550 | @@ -0,0 +1,250 @@ | |
551 | +dnl @synopsis AC_LIB_EVENT([MINIMUM-VERSION],[REQUIRED-VERSION]) | |
552 | +dnl | |
553 | +dnl Test for the libevent library of a particular version (or newer). | |
554 | +dnl Source: http://svn.apache.org/repos/asf/incubator/thrift/trunk/aclocal/ax_lib_event.m4 | |
555 | +dnl Modified: This file was modified for autoconf-2.13 and the PHP_ARG_WITH macro. | |
556 | +dnl | |
557 | +dnl If no path to the installed libevent is given, the macro will first try | |
558 | +dnl using no -I or -L flags, then searches under /usr, /usr/local, /opt, | |
559 | +dnl and /opt/libevent. | |
560 | +dnl If these all fail, it will try the $LIBEVENT_ROOT environment variable. | |
561 | +dnl | |
562 | +dnl This macro requires that #include <sys/types.h> works and defines u_char. | |
563 | +dnl | |
564 | +dnl This macro calls: | |
565 | +dnl AC_SUBST(LIBEVENT_CFLAGS) | |
566 | +dnl AC_SUBST(LIBEVENT_LIBS) | |
567 | +dnl | |
568 | +dnl And (if libevent is found): | |
569 | +dnl AC_DEFINE(HAVE_LIBEVENT) | |
570 | +dnl | |
571 | +dnl It also leaves the shell variables "success" and "ac_have_libevent" | |
572 | +dnl set to "yes" or "no". | |
573 | +dnl | |
574 | +dnl NOTE: This macro does not currently work for cross-compiling, | |
575 | +dnl but it can be easily modified to allow it. (grep "cross"). | |
576 | +dnl | |
577 | +dnl @category InstalledPackages | |
578 | +dnl @category C | |
579 | +dnl @version 2007-09-12 | |
580 | +dnl @license AllPermissive | |
581 | +dnl | |
582 | +dnl Copyright (C) 2009 David Reiss | |
583 | +dnl Copying and distribution of this file, with or without modification, | |
584 | +dnl are permitted in any medium without royalty provided the copyright | |
585 | +dnl notice and this notice are preserved. | |
586 | + | |
587 | +AC_DEFUN([AC_LIB_EVENT_DO_CHECK], | |
588 | +[ | |
589 | +# Save our flags. | |
590 | +CPPFLAGS_SAVED="$CPPFLAGS" | |
591 | +LDFLAGS_SAVED="$LDFLAGS" | |
592 | +LIBS_SAVED="$LIBS" | |
593 | +LD_LIBRARY_PATH_SAVED="$LD_LIBRARY_PATH" | |
594 | + | |
595 | +# Set our flags if we are checking a specific directory. | |
596 | +if test -n "$ac_libevent_path" ; then | |
597 | + LIBEVENT_CPPFLAGS="-I$ac_libevent_path/include" | |
598 | + LIBEVENT_LDFLAGS="-L$ac_libevent_path/lib" | |
599 | + LD_LIBRARY_PATH="$ac_libevent_path/lib:$LD_LIBRARY_PATH" | |
600 | +else | |
601 | + LIBEVENT_CPPFLAGS="" | |
602 | + LIBEVENT_LDFLAGS="" | |
603 | +fi | |
604 | + | |
605 | +# Required flag for libevent. | |
606 | +LIBEVENT_LIBS="-levent" | |
607 | + | |
608 | +# Prepare the environment for compilation. | |
609 | +CPPFLAGS="$CPPFLAGS $LIBEVENT_CPPFLAGS" | |
610 | +LDFLAGS="$LDFLAGS $LIBEVENT_LDFLAGS" | |
611 | +LIBS="$LIBS $LIBEVENT_LIBS" | |
612 | +export CPPFLAGS | |
613 | +export LDFLAGS | |
614 | +export LIBS | |
615 | +export LD_LIBRARY_PATH | |
616 | + | |
617 | +success=no | |
618 | + | |
619 | +# Compile, link, and run the program. This checks: | |
620 | +# - event.h is available for including. | |
621 | +# - event_get_version() is available for linking. | |
622 | +# - The event version string is lexicographically greater | |
623 | +# than the required version. | |
624 | +AC_TRY_RUN([ | |
625 | +#include <sys/types.h> | |
626 | +#include <event.h> | |
627 | + | |
628 | +int main(int argc, char *argv[]) | |
629 | +{ | |
630 | + const char* lib_version = event_get_version(); | |
631 | + const char* wnt_version = "$WANT_LIBEVENT_VERSION"; | |
632 | + for (;;) { | |
633 | + /* If we reached the end of the want version. We have it. */ | |
634 | + if (*wnt_version == '\0' || *wnt_version == '-') { | |
635 | + return 0; | |
636 | + } | |
637 | + /* If the want version continues but the lib version does not, */ | |
638 | + /* we are missing a letter. We don't have it. */ | |
639 | + if (*lib_version == '\0' || *lib_version == '-') { | |
640 | + return 1; | |
641 | + } | |
642 | + | |
643 | + /* In the 1.4 version numbering style, if there are more digits */ | |
644 | + /* in one version than the other, that one is higher. */ | |
645 | + int lib_digits; | |
646 | + for (lib_digits = 0; | |
647 | + lib_version[lib_digits] >= '0' && | |
648 | + lib_version[lib_digits] <= '9'; | |
649 | + lib_digits++) | |
650 | + ; | |
651 | + int wnt_digits; | |
652 | + for (wnt_digits = 0; | |
653 | + wnt_version[wnt_digits] >= '0' && | |
654 | + wnt_version[wnt_digits] <= '9'; | |
655 | + wnt_digits++) | |
656 | + ; | |
657 | + if (lib_digits > wnt_digits) { | |
658 | + return 0; | |
659 | + } | |
660 | + if (lib_digits < wnt_digits) { | |
661 | + return 1; | |
662 | + } | |
663 | + /* If we have greater than what we want. We have it. */ | |
664 | + if (*lib_version > *wnt_version) { | |
665 | + return 0; | |
666 | + } | |
667 | + /* If we have less, we don't. */ | |
668 | + if (*lib_version < *wnt_version) { | |
669 | + return 1; | |
670 | + } | |
671 | + lib_version++; | |
672 | + wnt_version++; | |
673 | + } | |
674 | + return 0; | |
675 | +} | |
676 | +],[ | |
677 | +success=yes | |
678 | +]) | |
679 | + | |
680 | +# Restore flags. | |
681 | +LIBEVENT_LIBS="" | |
682 | +CPPFLAGS="$CPPFLAGS_SAVED" | |
683 | +LDFLAGS="$LDFLAGS_SAVED" | |
684 | +LIBS="$LIBS_SAVED" | |
685 | +LD_LIBRARY_PATH="$LD_LIBRARY_PATH_SAVED" | |
686 | +]) | |
687 | + | |
688 | +AC_DEFUN([AC_LIB_EVENT], | |
689 | +[ | |
690 | + | |
691 | +PHP_ARG_WITH(libevent,, | |
692 | +[ --with-libevent[=PATH] Path to the libevent, needed for fpm SAPI [/usr/local]], yes, yes) | |
693 | + | |
694 | +if test "$PHP_LIBEVENT" != "no"; then | |
695 | + LIBEVENT_MIN_VERSION=ifelse([$1], ,1.4.3,$1) | |
696 | + LIBEVENT_REQ_VERSION=ifelse([$2], ,1.4.11,$2) | |
697 | + | |
698 | + # Default library search paths ($sys_lib_search_path_spec) | |
699 | + AC_LIBTOOL_SYS_DYNAMIC_LINKER | |
700 | + | |
701 | + libevent_prefix=$ac_default_prefix | |
702 | + if test $prefix != "NONE" -a $prefix != "" -a $prefix != "no" ; then | |
703 | + libevent_prefix=$prefix | |
704 | + fi | |
705 | + | |
706 | + if test "$PHP_LIBEVENT" = "yes"; then | |
707 | + PHP_LIBEVENT=$libevent_prefix | |
708 | + fi | |
709 | + | |
710 | + AC_MSG_CHECKING(for libevent >= $LIBEVENT_REQ_VERSION) | |
711 | + for ac_libevent_path in "" $PHP_LIBEVENT /usr /usr/local /opt /opt/local /opt/libevent ; do | |
712 | + WANT_LIBEVENT_VERSION="$LIBEVENT_REQ_VERSION" | |
713 | + AC_LIB_EVENT_DO_CHECK | |
714 | + if test "$success" = "yes"; then | |
715 | + break; | |
716 | + fi | |
717 | + done | |
718 | + if test "$success" = "no"; then | |
719 | + | |
720 | + AC_MSG_RESULT(no) | |
721 | + AC_MSG_WARN([Could not find libevent $LIBEVENT_REQ_VERSION.]) | |
722 | + AC_MSG_WARN([The use of earlier versions of libevent is not recommended]) | |
723 | + AC_MSG_WARN([and can result in unspecified or unsupported behaviour.]) | |
724 | + | |
725 | + AC_MSG_CHECKING(for minimum libevent version >= $LIBEVENT_MIN_VERSION) | |
726 | + for ac_libevent_path in "" $PHP_LIBEVENT /usr /usr/local /opt /opt/local /opt/libevent ; do | |
727 | + WANT_LIBEVENT_VERSION="$LIBEVENT_MIN_VERSION" | |
728 | + AC_LIB_EVENT_DO_CHECK | |
729 | + if test "$success" = "yes"; then | |
730 | + break; | |
731 | + fi | |
732 | + done | |
733 | + if test "$success" = "no"; then | |
734 | + AC_MSG_RESULT(no) | |
735 | + LIBEVENT_LIBS="" | |
736 | + ac_have_libevent=no | |
737 | + AC_MSG_WARN([Syntax:]) | |
738 | + AC_MSG_WARN([--with-libevent=yes|[path] - link to libevent.a (static library)]) | |
739 | + AC_MSG_WARN([--with-libevent=shared[,path] - link to libevent.so (shared library)]) | |
740 | + AC_MSG_ERROR([Libevent minimum version >= $LIBEVENT_MIN_VERSION could not be found.]) | |
741 | + fi | |
742 | + fi | |
743 | + | |
744 | + if test "$ext_shared" = "yes"; then | |
745 | + if test -n "$ac_libevent_path"; then | |
746 | + LIBEVENT_LIBS="-L$ac_libevent_path/lib -levent" | |
747 | + else | |
748 | + LIBEVENT_LIBS="-levent" | |
749 | + fi | |
750 | + else | |
751 | + libevent_a="libevent.a" | |
752 | + if test -n "$ac_libevent_path"; then | |
753 | + if test -f "$ac_libevent_path/lib/$libevent_a" ; then | |
754 | + LIBEVENT_LIBS="$ac_libevent_path/lib/$libevent_a" | |
755 | + fi | |
756 | + if test -z "$LIBEVENT_LIBS"; then | |
757 | + AC_MSG_RESULT(no) | |
758 | + AC_MSG_WARN([libevent.a could not be found. We looked in:]) | |
759 | + AC_MSG_WARN([\"$ac_libevent_path\"]) | |
760 | + fi | |
761 | + else | |
762 | + for search_path in $sys_lib_search_path_spec ; do | |
763 | + if test -f "$search_path$libevent_a" ; then | |
764 | + LIBEVENT_LIBS="$search_path$libevent_a" | |
765 | + break; | |
766 | + fi | |
767 | + done | |
768 | + if test -z "$LIBEVENT_LIBS"; then | |
769 | + AC_MSG_RESULT(no) | |
770 | + AC_MSG_WARN([libevent.a could not be found. We looked in:]) | |
771 | + AC_MSG_WARN([\"$sys_lib_search_path_spec\"]) | |
772 | + fi | |
773 | + fi | |
774 | + if test -z "$LIBEVENT_LIBS"; then | |
775 | + AC_MSG_WARN([Install libevent system-wide (make install)]) | |
776 | + AC_MSG_WARN([Syntax:]) | |
777 | + AC_MSG_WARN([--with-libevent=yes|[path] - link to libevent.a (static library)]) | |
778 | + AC_MSG_WARN([--with-libevent=shared[,path] - link to libevent.so (shared library)]) | |
779 | + AC_MSG_ERROR([libevent.a could not be found. Stop.]) | |
780 | + fi | |
781 | + fi | |
782 | + | |
783 | + if test "$success" = "yes" ; then | |
784 | + AC_MSG_RESULT(yes) | |
785 | + ac_have_libevent=yes | |
786 | + AC_DEFINE(HAVE_LIBEVENT, 1, [define if libevent is available]) | |
787 | + fi | |
788 | + | |
789 | + if test -n "$ac_libevent_path"; then | |
790 | + LIBEVENT_CFLAGS="-I$ac_libevent_path/include" | |
791 | + fi | |
792 | + | |
793 | + AC_SUBST(LIBEVENT_CFLAGS) | |
794 | + AC_SUBST(LIBEVENT_LIBS) | |
795 | + | |
796 | +else | |
797 | + AC_MSG_ERROR([FPM Requires Libevent. You must build this target --with-libevent. Stop.]) | |
798 | +fi | |
799 | + | |
800 | +]) | |
801 | diff -Naur php-src-vanilla/sapi/fpm/ac/Makefile.frag php-src/sapi/fpm/ac/Makefile.frag | |
802 | --- php-src-vanilla/sapi/fpm/ac/Makefile.frag 1970-01-01 01:00:00.000000000 +0100 | |
803 | +++ php-src/sapi/fpm/ac/Makefile.frag 2009-10-18 21:05:39.310440424 +0100 | |
804 | @@ -0,0 +1,61 @@ | |
805 | +fpm: $(SAPI_FPM_PATH) | |
806 | + | |
807 | +$(SAPI_FPM_PATH): $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(SAPI_EXTRA_DEPS) | |
808 | + $(BUILD_FPM) | |
809 | + | |
810 | +install: install-fpm | |
811 | + | |
812 | +install-fpm: all | |
813 | + @echo "Installing PHP FPM binary: $(INSTALL_ROOT)$(php_fpm_bin_path)" | |
814 | + @$(mkinstalldirs) $(INSTALL_ROOT)$(php_fpm_bin_dir) | |
815 | + @$(mkinstalldirs) $(INSTALL_ROOT)$(php_fpm_pid_dir) | |
816 | + @$(mkinstalldirs) $(INSTALL_ROOT)$(php_fpm_log_dir) | |
817 | + @$(INSTALL) -m 0755 $(SAPI_FPM_PATH) $(INSTALL_ROOT)$(php_fpm_bin_path)$(program_suffix)$(EXEEXT) | |
818 | + | |
819 | + @test "$(php_fpm_conf)" && \ | |
820 | + echo "Installing PHP FPM config: $(INSTALL_ROOT)$(php_fpm_conf_path)" && \ | |
821 | + $(mkinstalldirs) $(INSTALL_ROOT)$(php_fpm_conf_dir) || : | |
822 | + | |
823 | + @test "$(php_fpm_conf)" && \ | |
824 | + test -f "$(INSTALL_ROOT)$(php_fpm_conf_path)" && \ | |
825 | + $(INSTALL_DATA) --backup=numbered $(INSTALL_ROOT)$(php_fpm_conf_path) $(INSTALL_ROOT)$(php_fpm_conf_path).old || : | |
826 | + | |
827 | + @test "$(php_fpm_conf)" && \ | |
828 | + $(INSTALL_DATA) sapi/fpm/php_fpm.conf $(INSTALL_ROOT)$(php_fpm_conf_path).default && \ | |
829 | + ln -sf $(INSTALL_ROOT)$(php_fpm_conf_path).default $(INSTALL_ROOT)$(php_fpm_conf_path) || : | |
830 | + | |
831 | + @echo "Installing PHP FPM man page: $(INSTALL_ROOT)$(mandir)/man1/$(php_fpm_bin)$(program_suffix).1" | |
832 | + @$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man1 | |
833 | + @$(INSTALL_DATA) sapi/fpm/$(php_fpm_bin).1 $(INSTALL_ROOT)$(mandir)/man1/$(php_fpm_bin)$(program_suffix).1 | |
834 | + | |
835 | + @test "$(php_fpm_init)" && \ | |
836 | + echo "Installing PHP FPM init script: $(INSTALL_ROOT)$(php_fpm_init_path)" && \ | |
837 | + $(mkinstalldirs) $(INSTALL_ROOT)$(php_fpm_init_dir) && \ | |
838 | + $(INSTALL) -m 0755 sapi/fpm/init.d.php_fpm $(INSTALL_ROOT)$(php_fpm_init_path) || : | |
839 | + | |
840 | + @test -d /etc/nginx/ && \ | |
841 | + echo "Installing NGINX sample config: /etc/nginx/nginx-site-conf.sample" && \ | |
842 | + $(mkinstalldirs) $(INSTALL_ROOT)/etc/nginx && \ | |
843 | + $(INSTALL_DATA) -b sapi/fpm/nginx-site-conf.sample $(INSTALL_ROOT)/etc/nginx/nginx-site-conf.sample || : | |
844 | + | |
845 | + @test -d /usr/local/etc/nginx/ && \ | |
846 | + echo "Installing NGINX sample config: /usr/local/etc/nginx/nginx-site-conf.sample" && \ | |
847 | + $(mkinstalldirs) $(INSTALL_ROOT)/usr/local/etc/nginx && \ | |
848 | + $(INSTALL_DATA) -b sapi/fpm/nginx-site-conf.sample $(INSTALL_ROOT)/usr/local/etc/nginx/nginx-site-conf.sample || : | |
849 | + | |
850 | + @test -d /usr/local/nginx/conf/ && \ | |
851 | + echo "Installing NGINX sample config: /usr/local/nginx/conf/nginx-site-conf.sample" && \ | |
852 | + $(mkinstalldirs) $(INSTALL_ROOT)/usr/local/nginx/conf && \ | |
853 | + $(INSTALL_DATA) -b sapi/fpm/nginx-site-conf.sample $(INSTALL_ROOT)/usr/local/nginx/conf/nginx-site-conf.sample || : | |
854 | + | |
855 | + @echo "" | |
856 | + @echo "*** FPM Installation complete. ***" | |
857 | + @echo "" | |
858 | + | |
859 | + @test "$(php_fpm_init)" && \ | |
860 | + echo "run:" && \ | |
861 | + echo "\`update-rc.d $(php_fpm_init) defaults; invoke-rc.d $(php_fpm_init) start\`" && \ | |
862 | + echo "" && \ | |
863 | + echo "or system equivalent to start the $(php_fpm_init) service." && \ | |
864 | + echo "" || : | |
865 | + | |
866 | diff -Naur php-src-vanilla/sapi/fpm/cgi/cgi_main.c php-src/sapi/fpm/cgi/cgi_main.c | |
867 | --- php-src-vanilla/sapi/fpm/cgi/cgi_main.c 1970-01-01 01:00:00.000000000 +0100 | |
868 | +++ php-src/sapi/fpm/cgi/cgi_main.c 2009-10-18 21:05:39.302497288 +0100 | |
869 | @@ -0,0 +1,1660 @@ | |
870 | +/* | |
871 | + +----------------------------------------------------------------------+ | |
872 | + | PHP Version 5 | | |
873 | + +----------------------------------------------------------------------+ | |
874 | + | Copyright (c) 1997-2008 The PHP Group | | |
875 | + +----------------------------------------------------------------------+ | |
876 | + | This source file is subject to version 3.01 of the PHP license, | | |
877 | + | that is bundled with this package in the file LICENSE, and is | | |
878 | + | available through the world-wide-web at the following url: | | |
879 | + | http://www.php.net/license/3_01.txt | | |
880 | + | If you did not receive a copy of the PHP license and are unable to | | |
881 | + | obtain it through the world-wide-web, please send a note to | | |
882 | + | license@php.net so we can mail you a copy immediately. | | |
883 | + +----------------------------------------------------------------------+ | |
884 | + | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca> | | |
885 | + | Stig Bakken <ssb@php.net> | | |
886 | + | Zeev Suraski <zeev@zend.com> | | |
887 | + | FastCGI: Ben Mansell <php@slimyhorror.com> | | |
888 | + | Shane Caraveo <shane@caraveo.com> | | |
889 | + | Dmitry Stogov <dmitry@zend.com> | | |
890 | + +----------------------------------------------------------------------+ | |
891 | +*/ | |
892 | + | |
893 | +/* $Id$ */ | |
894 | + | |
895 | +#include <php.h> | |
896 | +#include <php_globals.h> | |
897 | +#include <php_variables.h> | |
898 | +#include <zend_modules.h> | |
899 | + | |
900 | +#include <SAPI.h> | |
901 | + | |
902 | +#include <stdio.h> | |
903 | + | |
904 | +#ifdef PHP_WIN32 | |
905 | +#include "win32/time.h" | |
906 | +#include "win32/signal.h" | |
907 | +#include <process.h> | |
908 | +#endif | |
909 | +#if HAVE_SYS_TIME_H | |
910 | +#include <sys/time.h> | |
911 | +#endif | |
912 | +#if HAVE_UNISTD_H | |
913 | +#include <unistd.h> | |
914 | +#endif | |
915 | +#if HAVE_SIGNAL_H | |
916 | +#include <signal.h> | |
917 | +#endif | |
918 | +#if HAVE_SETLOCALE | |
919 | +#include <locale.h> | |
920 | +#endif | |
921 | +#if HAVE_SYS_TYPES_H | |
922 | +#include <sys/types.h> | |
923 | +#endif | |
924 | +#if HAVE_SYS_WAIT_H | |
925 | +#include <sys/wait.h> | |
926 | +#endif | |
927 | +#if HAVE_FCNTL_H | |
928 | +#include <fcntl.h> | |
929 | +#endif | |
930 | +#include <zend.h> | |
931 | +#include <zend_extensions.h> | |
932 | +#include <php_ini.h> | |
933 | +#include <php_main.h> | |
934 | +#include <fopen_wrappers.h> | |
935 | +#include <ext/standard/php_standard.h> | |
936 | +#ifdef PHP_WIN32 | |
937 | +#include <io.h> | |
938 | +#include <fcntl.h> | |
939 | +#include "win32/php_registry.h" | |
940 | +#endif | |
941 | + | |
942 | +#ifdef __riscos__ | |
943 | +#include <unixlib/local.h> | |
944 | +int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS; | |
945 | +#endif | |
946 | + | |
947 | +#include "zend_compile.h" | |
948 | +#include "zend_execute.h" | |
949 | +#include "zend_highlight.h" | |
950 | +#include "zend_indent.h" | |
951 | + | |
952 | +#include "php_getopt.h" | |
953 | + | |
954 | +#include "fastcgi.h" | |
955 | + | |
956 | +#ifdef FPM_AUTOCONFIG_H | |
957 | +#include <fpm_autoconfig.h> | |
958 | +#else | |
959 | +#include <php_config.h> | |
960 | +#endif | |
961 | +#include <fpm/fpm.h> | |
962 | +#include <fpm/fpm_request.h> | |
963 | + | |
964 | + | |
965 | +static void (*php_php_import_environment_variables)(zval *array_ptr TSRMLS_DC); | |
966 | + | |
967 | +static int parent = 1; | |
968 | + | |
969 | +static int request_body_fd; | |
970 | + | |
971 | +static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC); | |
972 | + | |
973 | +static char *php_optarg = NULL; | |
974 | +static int php_optind = 1; | |
975 | +static zend_module_entry cgi_module_entry; | |
976 | + | |
977 | +static const opt_struct OPTIONS[] = { | |
978 | + {'a', 0, "interactive"}, | |
979 | + {'b', 1, "bindpath"}, | |
980 | + {'C', 0, "no-chdir"}, | |
981 | + {'c', 1, "php-ini"}, | |
982 | + {'d', 1, "define"}, | |
983 | + {'e', 0, "profile-info"}, | |
984 | + {'f', 1, "file"}, | |
985 | + {'h', 0, "help"}, | |
986 | + {'i', 0, "info"}, | |
987 | + {'l', 0, "syntax-check"}, | |
988 | + {'m', 0, "modules"}, | |
989 | + {'n', 0, "no-php-ini"}, | |
990 | + {'q', 0, "no-header"}, | |
991 | + {'s', 0, "syntax-highlight"}, | |
992 | + {'s', 0, "syntax-highlighting"}, | |
993 | + {'w', 0, "strip"}, | |
994 | + {'?', 0, "usage"},/* help alias (both '?' and 'usage') */ | |
995 | + {'v', 0, "version"}, | |
996 | + {'x', 0, "fpm"}, | |
997 | + {'y', 1, "fpm-config"}, | |
998 | + {'z', 1, "zend-extension"}, | |
999 | + {'-', 0, NULL} /* end of args */ | |
1000 | +}; | |
1001 | + | |
1002 | +typedef struct _php_cgi_globals_struct { | |
1003 | + zend_bool rfc2616_headers; | |
1004 | + zend_bool nph; | |
1005 | + zend_bool check_shebang_line; | |
1006 | +#if ENABLE_PATHINFO_CHECK | |
1007 | + zend_bool fix_pathinfo; | |
1008 | +#endif | |
1009 | + zend_bool fcgi_logging; | |
1010 | +# ifdef PHP_WIN32 | |
1011 | + zend_bool impersonate; | |
1012 | +# endif | |
1013 | + char *error_header; | |
1014 | +} php_cgi_globals_struct; | |
1015 | + | |
1016 | +#ifdef ZTS | |
1017 | +static int php_cgi_globals_id; | |
1018 | +#define CGIG(v) TSRMG(php_cgi_globals_id, php_cgi_globals_struct *, v) | |
1019 | +#else | |
1020 | +static php_cgi_globals_struct php_cgi_globals; | |
1021 | +#define CGIG(v) (php_cgi_globals.v) | |
1022 | +#endif | |
1023 | + | |
1024 | +#ifdef PHP_WIN32 | |
1025 | +#define TRANSLATE_SLASHES(path) \ | |
1026 | + { \ | |
1027 | + char *tmp = path; \ | |
1028 | + while (*tmp) { \ | |
1029 | + if (*tmp == '\\') *tmp = '/'; \ | |
1030 | + tmp++; \ | |
1031 | + } \ | |
1032 | + } | |
1033 | +#else | |
1034 | +#define TRANSLATE_SLASHES(path) | |
1035 | +#endif | |
1036 | + | |
1037 | +static int print_module_info(zend_module_entry *module, void *arg TSRMLS_DC) | |
1038 | +{ | |
1039 | + php_printf("%s\n", module->name); | |
1040 | + return 0; | |
1041 | +} | |
1042 | + | |
1043 | +static int module_name_cmp(const void *a, const void *b TSRMLS_DC) | |
1044 | +{ | |
1045 | + Bucket *f = *((Bucket **) a); | |
1046 | + Bucket *s = *((Bucket **) b); | |
1047 | + | |
1048 | + return strcasecmp(((zend_module_entry *)f->pData)->name, | |
1049 | + ((zend_module_entry *)s->pData)->name); | |
1050 | +} | |
1051 | + | |
1052 | +static void print_modules(TSRMLS_D) | |
1053 | +{ | |
1054 | + HashTable sorted_registry; | |
1055 | + zend_module_entry tmp; | |
1056 | + | |
1057 | + zend_hash_init(&sorted_registry, 50, NULL, NULL, 1); | |
1058 | + zend_hash_copy(&sorted_registry, &module_registry, NULL, &tmp, sizeof(zend_module_entry)); | |
1059 | + zend_hash_sort(&sorted_registry, zend_qsort, module_name_cmp, 0 TSRMLS_CC); | |
1060 | + zend_hash_apply_with_argument(&sorted_registry, (apply_func_arg_t) print_module_info, NULL TSRMLS_CC); | |
1061 | + zend_hash_destroy(&sorted_registry); | |
1062 | +} | |
1063 | + | |
1064 | +static int print_extension_info(zend_extension *ext, void *arg TSRMLS_DC) | |
1065 | +{ | |
1066 | + php_printf("%s\n", ext->name); | |
1067 | + return 0; | |
1068 | +} | |
1069 | + | |
1070 | +static int extension_name_cmp(const zend_llist_element **f, | |
1071 | + const zend_llist_element **s TSRMLS_DC) | |
1072 | +{ | |
1073 | + return strcmp(((zend_extension *)(*f)->data)->name, | |
1074 | + ((zend_extension *)(*s)->data)->name); | |
1075 | +} | |
1076 | + | |
1077 | +static void print_extensions(TSRMLS_D) | |
1078 | +{ | |
1079 | + zend_llist sorted_exts; | |
1080 | + | |
1081 | + zend_llist_copy(&sorted_exts, &zend_extensions); | |
1082 | + sorted_exts.dtor = NULL; | |
1083 | + zend_llist_sort(&sorted_exts, extension_name_cmp TSRMLS_CC); | |
1084 | + zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL TSRMLS_CC); | |
1085 | + zend_llist_destroy(&sorted_exts); | |
1086 | +} | |
1087 | + | |
1088 | +#ifndef STDOUT_FILENO | |
1089 | +#define STDOUT_FILENO 1 | |
1090 | +#endif | |
1091 | + | |
1092 | +static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC) | |
1093 | +{ | |
1094 | + long ret; | |
1095 | + | |
1096 | + if (fcgi_is_fastcgi()) { | |
1097 | + fcgi_request *request = (fcgi_request*) SG(server_context); | |
1098 | + long ret = fcgi_write(request, FCGI_STDOUT, str, str_length); | |
1099 | + if (ret <= 0) { | |
1100 | + return 0; | |
1101 | + } | |
1102 | + return ret; | |
1103 | + } | |
1104 | + ret = write(STDOUT_FILENO, str, str_length); | |
1105 | + if (ret <= 0) return 0; | |
1106 | + return ret; | |
1107 | +} | |
1108 | + | |
1109 | +static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC) | |
1110 | +{ | |
1111 | + const char *ptr = str; | |
1112 | + uint remaining = str_length; | |
1113 | + size_t ret; | |
1114 | + | |
1115 | + while (remaining > 0) { | |
1116 | + ret = sapi_cgibin_single_write(ptr, remaining TSRMLS_CC); | |
1117 | + if (!ret) { | |
1118 | + php_handle_aborted_connection(); | |
1119 | + return str_length - remaining; | |
1120 | + } | |
1121 | + ptr += ret; | |
1122 | + remaining -= ret; | |
1123 | + } | |
1124 | + | |
1125 | + return str_length; | |
1126 | +} | |
1127 | + | |
1128 | + | |
1129 | +static void sapi_cgibin_flush(void *server_context) | |
1130 | +{ | |
1131 | + if (fcgi_is_fastcgi()) { | |
1132 | + fcgi_request *request = (fcgi_request*) server_context; | |
1133 | + if ( | |
1134 | +#ifndef PHP_WIN32 | |
1135 | + !parent && | |
1136 | +#endif | |
1137 | + request && !fcgi_flush(request, 0)) { | |
1138 | + php_handle_aborted_connection(); | |
1139 | + } | |
1140 | + return; | |
1141 | + } | |
1142 | + if (fflush(stdout) == EOF) { | |
1143 | + php_handle_aborted_connection(); | |
1144 | + } | |
1145 | +} | |
1146 | + | |
1147 | +#define SAPI_CGI_MAX_HEADER_LENGTH 1024 | |
1148 | + | |
1149 | +typedef struct _http_error { | |
1150 | + int code; | |
1151 | + const char* msg; | |
1152 | +} http_error; | |
1153 | + | |
1154 | +static const http_error http_error_codes[] = { | |
1155 | + {100, "Continue"}, | |
1156 | + {101, "Switching Protocols"}, | |
1157 | + {200, "OK"}, | |
1158 | + {201, "Created"}, | |
1159 | + {202, "Accepted"}, | |
1160 | + {203, "Non-Authoritative Information"}, | |
1161 | + {204, "No Content"}, | |
1162 | + {205, "Reset Content"}, | |
1163 | + {206, "Partial Content"}, | |
1164 | + {300, "Multiple Choices"}, | |
1165 | + {301, "Moved Permanently"}, | |
1166 | + {302, "Moved Temporarily"}, | |
1167 | + {303, "See Other"}, | |
1168 | + {304, "Not Modified"}, | |
1169 | + {305, "Use Proxy"}, | |
1170 | + {400, "Bad Request"}, | |
1171 | + {401, "Unauthorized"}, | |
1172 | + {402, "Payment Required"}, | |
1173 | + {403, "Forbidden"}, | |
1174 | + {404, "Not Found"}, | |
1175 | + {405, "Method Not Allowed"}, | |
1176 | + {406, "Not Acceptable"}, | |
1177 | + {407, "Proxy Authentication Required"}, | |
1178 | + {408, "Request Time-out"}, | |
1179 | + {409, "Conflict"}, | |
1180 | + {410, "Gone"}, | |
1181 | + {411, "Length Required"}, | |
1182 | + {412, "Precondition Failed"}, | |
1183 | + {413, "Request Entity Too Large"}, | |
1184 | + {414, "Request-URI Too Large"}, | |
1185 | + {415, "Unsupported Media Type"}, | |
1186 | + {500, "Internal Server Error"}, | |
1187 | + {501, "Not Implemented"}, | |
1188 | + {502, "Bad Gateway"}, | |
1189 | + {503, "Service Unavailable"}, | |
1190 | + {504, "Gateway Time-out"}, | |
1191 | + {505, "HTTP Version not supported"}, | |
1192 | + {0, NULL} | |
1193 | +}; | |
1194 | + | |
1195 | +static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) | |
1196 | +{ | |
1197 | + char buf[SAPI_CGI_MAX_HEADER_LENGTH]; | |
1198 | + sapi_header_struct *h; | |
1199 | + zend_llist_position pos; | |
1200 | + zend_bool ignore_status = 0; | |
1201 | + int response_status = SG(sapi_headers).http_response_code; | |
1202 | + | |
1203 | + if (SG(request_info).no_headers == 1) { | |
1204 | + return SAPI_HEADER_SENT_SUCCESSFULLY; | |
1205 | + } | |
1206 | + | |
1207 | + if (CGIG(nph) || SG(sapi_headers).http_response_code != 200) | |
1208 | + { | |
1209 | + int len; | |
1210 | + zend_bool has_status = 0; | |
1211 | + | |
1212 | + if (CGIG(rfc2616_headers) && SG(sapi_headers).http_status_line) { | |
1213 | + char *s; | |
1214 | + len = slprintf(buf, SAPI_CGI_MAX_HEADER_LENGTH, "%s\r\n", SG(sapi_headers).http_status_line); | |
1215 | + if ((s = strchr(SG(sapi_headers).http_status_line, ' '))) { | |
1216 | + response_status = atoi((s + 1)); | |
1217 | + } | |
1218 | + | |
1219 | + if (len > SAPI_CGI_MAX_HEADER_LENGTH) { | |
1220 | + len = SAPI_CGI_MAX_HEADER_LENGTH; | |
1221 | + } | |
1222 | + | |
1223 | + } else { | |
1224 | + char *s; | |
1225 | + | |
1226 | + if (SG(sapi_headers).http_status_line && | |
1227 | + (s = strchr(SG(sapi_headers).http_status_line, ' ')) != 0 && | |
1228 | + (s - SG(sapi_headers).http_status_line) >= 5 && | |
1229 | + strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0) { | |
1230 | + len = slprintf(buf, sizeof(buf), "Status:%s\r\n", s); | |
1231 | + response_status = atoi((s + 1)); | |
1232 | + } else { | |
1233 | + h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos); | |
1234 | + while (h) { | |
1235 | + if (h->header_len > sizeof("Status:")-1 && | |
1236 | + strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0) { | |
1237 | + has_status = 1; | |
1238 | + break; | |
1239 | + } | |
1240 | + h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); | |
1241 | + } | |
1242 | + if (!has_status) { | |
1243 | + http_error *err = (http_error*)http_error_codes; | |
1244 | + | |
1245 | + while (err->code != 0) { | |
1246 | + if (err->code == SG(sapi_headers).http_response_code) { | |
1247 | + break; | |
1248 | + } | |
1249 | + err++; | |
1250 | + } | |
1251 | + if (err->msg) { | |
1252 | + len = slprintf(buf, sizeof(buf), "Status: %d %s\r\n", SG(sapi_headers).http_response_code, err->msg); | |
1253 | + } else { | |
1254 | + len = slprintf(buf, sizeof(buf), "Status: %d\r\n", SG(sapi_headers).http_response_code); | |
1255 | + } | |
1256 | + } | |
1257 | + } | |
1258 | + } | |
1259 | + if (!has_status) { | |
1260 | + PHPWRITE_H(buf, len); | |
1261 | + ignore_status = 1; | |
1262 | + } | |
1263 | + } | |
1264 | + | |
1265 | + h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos); | |
1266 | + while (h) { | |
1267 | + /* prevent CRLFCRLF */ | |
1268 | + if (h->header_len) { | |
1269 | + if (h->header_len > sizeof("Status:")-1 && | |
1270 | + strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0) { | |
1271 | + if (!ignore_status) { | |
1272 | + ignore_status = 1; | |
1273 | + PHPWRITE_H(h->header, h->header_len); | |
1274 | + PHPWRITE_H("\r\n", 2); | |
1275 | + } | |
1276 | + } else if (response_status == 304 && h->header_len > sizeof("Content-Type:")-1 && | |
1277 | + strncasecmp(h->header, "Content-Type:", sizeof("Content-Type:")-1) == 0) { | |
1278 | + h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); | |
1279 | + continue; | |
1280 | + } else { | |
1281 | + PHPWRITE_H(h->header, h->header_len); | |
1282 | + PHPWRITE_H("\r\n", 2); | |
1283 | + } | |
1284 | + } | |
1285 | + h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); | |
1286 | + } | |
1287 | + PHPWRITE_H("\r\n", 2); | |
1288 | + | |
1289 | + return SAPI_HEADER_SENT_SUCCESSFULLY; | |
1290 | +} | |
1291 | + | |
1292 | + | |
1293 | +static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) | |
1294 | +{ | |
1295 | + int read_bytes=0, tmp_read_bytes; | |
1296 | + | |
1297 | + count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes)); | |
1298 | + while (read_bytes < count_bytes) { | |
1299 | + if (fcgi_is_fastcgi()) { | |
1300 | + fcgi_request *request = (fcgi_request*) SG(server_context); | |
1301 | + | |
1302 | + if (request_body_fd == -1) { | |
1303 | + char *request_body_filename = sapi_cgibin_getenv((char *) "REQUEST_BODY_FILE", | |
1304 | + sizeof("REQUEST_BODY_FILE")-1 TSRMLS_CC); | |
1305 | + | |
1306 | + if (request_body_filename && *request_body_filename) { | |
1307 | + request_body_fd = open(request_body_filename, O_RDONLY); | |
1308 | + | |
1309 | + if (0 > request_body_fd) { | |
1310 | + php_error(E_WARNING, "REQUEST_BODY_FILE: open('%s') failed: %s (%d)", | |
1311 | + request_body_filename, strerror(errno), errno); | |
1312 | + return 0; | |
1313 | + } | |
1314 | + } | |
1315 | + } | |
1316 | + | |
1317 | + /* If REQUEST_BODY_FILE variable not available - read post body from fastcgi stream */ | |
1318 | + if (request_body_fd < 0) { | |
1319 | + tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes); | |
1320 | + } else { | |
1321 | + tmp_read_bytes = read(request_body_fd, buffer + read_bytes, count_bytes - read_bytes); | |
1322 | + } | |
1323 | + } else { | |
1324 | + tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes); | |
1325 | + } | |
1326 | + | |
1327 | + if (tmp_read_bytes <= 0) { | |
1328 | + break; | |
1329 | + } | |
1330 | + read_bytes += tmp_read_bytes; | |
1331 | + } | |
1332 | + return read_bytes; | |
1333 | +} | |
1334 | + | |
1335 | +static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC) | |
1336 | +{ | |
1337 | + /* when php is started by mod_fastcgi, no regular environment | |
1338 | + is provided to PHP. It is always sent to PHP at the start | |
1339 | + of a request. So we have to do our own lookup to get env | |
1340 | + vars. This could probably be faster somehow. */ | |
1341 | + if (fcgi_is_fastcgi()) { | |
1342 | + fcgi_request *request = (fcgi_request*) SG(server_context); | |
1343 | + return fcgi_getenv(request, name, name_len); | |
1344 | + } | |
1345 | + /* if cgi, or fastcgi and not found in fcgi env | |
1346 | + check the regular environment */ | |
1347 | + return getenv(name); | |
1348 | +} | |
1349 | + | |
1350 | +static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC) | |
1351 | +{ | |
1352 | + int name_len; | |
1353 | +#if !HAVE_SETENV || !HAVE_UNSETENV | |
1354 | + int len; | |
1355 | + char *buf; | |
1356 | +#endif | |
1357 | + | |
1358 | + if (!name) { | |
1359 | + return NULL; | |
1360 | + } | |
1361 | + name_len = strlen(name); | |
1362 | + | |
1363 | + /* when php is started by mod_fastcgi, no regular environment | |
1364 | + is provided to PHP. It is always sent to PHP at the start | |
1365 | + of a request. So we have to do our own lookup to get env | |
1366 | + vars. This could probably be faster somehow. */ | |
1367 | + if (fcgi_is_fastcgi()) { | |
1368 | + fcgi_request *request = (fcgi_request*) SG(server_context); | |
1369 | + return fcgi_putenv(request, name, name_len, value); | |
1370 | + } | |
1371 | +#if HAVE_SETENV | |
1372 | + if (value) { | |
1373 | + setenv(name, value, 1); | |
1374 | + } | |
1375 | +#endif | |
1376 | +#if HAVE_UNSETENV | |
1377 | + if (!value) { | |
1378 | + unsetenv(name); | |
1379 | + } | |
1380 | +#endif | |
1381 | + | |
1382 | +#if !HAVE_SETENV || !HAVE_UNSETENV | |
1383 | + /* if cgi, or fastcgi and not found in fcgi env | |
1384 | + check the regular environment | |
1385 | + this leaks, but it's only cgi anyway, we'll fix | |
1386 | + it for 5.0 | |
1387 | + */ | |
1388 | + len = name_len + (value ? strlen(value) : 0) + sizeof("=") + 2; | |
1389 | + buf = (char *) malloc(len); | |
1390 | + if (buf == NULL) { | |
1391 | + return getenv(name); | |
1392 | + } | |
1393 | +#endif | |
1394 | +#if !HAVE_SETENV | |
1395 | + if (value) { | |
1396 | + len = slprintf(buf, len - 1, "%s=%s", name, value); | |
1397 | + putenv(buf); | |
1398 | + } | |
1399 | +#endif | |
1400 | +#if !HAVE_UNSETENV | |
1401 | + if (!value) { | |
1402 | + len = slprintf(buf, len - 1, "%s=", name); | |
1403 | + putenv(buf); | |
1404 | + } | |
1405 | +#endif | |
1406 | + return getenv(name); | |
1407 | +} | |
1408 | + | |
1409 | +static char *sapi_cgi_read_cookies(TSRMLS_D) | |
1410 | +{ | |
1411 | + return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE")-1 TSRMLS_CC); | |
1412 | +} | |
1413 | + | |
1414 | +void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC) | |
1415 | +{ | |
1416 | + if (PG(http_globals)[TRACK_VARS_ENV] && | |
1417 | + array_ptr != PG(http_globals)[TRACK_VARS_ENV] && | |
1418 | + Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY && | |
1419 | + zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_ENV])) > 0) { | |
1420 | + zval_dtor(array_ptr); | |
1421 | + *array_ptr = *PG(http_globals)[TRACK_VARS_ENV]; | |
1422 | + INIT_PZVAL(array_ptr); | |
1423 | + zval_copy_ctor(array_ptr); | |
1424 | + return; | |
1425 | + } else if (PG(http_globals)[TRACK_VARS_SERVER] && | |
1426 | + array_ptr != PG(http_globals)[TRACK_VARS_SERVER] && | |
1427 | + Z_TYPE_P(PG(http_globals)[TRACK_VARS_SERVER]) == IS_ARRAY && | |
1428 | + zend_hash_num_elements(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])) > 0) { | |
1429 | + zval_dtor(array_ptr); | |
1430 | + *array_ptr = *PG(http_globals)[TRACK_VARS_SERVER]; | |
1431 | + INIT_PZVAL(array_ptr); | |
1432 | + zval_copy_ctor(array_ptr); | |
1433 | + return; | |
1434 | + } | |
1435 | + | |
1436 | + /* call php's original import as a catch-all */ | |
1437 | + php_php_import_environment_variables(array_ptr TSRMLS_CC); | |
1438 | + | |
1439 | + if (fcgi_is_fastcgi()) { | |
1440 | + fcgi_request *request = (fcgi_request*) SG(server_context); | |
1441 | + HashPosition pos; | |
1442 | + int magic_quotes_gpc = PG(magic_quotes_gpc); | |
1443 | + char *var, **val; | |
1444 | + uint var_len; | |
1445 | + ulong idx; | |
1446 | + int filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER; | |
1447 | + | |
1448 | + /* turn off magic_quotes while importing environment variables */ | |
1449 | + PG(magic_quotes_gpc) = 0; | |
1450 | + for (zend_hash_internal_pointer_reset_ex(&request->env, &pos); | |
1451 | + zend_hash_get_current_key_ex(&request->env, &var, &var_len, &idx, 0, &pos) == HASH_KEY_IS_STRING && | |
1452 | + zend_hash_get_current_data_ex(&request->env, (void **) &val, &pos) == SUCCESS; | |
1453 | + zend_hash_move_forward_ex(&request->env, &pos)) { | |
1454 | + unsigned int new_val_len; | |
1455 | + if (sapi_module.input_filter(filter_arg, var, val, strlen(*val), &new_val_len TSRMLS_CC)) { | |
1456 | + php_register_variable_safe(var, *val, new_val_len, array_ptr TSRMLS_CC); | |
1457 | + } | |
1458 | + } | |
1459 | + PG(magic_quotes_gpc) = magic_quotes_gpc; | |
1460 | + } | |
1461 | +} | |
1462 | + | |
1463 | +static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC) | |
1464 | +{ | |
1465 | + unsigned int php_self_len; | |
1466 | + char *php_self; | |
1467 | + | |
1468 | + /* In CGI mode, we consider the environment to be a part of the server | |
1469 | + * variables | |
1470 | + */ | |
1471 | + php_import_environment_variables(track_vars_array TSRMLS_CC); | |
1472 | + | |
1473 | +#if ENABLE_PATHINFO_CHECK | |
1474 | + if (CGIG(fix_pathinfo)) { | |
1475 | + char *script_name = SG(request_info).request_uri; | |
1476 | + unsigned int script_name_len = script_name ? strlen(script_name) : 0; | |
1477 | + char *path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC); | |
1478 | + unsigned int path_info_len = path_info ? strlen(path_info) : 0; | |
1479 | + | |
1480 | + php_self_len = script_name_len + path_info_len; | |
1481 | + php_self = emalloc(php_self_len + 1); | |
1482 | + if (script_name) { | |
1483 | + memcpy(php_self, script_name, script_name_len + 1); | |
1484 | + } | |
1485 | + if (path_info) { | |
1486 | + memcpy(php_self + script_name_len, path_info, path_info_len + 1); | |
1487 | + } | |
1488 | + | |
1489 | + /* Build the special-case PHP_SELF variable for the CGI version */ | |
1490 | + if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) { | |
1491 | + php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC); | |
1492 | + } | |
1493 | + efree(php_self); | |
1494 | + return; | |
1495 | + } | |
1496 | +#endif | |
1497 | + | |
1498 | + php_self = SG(request_info).request_uri ? SG(request_info).request_uri : ""; | |
1499 | + php_self_len = strlen(php_self); | |
1500 | + if (sapi_module.input_filter(PARSE_SERVER, "PHP_SELF", &php_self, php_self_len, &php_self_len TSRMLS_CC)) { | |
1501 | + php_register_variable_safe("PHP_SELF", php_self, php_self_len, track_vars_array TSRMLS_CC); | |
1502 | + } | |
1503 | +} | |
1504 | + | |
1505 | +static void sapi_cgi_log_message(char *message) | |
1506 | +{ | |
1507 | + TSRMLS_FETCH(); | |
1508 | + | |
1509 | + if (fcgi_is_fastcgi() && CGIG(fcgi_logging)) { | |
1510 | + fcgi_request *request; | |
1511 | + | |
1512 | + request = (fcgi_request*) SG(server_context); | |
1513 | + if (request) { | |
1514 | + int len = strlen(message); | |
1515 | + char *buf = malloc(len+2); | |
1516 | + | |
1517 | + memcpy(buf, message, len); | |
1518 | + memcpy(buf + len, "\n", sizeof("\n")); | |
1519 | + fcgi_write(request, FCGI_STDERR, buf, len+1); | |
1520 | + free(buf); | |
1521 | + } else { | |
1522 | + fprintf(stderr, "%s\n", message); | |
1523 | + } | |
1524 | + /* ignore return code */ | |
1525 | + } else | |
1526 | + fprintf(stderr, "%s\n", message); | |
1527 | +} | |
1528 | + | |
1529 | +static int sapi_cgi_deactivate(TSRMLS_D) | |
1530 | +{ | |
1531 | + /* flush only when SAPI was started. The reasons are: | |
1532 | + 1. SAPI Deactivate is called from two places: module init and request shutdown | |
1533 | + 2. When the first call occurs and the request is not set up, flush fails on | |
1534 | + FastCGI. | |
1535 | + */ | |
1536 | + if (SG(sapi_started)) { | |
1537 | + sapi_cgibin_flush(SG(server_context)); | |
1538 | + } | |
1539 | + return SUCCESS; | |
1540 | +} | |
1541 | + | |
1542 | +static int php_cgi_startup(sapi_module_struct *sapi_module) | |
1543 | +{ | |
1544 | + if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) { | |
1545 | + return FAILURE; | |
1546 | + } | |
1547 | + return SUCCESS; | |
1548 | +} | |
1549 | + | |
1550 | + | |
1551 | +/* {{{ sapi_module_struct cgi_sapi_module | |
1552 | + */ | |
1553 | +static sapi_module_struct cgi_sapi_module = { | |
1554 | + "cgi-fcgi", /* name */ | |
1555 | + "CGI/FastCGI", /* pretty name */ | |
1556 | + | |
1557 | + php_cgi_startup, /* startup */ | |
1558 | + php_module_shutdown_wrapper, /* shutdown */ | |
1559 | + | |
1560 | + NULL, /* activate */ | |
1561 | + sapi_cgi_deactivate, /* deactivate */ | |
1562 | + | |
1563 | + sapi_cgibin_ub_write, /* unbuffered write */ | |
1564 | + sapi_cgibin_flush, /* flush */ | |
1565 | + NULL, /* get uid */ | |
1566 | + sapi_cgibin_getenv, /* getenv */ | |
1567 | + | |
1568 | + php_error, /* error handler */ | |
1569 | + | |
1570 | + NULL, /* header handler */ | |
1571 | + sapi_cgi_send_headers, /* send headers handler */ | |
1572 | + NULL, /* send header handler */ | |
1573 | + | |
1574 | + sapi_cgi_read_post, /* read POST data */ | |
1575 | + sapi_cgi_read_cookies, /* read Cookies */ | |
1576 | + | |
1577 | + sapi_cgi_register_variables, /* register server variables */ | |
1578 | + sapi_cgi_log_message, /* Log message */ | |
1579 | + NULL, /* Get request time */ | |
1580 | + | |
1581 | + STANDARD_SAPI_MODULE_PROPERTIES | |
1582 | +}; | |
1583 | +/* }}} */ | |
1584 | + | |
1585 | +/* {{{ php_cgi_usage | |
1586 | + */ | |
1587 | +static void php_cgi_usage(char *argv0) | |
1588 | +{ | |
1589 | + char *prog; | |
1590 | + | |
1591 | + prog = strrchr(argv0, '/'); | |
1592 | + if (prog) { | |
1593 | + prog++; | |
1594 | + } else { | |
1595 | + prog = "php"; | |
1596 | + } | |
1597 | + | |
1598 | + php_printf("Usage: %s [options]\n" | |
1599 | + "\n" | |
1600 | + " -C Do not chdir to the script's directory\n" | |
1601 | + " -c <path>|<file> Look for php.ini file in this directory\n" | |
1602 | + " -n No php.ini file will be used\n" | |
1603 | + " -d foo[=bar] Define INI entry foo with value 'bar'\n" | |
1604 | + " -e Generate extended information for debugger/profiler\n" | |
1605 | + " -h This help\n" | |
1606 | + " -i PHP information\n" | |
1607 | + " -m Show compiled in modules\n" | |
1608 | + " -v Version number\n" | |
1609 | + " -y, --fpm-config <file>\n" | |
1610 | + " Specify alternative path to FastCGI process manager config file.\n" | |
1611 | + " -z <file> Load Zend extension <file>.\n" | |
1612 | + , | |
1613 | + prog); | |
1614 | +} | |
1615 | +/* }}} */ | |
1616 | + | |
1617 | +/* {{{ is_valid_path | |
1618 | + * | |
1619 | + * some server configurations allow '..' to slip through in the | |
1620 | + * translated path. We'll just refuse to handle such a path. | |
1621 | + */ | |
1622 | +static int is_valid_path(const char *path) | |
1623 | +{ | |
1624 | + const char *p; | |
1625 | + | |
1626 | + if (!path) { | |
1627 | + return 0; | |
1628 | + } | |
1629 | + p = strstr(path, ".."); | |
1630 | + if (p) { | |
1631 | + if ((p == path || IS_SLASH(*(p-1))) && | |
1632 | + (*(p+2) == 0 || IS_SLASH(*(p+2)))) { | |
1633 | + return 0; | |
1634 | + } | |
1635 | + while (1) { | |
1636 | + p = strstr(p+1, ".."); | |
1637 | + if (!p) { | |
1638 | + break; | |
1639 | + } | |
1640 | + if (IS_SLASH(*(p-1)) && | |
1641 | + (*(p+2) == 0 || IS_SLASH(*(p+2)))) { | |
1642 | + return 0; | |
1643 | + } | |
1644 | + } | |
1645 | + } | |
1646 | + return 1; | |
1647 | +} | |
1648 | +/* }}} */ | |
1649 | + | |
1650 | +/* {{{ init_request_info | |
1651 | + | |
1652 | + initializes request_info structure | |
1653 | + | |
1654 | + specificly in this section we handle proper translations | |
1655 | + for: | |
1656 | + | |
1657 | + PATH_INFO | |
1658 | + derived from the portion of the URI path following | |
1659 | + the script name but preceding any query data | |
1660 | + may be empty | |
1661 | + | |
1662 | + PATH_TRANSLATED | |
1663 | + derived by taking any path-info component of the | |
1664 | + request URI and performing any virtual-to-physical | |
1665 | + translation appropriate to map it onto the server's | |
1666 | + document repository structure | |
1667 | + | |
1668 | + empty if PATH_INFO is empty | |
1669 | + | |
1670 | + The env var PATH_TRANSLATED **IS DIFFERENT** than the | |
1671 | + request_info.path_translated variable, the latter should | |
1672 | + match SCRIPT_FILENAME instead. | |
1673 | + | |
1674 | + SCRIPT_NAME | |
1675 | + set to a URL path that could identify the CGI script | |
1676 | + rather than the interpreter. PHP_SELF is set to this. | |
1677 | + | |
1678 | + REQUEST_URI | |
1679 | + uri section following the domain:port part of a URI | |
1680 | + | |
1681 | + SCRIPT_FILENAME | |
1682 | + The virtual-to-physical translation of SCRIPT_NAME (as per | |
1683 | + PATH_TRANSLATED) | |
1684 | + | |
1685 | + These settings are documented at | |
1686 | + http://cgi-spec.golux.com/ | |
1687 | + | |
1688 | + | |
1689 | + Based on the following URL request: | |
1690 | + | |
1691 | + http://localhost/info.php/test?a=b | |
1692 | + | |
1693 | + should produce, which btw is the same as if | |
1694 | + we were running under mod_cgi on apache (ie. not | |
1695 | + using ScriptAlias directives): | |
1696 | + | |
1697 | + PATH_INFO=/test | |
1698 | + PATH_TRANSLATED=/docroot/test | |
1699 | + SCRIPT_NAME=/info.php | |
1700 | + REQUEST_URI=/info.php/test?a=b | |
1701 | + SCRIPT_FILENAME=/docroot/info.php | |
1702 | + QUERY_STRING=a=b | |
1703 | + | |
1704 | + but what we get is (cgi/mod_fastcgi under apache): | |
1705 | + | |
1706 | + PATH_INFO=/info.php/test | |
1707 | + PATH_TRANSLATED=/docroot/info.php/test | |
1708 | + SCRIPT_NAME=/php/php-cgi (from the Action setting I suppose) | |
1709 | + REQUEST_URI=/info.php/test?a=b | |
1710 | + SCRIPT_FILENAME=/path/to/php/bin/php-cgi (Action setting translated) | |
1711 | + QUERY_STRING=a=b | |
1712 | + | |
1713 | + Comments in the code below refer to using the above URL in a request | |
1714 | + | |
1715 | + */ | |
1716 | +static void init_request_info(TSRMLS_D) | |
1717 | +{ | |
1718 | + char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1 TSRMLS_CC); | |
1719 | + char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1 TSRMLS_CC); | |
1720 | + char *script_path_translated = env_script_filename; | |
1721 | + | |
1722 | +#if !DISCARD_PATH | |
1723 | + /* some broken servers do not have script_filename or argv0 | |
1724 | + an example, IIS configured in some ways. then they do more | |
1725 | + broken stuff and set path_translated to the cgi script location */ | |
1726 | + if (!script_path_translated && env_path_translated) { | |
1727 | + script_path_translated = env_path_translated; | |
1728 | + } | |
1729 | +#endif | |
1730 | + | |
1731 | + /* initialize the defaults */ | |
1732 | + SG(request_info).path_translated = NULL; | |
1733 | + SG(request_info).request_method = NULL; | |
1734 | + SG(request_info).proto_num = 1000; | |
1735 | + SG(request_info).query_string = NULL; | |
1736 | + SG(request_info).request_uri = NULL; | |
1737 | + SG(request_info).content_type = NULL; | |
1738 | + SG(request_info).content_length = 0; | |
1739 | + SG(sapi_headers).http_response_code = 200; | |
1740 | + | |
1741 | + /* script_path_translated being set is a good indication that | |
1742 | + we are running in a cgi environment, since it is always | |
1743 | + null otherwise. otherwise, the filename | |
1744 | + of the script will be retreived later via argc/argv */ | |
1745 | + if (script_path_translated) { | |
1746 | + const char *auth; | |
1747 | + char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1 TSRMLS_CC); | |
1748 | + char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE")-1 TSRMLS_CC); | |
1749 | + char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC); | |
1750 | + char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1 TSRMLS_CC); | |
1751 | +#if ENABLE_PATHINFO_CHECK | |
1752 | + struct stat st; | |
1753 | + char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL")-1 TSRMLS_CC); | |
1754 | + char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC); | |
1755 | + int script_path_translated_len; | |
1756 | + | |
1757 | + /* Hack for buggy IIS that sets incorrect PATH_INFO */ | |
1758 | + char *env_server_software = sapi_cgibin_getenv("SERVER_SOFTWARE", sizeof("SERVER_SOFTWARE")-1 TSRMLS_CC); | |
1759 | + if (env_server_software && | |
1760 | + env_script_name && | |
1761 | + env_path_info && | |
1762 | + strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS")-1) == 0 && | |
1763 | + strncmp(env_path_info, env_script_name, strlen(env_script_name)) == 0) { | |
1764 | + env_path_info = _sapi_cgibin_putenv("ORIG_PATH_INFO", env_path_info TSRMLS_CC); | |
1765 | + env_path_info += strlen(env_script_name); | |
1766 | + if (*env_path_info == 0) { | |
1767 | + env_path_info = NULL; | |
1768 | + } | |
1769 | + env_path_info = _sapi_cgibin_putenv("PATH_INFO", env_path_info TSRMLS_CC); | |
1770 | + } | |
1771 | + | |
1772 | + if (CGIG(fix_pathinfo)) { | |
1773 | + char *real_path = NULL; | |
1774 | + char *orig_path_translated = env_path_translated; | |
1775 | + char *orig_path_info = env_path_info; | |
1776 | + char *orig_script_name = env_script_name; | |
1777 | + char *orig_script_filename = env_script_filename; | |
1778 | + | |
1779 | + if (!env_document_root && PG(doc_root)) { | |
1780 | + env_document_root = _sapi_cgibin_putenv("DOCUMENT_ROOT", PG(doc_root) TSRMLS_CC); | |
1781 | + /* fix docroot */ | |
1782 | + TRANSLATE_SLASHES(env_document_root); | |
1783 | + } | |
1784 | + | |
1785 | + if (env_path_translated != NULL && env_redirect_url != NULL) { | |
1786 | + /* | |
1787 | + pretty much apache specific. If we have a redirect_url | |
1788 | + then our script_filename and script_name point to the | |
1789 | + php executable | |
1790 | + */ | |
1791 | + script_path_translated = env_path_translated; | |
1792 | + /* we correct SCRIPT_NAME now in case we don't have PATH_INFO */ | |
1793 | + env_script_name = env_redirect_url; | |
1794 | + } | |
1795 | + | |
1796 | +#ifdef __riscos__ | |
1797 | + /* Convert path to unix format*/ | |
1798 | + __riscosify_control |= __RISCOSIFY_DONT_CHECK_DIR; | |
1799 | + script_path_translated = __unixify(script_path_translated, 0, NULL, 1, 0); | |
1800 | +#endif | |
1801 | + | |
1802 | + /* | |
1803 | + * if the file doesn't exist, try to extract PATH_INFO out | |
1804 | + * of it by stat'ing back through the '/' | |
1805 | + * this fixes url's like /info.php/test | |
1806 | + */ | |
1807 | + if (script_path_translated && | |
1808 | + (script_path_translated_len = strlen(script_path_translated)) > 0 && | |
1809 | + (script_path_translated[script_path_translated_len-1] == '/' || | |
1810 | +#ifdef PHP_WIN32 | |
1811 | + script_path_translated[script_path_translated_len-1] == '\\' || | |
1812 | +#endif | |
1813 | + (real_path = tsrm_realpath(script_path_translated, NULL TSRMLS_CC)) == NULL)) { | |
1814 | + char *pt = estrndup(script_path_translated, script_path_translated_len); | |
1815 | + int len = script_path_translated_len; | |
1816 | + char *ptr; | |
1817 | + | |
1818 | + while ((ptr = strrchr(pt, '/')) || (ptr = strrchr(pt, '\\'))) { | |
1819 | + *ptr = 0; | |
1820 | + if (stat(pt, &st) == 0 && S_ISREG(st.st_mode)) { | |
1821 | + /* | |
1822 | + * okay, we found the base script! | |
1823 | + * work out how many chars we had to strip off; | |
1824 | + * then we can modify PATH_INFO | |
1825 | + * accordingly | |
1826 | + * | |
1827 | + * we now have the makings of | |
1828 | + * PATH_INFO=/test | |
1829 | + * SCRIPT_FILENAME=/docroot/info.php | |
1830 | + * | |
1831 | + * we now need to figure out what docroot is. | |
1832 | + * if DOCUMENT_ROOT is set, this is easy, otherwise, | |
1833 | + * we have to play the game of hide and seek to figure | |
1834 | + * out what SCRIPT_NAME should be | |
1835 | + */ | |
1836 | + int slen = len - strlen(pt); | |
1837 | + int pilen = env_path_info ? strlen(env_path_info) : 0; | |
1838 | + char *path_info = env_path_info ? env_path_info + pilen - slen : NULL; | |
1839 | + | |
1840 | + if (orig_path_info != path_info) { | |
1841 | + if (orig_path_info) { | |
1842 | + char old; | |
1843 | + | |
1844 | + _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC); | |
1845 | + old = path_info[0]; | |
1846 | + path_info[0] = 0; | |
1847 | + if (!orig_script_name || | |
1848 | + strcmp(orig_script_name, env_path_info) != 0) { | |
1849 | + if (orig_script_name) { | |
1850 | + _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC); | |
1851 | + } | |
1852 | + SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_path_info TSRMLS_CC); | |
1853 | + } else { | |
1854 | + SG(request_info).request_uri = orig_script_name; | |
1855 | + } | |
1856 | + path_info[0] = old; | |
1857 | + } | |
1858 | + env_path_info = _sapi_cgibin_putenv("PATH_INFO", path_info TSRMLS_CC); | |
1859 | + } | |
1860 | + if (!orig_script_filename || | |
1861 | + strcmp(orig_script_filename, pt) != 0) { | |
1862 | + if (orig_script_filename) { | |
1863 | + _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC); | |
1864 | + } | |
1865 | + script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", pt TSRMLS_CC); | |
1866 | + } | |
1867 | + TRANSLATE_SLASHES(pt); | |
1868 | + | |
1869 | + /* figure out docroot | |
1870 | + SCRIPT_FILENAME minus SCRIPT_NAME | |
1871 | + */ | |
1872 | + | |
1873 | + if (env_document_root) { | |
1874 | + int l = strlen(env_document_root); | |
1875 | + int path_translated_len = 0; | |
1876 | + char *path_translated = NULL; | |
1877 | + | |
1878 | + if (l && env_document_root[l - 1] == '/') { | |
1879 | + --l; | |
1880 | + } | |
1881 | + | |
1882 | + /* we have docroot, so we should have: | |
1883 | + * DOCUMENT_ROOT=/docroot | |
1884 | + * SCRIPT_FILENAME=/docroot/info.php | |
1885 | + */ | |
1886 | + | |
1887 | + /* PATH_TRANSLATED = DOCUMENT_ROOT + PATH_INFO */ | |
1888 | + path_translated_len = l + (env_path_info ? strlen(env_path_info) : 0); | |
1889 | + path_translated = (char *) emalloc(path_translated_len + 1); | |
1890 | + memcpy(path_translated, env_document_root, l); | |
1891 | + if (env_path_info) { | |
1892 | + memcpy(path_translated + l, env_path_info, (path_translated_len - l)); | |
1893 | + } | |
1894 | + path_translated[path_translated_len] = '\0'; | |
1895 | + if (orig_path_translated) { | |
1896 | + _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC); | |
1897 | + } | |
1898 | + env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC); | |
1899 | + efree(path_translated); | |
1900 | + } else if (env_script_name && | |
1901 | + strstr(pt, env_script_name) | |
1902 | + ) { | |
1903 | + /* PATH_TRANSLATED = PATH_TRANSLATED - SCRIPT_NAME + PATH_INFO */ | |
1904 | + int ptlen = strlen(pt) - strlen(env_script_name); | |
1905 | + int path_translated_len = ptlen + (env_path_info ? strlen(env_path_info) : 0); | |
1906 | + char *path_translated = NULL; | |
1907 | + | |
1908 | + path_translated = (char *) emalloc(path_translated_len + 1); | |
1909 | + memcpy(path_translated, pt, ptlen); | |
1910 | + if (env_path_info) { | |
1911 | + memcpy(path_translated + ptlen, env_path_info, path_translated_len - ptlen); | |
1912 | + } | |
1913 | + path_translated[path_translated_len] = '\0'; | |
1914 | + if (orig_path_translated) { | |
1915 | + _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC); | |
1916 | + } | |
1917 | + env_path_translated = _sapi_cgibin_putenv("PATH_TRANSLATED", path_translated TSRMLS_CC); | |
1918 | + efree(path_translated); | |
1919 | + } | |
1920 | + break; | |
1921 | + } | |
1922 | + } | |
1923 | + if (!ptr) { | |
1924 | + /* | |
1925 | + * if we stripped out all the '/' and still didn't find | |
1926 | + * a valid path... we will fail, badly. of course we would | |
1927 | + * have failed anyway... we output 'no input file' now. | |
1928 | + */ | |
1929 | + if (orig_script_filename) { | |
1930 | + _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC); | |
1931 | + } | |
1932 | + script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", NULL TSRMLS_CC); | |
1933 | + SG(sapi_headers).http_response_code = 404; | |
1934 | + } | |
1935 | + if (!SG(request_info).request_uri) { | |
1936 | + if (!orig_script_name || | |
1937 | + strcmp(orig_script_name, env_script_name) != 0) { | |
1938 | + if (orig_script_name) { | |
1939 | + _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC); | |
1940 | + } | |
1941 | + SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC); | |
1942 | + } else { | |
1943 | + SG(request_info).request_uri = orig_script_name; | |
1944 | + } | |
1945 | + } | |
1946 | + if (pt) { | |
1947 | + efree(pt); | |
1948 | + } | |
1949 | + if (is_valid_path(script_path_translated)) { | |
1950 | + SG(request_info).path_translated = estrdup(script_path_translated); | |
1951 | + } | |
1952 | + } else { | |
1953 | + /* make sure path_info/translated are empty */ | |
1954 | + if (!orig_script_filename || | |
1955 | + (script_path_translated != orig_script_filename && | |
1956 | + strcmp(script_path_translated, orig_script_filename) != 0)) { | |
1957 | + if (orig_script_filename) { | |
1958 | + _sapi_cgibin_putenv("ORIG_SCRIPT_FILENAME", orig_script_filename TSRMLS_CC); | |
1959 | + } | |
1960 | + script_path_translated = _sapi_cgibin_putenv("SCRIPT_FILENAME", script_path_translated TSRMLS_CC); | |
1961 | + } | |
1962 | + if (env_redirect_url) { | |
1963 | + if (orig_path_info) { | |
1964 | + _sapi_cgibin_putenv("ORIG_PATH_INFO", orig_path_info TSRMLS_CC); | |
1965 | + _sapi_cgibin_putenv("PATH_INFO", NULL TSRMLS_CC); | |
1966 | + } | |
1967 | + if (orig_path_translated) { | |
1968 | + _sapi_cgibin_putenv("ORIG_PATH_TRANSLATED", orig_path_translated TSRMLS_CC); | |
1969 | + _sapi_cgibin_putenv("PATH_TRANSLATED", NULL TSRMLS_CC); | |
1970 | + } | |
1971 | + } | |
1972 | + if (env_script_name != orig_script_name) { | |
1973 | + if (orig_script_name) { | |
1974 | + _sapi_cgibin_putenv("ORIG_SCRIPT_NAME", orig_script_name TSRMLS_CC); | |
1975 | + } | |
1976 | + SG(request_info).request_uri = _sapi_cgibin_putenv("SCRIPT_NAME", env_script_name TSRMLS_CC); | |
1977 | + } else { | |
1978 | + SG(request_info).request_uri = env_script_name; | |
1979 | + } | |
1980 | + if (is_valid_path(script_path_translated)) { | |
1981 | + SG(request_info).path_translated = estrdup(script_path_translated); | |
1982 | + } | |
1983 | + free(real_path); | |
1984 | + } | |
1985 | + } else { | |
1986 | +#endif | |
1987 | + /* pre 4.3 behaviour, shouldn't be used but provides BC */ | |
1988 | + if (env_path_info) { | |
1989 | + SG(request_info).request_uri = env_path_info; | |
1990 | + } else { | |
1991 | + SG(request_info).request_uri = env_script_name; | |
1992 | + } | |
1993 | +#if !DISCARD_PATH | |
1994 | + if (env_path_translated) { | |
1995 | + script_path_translated = env_path_translated; | |
1996 | + } | |
1997 | +#endif | |
1998 | + if (is_valid_path(script_path_translated)) { | |
1999 | + SG(request_info).path_translated = estrdup(script_path_translated); | |
2000 | + } | |
2001 | +#if ENABLE_PATHINFO_CHECK | |
2002 | + } | |
2003 | +#endif | |
2004 | + SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD")-1 TSRMLS_CC); | |
2005 | + /* FIXME - Work out proto_num here */ | |
2006 | + SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING")-1 TSRMLS_CC); | |
2007 | + SG(request_info).content_type = (content_type ? content_type : "" ); | |
2008 | + SG(request_info).content_length = (content_length ? atoi(content_length) : 0); | |
2009 | + | |
2010 | + /* The CGI RFC allows servers to pass on unvalidated Authorization data */ | |
2011 | + auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION")-1 TSRMLS_CC); | |
2012 | + php_handle_auth_data(auth TSRMLS_CC); | |
2013 | + } | |
2014 | +} | |
2015 | +/* }}} */ | |
2016 | + | |
2017 | + | |
2018 | +PHP_INI_BEGIN() | |
2019 | + STD_PHP_INI_ENTRY("cgi.rfc2616_headers", "0", PHP_INI_ALL, OnUpdateBool, rfc2616_headers, php_cgi_globals_struct, php_cgi_globals) | |
2020 | + STD_PHP_INI_ENTRY("cgi.nph", "0", PHP_INI_ALL, OnUpdateBool, nph, php_cgi_globals_struct, php_cgi_globals) | |
2021 | + STD_PHP_INI_ENTRY("cgi.check_shebang_line", "1", PHP_INI_SYSTEM, OnUpdateBool, check_shebang_line, php_cgi_globals_struct, php_cgi_globals) | |
2022 | +#if ENABLE_PATHINFO_CHECK | |
2023 | + STD_PHP_INI_ENTRY("cgi.fix_pathinfo", "1", PHP_INI_SYSTEM, OnUpdateBool, fix_pathinfo, php_cgi_globals_struct, php_cgi_globals) | |
2024 | +#endif | |
2025 | + STD_PHP_INI_ENTRY("fastcgi.logging", "1", PHP_INI_SYSTEM, OnUpdateBool, fcgi_logging, php_cgi_globals_struct, php_cgi_globals) | |
2026 | +# ifdef PHP_WIN32 | |
2027 | + STD_PHP_INI_ENTRY("fastcgi.impersonate", "0", PHP_INI_SYSTEM, OnUpdateBool, impersonate, php_cgi_globals_struct, php_cgi_globals) | |
2028 | +# endif | |
2029 | + STD_PHP_INI_ENTRY("fastcgi.error_header", NULL, PHP_INI_SYSTEM, OnUpdateString, error_header, php_cgi_globals_struct, php_cgi_globals) | |
2030 | +PHP_INI_END() | |
2031 | + | |
2032 | +/* {{{ php_cgi_globals_ctor | |
2033 | + */ | |
2034 | +static void php_cgi_globals_ctor(php_cgi_globals_struct *php_cgi_globals TSRMLS_DC) | |
2035 | +{ | |
2036 | + php_cgi_globals->rfc2616_headers = 0; | |
2037 | + php_cgi_globals->nph = 0; | |
2038 | + php_cgi_globals->check_shebang_line = 1; | |
2039 | +#if ENABLE_PATHINFO_CHECK | |
2040 | + php_cgi_globals->fix_pathinfo = 1; | |
2041 | +#endif | |
2042 | + php_cgi_globals->fcgi_logging = 1; | |
2043 | +# ifdef PHP_WIN32 | |
2044 | + php_cgi_globals->impersonate = 0; | |
2045 | +# endif | |
2046 | + php_cgi_globals->error_header = NULL; | |
2047 | +} | |
2048 | +/* }}} */ | |
2049 | + | |
2050 | +/* {{{ PHP_MINIT_FUNCTION | |
2051 | + */ | |
2052 | +static PHP_MINIT_FUNCTION(cgi) | |
2053 | +{ | |
2054 | +#ifdef ZTS | |
2055 | + ts_allocate_id(&php_cgi_globals_id, sizeof(php_cgi_globals_struct), (ts_allocate_ctor) php_cgi_globals_ctor, NULL); | |
2056 | +#else | |
2057 | + php_cgi_globals_ctor(&php_cgi_globals TSRMLS_CC); | |
2058 | +#endif | |
2059 | + REGISTER_INI_ENTRIES(); | |
2060 | + return SUCCESS; | |
2061 | +} | |
2062 | +/* }}} */ | |
2063 | + | |
2064 | +/* {{{ PHP_MSHUTDOWN_FUNCTION | |
2065 | + */ | |
2066 | +static PHP_MSHUTDOWN_FUNCTION(cgi) | |
2067 | +{ | |
2068 | + UNREGISTER_INI_ENTRIES(); | |
2069 | + return SUCCESS; | |
2070 | +} | |
2071 | +/* }}} */ | |
2072 | + | |
2073 | +/* {{{ PHP_MINFO_FUNCTION | |
2074 | + */ | |
2075 | +static PHP_MINFO_FUNCTION(cgi) | |
2076 | +{ | |
2077 | + DISPLAY_INI_ENTRIES(); | |
2078 | + | |
2079 | + php_info_print_table_start(); | |
2080 | + php_info_print_table_row(2, "php-fpm", "active"); | |
2081 | + php_info_print_table_row(2, "php-fpm version", PHP_FPM_VERSION); | |
2082 | + php_info_print_table_end(); | |
2083 | + | |
2084 | +} | |
2085 | +/* }}} */ | |
2086 | + | |
2087 | +PHP_FUNCTION(fastcgi_finish_request) | |
2088 | +{ | |
2089 | + fcgi_request *request = (fcgi_request*) SG(server_context); | |
2090 | + | |
2091 | + if (fcgi_is_fastcgi() && request->fd >= 0) { | |
2092 | + | |
2093 | + php_end_ob_buffers(1 TSRMLS_CC); | |
2094 | + php_header(TSRMLS_C); | |
2095 | + | |
2096 | + fcgi_flush(request, 1); | |
2097 | + fcgi_close(request, 0, 0); | |
2098 | + RETURN_TRUE; | |
2099 | + } | |
2100 | + | |
2101 | + RETURN_FALSE; | |
2102 | + | |
2103 | +} | |
2104 | + | |
2105 | +function_entry cgi_fcgi_sapi_functions[] = { | |
2106 | + PHP_FE(fastcgi_finish_request, NULL) | |
2107 | + {NULL, NULL, NULL} | |
2108 | +}; | |
2109 | + | |
2110 | +static zend_module_entry cgi_module_entry = { | |
2111 | + STANDARD_MODULE_HEADER, | |
2112 | + "cgi-fcgi", | |
2113 | + cgi_fcgi_sapi_functions, | |
2114 | + PHP_MINIT(cgi), | |
2115 | + PHP_MSHUTDOWN(cgi), | |
2116 | + NULL, | |
2117 | + NULL, | |
2118 | + PHP_MINFO(cgi), | |
2119 | + NO_VERSION_YET, | |
2120 | + STANDARD_MODULE_PROPERTIES | |
2121 | +}; | |
2122 | + | |
2123 | +/* {{{ main | |
2124 | + */ | |
2125 | +int main(int argc, char *argv[]) | |
2126 | +{ | |
2127 | + int free_query_string = 0; | |
2128 | + int exit_status = SUCCESS; | |
2129 | + int c; | |
2130 | + zend_file_handle file_handle = {}; | |
2131 | + int retval; | |
2132 | +/* temporary locals */ | |
2133 | + int orig_optind = php_optind; | |
2134 | + char *orig_optarg = php_optarg; | |
2135 | + int ini_entries_len = 0; | |
2136 | + | |
2137 | +/* end of temporary locals */ | |
2138 | +#ifdef ZTS | |
2139 | + void ***tsrm_ls; | |
2140 | +#endif | |
2141 | + | |
2142 | + int max_requests = 500; | |
2143 | + int requests = 0; | |
2144 | + int fcgi_fd = 0; | |
2145 | + fcgi_request request; | |
2146 | + char *fpm_config = NULL; | |
2147 | + | |
2148 | +#ifdef HAVE_SIGNAL_H | |
2149 | +#if defined(SIGPIPE) && defined(SIG_IGN) | |
2150 | + signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE in standalone mode so | |
2151 | + that sockets created via fsockopen() | |
2152 | + don't kill PHP if the remote site | |
2153 | + closes it. in apache|apxs mode apache | |
2154 | + does that for us! thies@thieso.net | |
2155 | + 20000419 */ | |
2156 | +#endif | |
2157 | +#endif | |
2158 | + | |
2159 | +#ifdef ZTS | |
2160 | + tsrm_startup(1, 1, 0, NULL); | |
2161 | + tsrm_ls = ts_resource(0); | |
2162 | +#endif | |
2163 | + | |
2164 | + sapi_startup(&cgi_sapi_module); | |
2165 | + cgi_sapi_module.php_ini_path_override = NULL; | |
2166 | + | |
2167 | +#ifdef PHP_WIN32 | |
2168 | + _fmode = _O_BINARY; /* sets default for file streams to binary */ | |
2169 | + setmode(_fileno(stdin), O_BINARY); /* make the stdio mode be binary */ | |
2170 | + setmode(_fileno(stdout), O_BINARY); /* make the stdio mode be binary */ | |
2171 | + setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */ | |
2172 | +#endif | |
2173 | + | |
2174 | + while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0)) != -1) { | |
2175 | + switch (c) { | |
2176 | + | |
2177 | + case 'c': | |
2178 | + if (cgi_sapi_module.php_ini_path_override) { | |
2179 | + free(cgi_sapi_module.php_ini_path_override); | |
2180 | + } | |
2181 | + cgi_sapi_module.php_ini_path_override = strdup(php_optarg); | |
2182 | + break; | |
2183 | + | |
2184 | + case 'n': | |
2185 | + cgi_sapi_module.php_ini_ignore = 1; | |
2186 | + break; | |
2187 | + | |
2188 | + case 'C': /* don't chdir to the script directory */ | |
2189 | + SG(options) |= SAPI_OPTION_NO_CHDIR; | |
2190 | + break; | |
2191 | + | |
2192 | + case 'd': { | |
2193 | + /* define ini entries on command line */ | |
2194 | + int len = strlen(php_optarg); | |
2195 | + char *val; | |
2196 | + | |
2197 | + if ((val = strchr(php_optarg, '='))) { | |
2198 | + val++; | |
2199 | + if (!isalnum(*val) && *val != '"' && *val != '\'' && *val != '\0') { | |
2200 | + cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\"\"\n\0")); | |
2201 | + memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, (val - php_optarg)); | |
2202 | + ini_entries_len += (val - php_optarg); | |
2203 | + memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"", 1); | |
2204 | + ini_entries_len++; | |
2205 | + memcpy(cgi_sapi_module.ini_entries + ini_entries_len, val, len - (val - php_optarg)); | |
2206 | + ini_entries_len += len - (val - php_optarg); | |
2207 | + memcpy(cgi_sapi_module.ini_entries + ini_entries_len, "\"\n\0", sizeof("\"\n\0")); | |
2208 | + ini_entries_len += sizeof("\n\0\"") - 2; | |
2209 | + } else { | |
2210 | + cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("\n\0")); | |
2211 | + memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len); | |
2212 | + memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "\n\0", sizeof("\n\0")); | |
2213 | + ini_entries_len += len + sizeof("\n\0") - 2; | |
2214 | + } | |
2215 | + } else { | |
2216 | + cgi_sapi_module.ini_entries = realloc(cgi_sapi_module.ini_entries, ini_entries_len + len + sizeof("=1\n\0")); | |
2217 | + memcpy(cgi_sapi_module.ini_entries + ini_entries_len, php_optarg, len); | |
2218 | + memcpy(cgi_sapi_module.ini_entries + ini_entries_len + len, "=1\n\0", sizeof("=1\n\0")); | |
2219 | + ini_entries_len += len + sizeof("=1\n\0") - 2; | |
2220 | + } | |
2221 | + break; | |
2222 | + } | |
2223 | + | |
2224 | + case 'y': | |
2225 | + fpm_config = php_optarg; | |
2226 | + break; | |
2227 | + | |
2228 | + case 'e': /* enable extended info output */ | |
2229 | + /* CG(extended_info) = 1; */ /* 5_2 */ | |
2230 | + CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO; /* 5_3 */ | |
2231 | + break; | |
2232 | + | |
2233 | + case 'm': /* list compiled in modules */ | |
2234 | + cgi_sapi_module.startup(&cgi_sapi_module); | |
2235 | + php_output_startup(); | |
2236 | + php_output_activate(TSRMLS_C); | |
2237 | + SG(headers_sent) = 1; | |
2238 | + php_printf("[PHP Modules]\n"); | |
2239 | + print_modules(TSRMLS_C); | |
2240 | + php_printf("\n[Zend Modules]\n"); | |
2241 | + print_extensions(TSRMLS_C); | |
2242 | + php_printf("\n"); | |
2243 | + php_end_ob_buffers(1 TSRMLS_CC); | |
2244 | + exit_status = 0; | |
2245 | + goto out; | |
2246 | + | |
2247 | + case 'i': /* php info & quit */ | |
2248 | + cgi_sapi_module.startup(&cgi_sapi_module); | |
2249 | + if (php_request_startup(TSRMLS_C) == FAILURE) { | |
2250 | + SG(server_context) = NULL; | |
2251 | + php_module_shutdown(TSRMLS_C); | |
2252 | + return FAILURE; | |
2253 | + } | |
2254 | + SG(headers_sent) = 1; | |
2255 | + SG(request_info).no_headers = 1; | |
2256 | + php_print_info(0xFFFFFFFF TSRMLS_CC); | |
2257 | + php_request_shutdown((void *) 0); | |
2258 | + exit_status = 0; | |
2259 | + goto out; | |
2260 | + | |
2261 | + case 'h': | |
2262 | + case '?': | |
2263 | + cgi_sapi_module.startup(&cgi_sapi_module); | |
2264 | + php_output_startup(); | |
2265 | + php_output_activate(TSRMLS_C); | |
2266 | + SG(headers_sent) = 1; | |
2267 | + php_cgi_usage(argv[0]); | |
2268 | + php_end_ob_buffers(1 TSRMLS_CC); | |
2269 | + exit_status = 0; | |
2270 | + goto out; | |
2271 | + | |
2272 | + case 'v': /* show php version & quit */ | |
2273 | + cgi_sapi_module.startup(&cgi_sapi_module); | |
2274 | + if (php_request_startup(TSRMLS_C) == FAILURE) { | |
2275 | + SG(server_context) = NULL; | |
2276 | + php_module_shutdown(TSRMLS_C); | |
2277 | + return FAILURE; | |
2278 | + } | |
2279 | + SG(headers_sent) = 1; | |
2280 | + SG(request_info).no_headers = 1; | |
2281 | + | |
2282 | +#if SUHOSIN_PATCH | |
2283 | +#if ZEND_DEBUG | |
2284 | + php_printf("PHP %s with Suhosin-Patch %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, SUHOSIN_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); | |
2285 | +#else | |
2286 | + php_printf("PHP %s with Suhosin-Patch %s (%s) (built: %s %s)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, SUHOSIN_PATCH_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); | |
2287 | +#endif | |
2288 | +#else | |
2289 | +#if ZEND_DEBUG | |
2290 | + php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); | |
2291 | +#else | |
2292 | + php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2009 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version()); | |
2293 | +#endif | |
2294 | +#endif | |
2295 | + php_request_shutdown((void *) 0); | |
2296 | + exit_status = 0; | |
2297 | + goto out; | |
2298 | + | |
2299 | + } | |
2300 | + | |
2301 | + } | |
2302 | + php_optind = orig_optind; | |
2303 | + php_optarg = orig_optarg; | |
2304 | + | |
2305 | +#ifdef ZTS | |
2306 | + SG(request_info).path_translated = NULL; | |
2307 | +#endif | |
2308 | + | |
2309 | + cgi_sapi_module.executable_location = argv[0]; | |
2310 | + | |
2311 | + /* startup after we get the above ini override se we get things right */ | |
2312 | + if (cgi_sapi_module.startup(&cgi_sapi_module) == FAILURE) { | |
2313 | +#ifdef ZTS | |
2314 | + tsrm_shutdown(); | |
2315 | +#endif | |
2316 | + return FAILURE; | |
2317 | + } | |
2318 | + | |
2319 | + if (0 > fpm_init(argc, argv, fpm_config)) { | |
2320 | + return FAILURE; | |
2321 | + } | |
2322 | + | |
2323 | + fcgi_fd = fpm_run(&max_requests); | |
2324 | + | |
2325 | + parent = 0; | |
2326 | + | |
2327 | + fcgi_set_is_fastcgi(1); | |
2328 | + | |
2329 | + /* make php call us to get _ENV vars */ | |
2330 | + php_php_import_environment_variables = php_import_environment_variables; | |
2331 | + php_import_environment_variables = cgi_php_import_environment_variables; | |
2332 | + | |
2333 | + /* library is already initialized, now init our request */ | |
2334 | + fcgi_init_request(&request, fcgi_fd); | |
2335 | + | |
2336 | + zend_first_try { | |
2337 | + | |
2338 | + /* start of FAST CGI loop */ | |
2339 | + /* Initialise FastCGI request structure */ | |
2340 | +#ifdef PHP_WIN32 | |
2341 | + /* attempt to set security impersonation for fastcgi | |
2342 | + will only happen on NT based OS, others will ignore it. */ | |
2343 | + if (fastcgi && CGIG(impersonate)) { | |
2344 | + fcgi_impersonate(); | |
2345 | + } | |
2346 | +#endif | |
2347 | + while (fcgi_accept_request(&request) >= 0) { | |
2348 | + | |
2349 | + request_body_fd = -1; | |
2350 | + | |
2351 | + SG(server_context) = (void *) &request; | |
2352 | + | |
2353 | + init_request_info(TSRMLS_C); | |
2354 | + | |
2355 | + CG(interactive) = 0; | |
2356 | + | |
2357 | + fpm_request_info(); | |
2358 | + | |
2359 | + /* | |
2360 | + we never take stdin if we're (f)cgi, always | |
2361 | + rely on the web server giving us the info | |
2362 | + we need in the environment. | |
2363 | + */ | |
2364 | + if (SG(request_info).path_translated) { | |
2365 | + file_handle.type = ZEND_HANDLE_FILENAME; | |
2366 | + file_handle.filename = SG(request_info).path_translated; | |
2367 | + file_handle.handle.fp = NULL; | |
2368 | + } | |
2369 | + file_handle.opened_path = NULL; | |
2370 | + file_handle.free_filename = 0; | |
2371 | + | |
2372 | + /* request startup only after we've done all we can to | |
2373 | + get path_translated */ | |
2374 | + if (php_request_startup(TSRMLS_C) == FAILURE) { | |
2375 | + fcgi_finish_request(&request); | |
2376 | + SG(server_context) = NULL; | |
2377 | + php_module_shutdown(TSRMLS_C); | |
2378 | + return FAILURE; | |
2379 | + } | |
2380 | + | |
2381 | + /* | |
2382 | + at this point path_translated will be set if: | |
2383 | + 1. we are running from shell and got filename was there | |
2384 | + 2. we are running as cgi or fastcgi | |
2385 | + */ | |
2386 | + retval = FAILURE; | |
2387 | + if (SG(request_info).path_translated) { | |
2388 | + if (!php_check_open_basedir(SG(request_info).path_translated TSRMLS_CC)) { | |
2389 | + retval = php_fopen_primary_script(&file_handle TSRMLS_CC); | |
2390 | + } | |
2391 | + } | |
2392 | + /* | |
2393 | + if we are unable to open path_translated and we are not | |
2394 | + running from shell (so fp == NULL), then fail. | |
2395 | + */ | |
2396 | + if (retval == FAILURE && file_handle.handle.fp == NULL) { | |
2397 | + if (errno == EACCES) { | |
2398 | + SG(sapi_headers).http_response_code = 403; | |
2399 | + PUTS("Access denied.\n"); | |
2400 | + } else { | |
2401 | + SG(sapi_headers).http_response_code = 404; | |
2402 | + PUTS("No input file specified.\n"); | |
2403 | + } | |
2404 | + /* we want to serve more requests if this is fastcgi | |
2405 | + so cleanup and continue, request shutdown is | |
2406 | + handled later */ | |
2407 | + goto fastcgi_request_done; | |
2408 | + | |
2409 | + STR_FREE(SG(request_info).path_translated); | |
2410 | + | |
2411 | + if (free_query_string && SG(request_info).query_string) { | |
2412 | + free(SG(request_info).query_string); | |
2413 | + SG(request_info).query_string = NULL; | |
2414 | + } | |
2415 | + | |
2416 | + php_request_shutdown((void *) 0); | |
2417 | + SG(server_context) = NULL; | |
2418 | + php_module_shutdown(TSRMLS_C); | |
2419 | + sapi_shutdown(); | |
2420 | +#ifdef ZTS | |
2421 | + tsrm_shutdown(); | |
2422 | +#endif | |
2423 | + return FAILURE; | |
2424 | + } | |
2425 | + | |
2426 | + fpm_request_executing(); | |
2427 | + | |
2428 | + php_execute_script(&file_handle TSRMLS_CC); | |
2429 | + | |
2430 | +fastcgi_request_done: | |
2431 | + | |
2432 | + if (request_body_fd != -1) close(request_body_fd); | |
2433 | + | |
2434 | + request_body_fd = -2; | |
2435 | + | |
2436 | + { | |
2437 | + char *path_translated; | |
2438 | + | |
2439 | + /* Go through this trouble so that the memory manager doesn't warn | |
2440 | + * about SG(request_info).path_translated leaking | |
2441 | + */ | |
2442 | + if (SG(request_info).path_translated) { | |
2443 | + path_translated = strdup(SG(request_info).path_translated); | |
2444 | + STR_FREE(SG(request_info).path_translated); | |
2445 | + SG(request_info).path_translated = path_translated; | |
2446 | + } | |
2447 | + | |
2448 | + if (EG(exit_status) == 255) { | |
2449 | + if (CGIG(error_header) && *CGIG(error_header)) { | |
2450 | + sapi_header_line ctr = {0}; | |
2451 | + | |
2452 | + ctr.line = CGIG(error_header); | |
2453 | + ctr.line_len = strlen(CGIG(error_header)); | |
2454 | + sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); | |
2455 | + } | |
2456 | + } | |
2457 | + | |
2458 | + php_request_shutdown((void *) 0); | |
2459 | + if (exit_status == 0) { | |
2460 | + exit_status = EG(exit_status); | |
2461 | + } | |
2462 | + | |
2463 | + if (SG(request_info).path_translated) { | |
2464 | + free(SG(request_info).path_translated); | |
2465 | + SG(request_info).path_translated = NULL; | |
2466 | + } | |
2467 | + if (free_query_string && SG(request_info).query_string) { | |
2468 | + free(SG(request_info).query_string); | |
2469 | + SG(request_info).query_string = NULL; | |
2470 | + } | |
2471 | + | |
2472 | + } | |
2473 | + | |
2474 | + requests++; | |
2475 | + if (max_requests && (requests == max_requests)) { | |
2476 | + fcgi_finish_request(&request); | |
2477 | + break; | |
2478 | + } | |
2479 | + | |
2480 | + /* end of fastcgi loop */ | |
2481 | + } | |
2482 | + | |
2483 | + fcgi_shutdown(); | |
2484 | + | |
2485 | + if (fcgi_in_shutdown() || /* graceful shutdown by a signal */ | |
2486 | + (max_requests && (requests == max_requests)) /* we were told to process max_requests and we are done */ | |
2487 | + ) { | |
2488 | + exit_status = 0; | |
2489 | + } | |
2490 | + else { | |
2491 | + exit_status = 255; | |
2492 | + } | |
2493 | + | |
2494 | + if (cgi_sapi_module.php_ini_path_override) { | |
2495 | + free(cgi_sapi_module.php_ini_path_override); | |
2496 | + } | |
2497 | + if (cgi_sapi_module.ini_entries) { | |
2498 | + free(cgi_sapi_module.ini_entries); | |
2499 | + } | |
2500 | + } zend_catch { | |
2501 | + exit_status = 255; | |
2502 | + } zend_end_try(); | |
2503 | + | |
2504 | +out: | |
2505 | + | |
2506 | + SG(server_context) = NULL; | |
2507 | + php_module_shutdown(TSRMLS_C); | |
2508 | + sapi_shutdown(); | |
2509 | + | |
2510 | +#ifdef ZTS | |
2511 | + /*tsrm_shutdown();*/ | |
2512 | +#endif | |
2513 | + | |
2514 | +#if defined(PHP_WIN32) && ZEND_DEBUG && 0 | |
2515 | + _CrtDumpMemoryLeaks(); | |
2516 | +#endif | |
2517 | + | |
2518 | + return exit_status; | |
2519 | +} | |
2520 | +/* }}} */ | |
2521 | + | |
2522 | +/* | |
2523 | + * Local variables: | |
2524 | + * tab-width: 4 | |
2525 | + * c-basic-offset: 4 | |
2526 | + * End: | |
2527 | + * vim600: sw=4 ts=4 fdm=marker | |
2528 | + * vim<600: sw=4 ts=4 | |
2529 | + */ | |
2530 | diff -Naur php-src-vanilla/sapi/fpm/cgi/CREDITS php-src/sapi/fpm/cgi/CREDITS | |
2531 | --- php-src-vanilla/sapi/fpm/cgi/CREDITS 1970-01-01 01:00:00.000000000 +0100 | |
2532 | +++ php-src/sapi/fpm/cgi/CREDITS 2009-10-18 21:05:39.302497288 +0100 | |
2533 | @@ -0,0 +1,2 @@ | |
2534 | +CGI / FastCGI | |
2535 | +Rasmus Lerdorf, Stig Bakken, Shane Caraveo, Dmitry Stogov | |
2536 | diff -Naur php-src-vanilla/sapi/fpm/cgi/fastcgi.c php-src/sapi/fpm/cgi/fastcgi.c | |
2537 | --- php-src-vanilla/sapi/fpm/cgi/fastcgi.c 1970-01-01 01:00:00.000000000 +0100 | |
2538 | +++ php-src/sapi/fpm/cgi/fastcgi.c 2009-10-18 21:05:39.302497288 +0100 | |
2539 | @@ -0,0 +1,1319 @@ | |
2540 | +/* | |
2541 | + +----------------------------------------------------------------------+ | |
2542 | + | PHP Version 5 | | |
2543 | + +----------------------------------------------------------------------+ | |
2544 | + | Copyright (c) 1997-2008 The PHP Group | | |
2545 | + +----------------------------------------------------------------------+ | |
2546 | + | This source file is subject to version 3.01 of the PHP license, | | |
2547 | + | that is bundled with this package in the file LICENSE, and is | | |
2548 | + | available through the world-wide-web at the following url: | | |
2549 | + | http://www.php.net/license/3_01.txt | | |
2550 | + | If you did not receive a copy of the PHP license and are unable to | | |
2551 | + | obtain it through the world-wide-web, please send a note to | | |
2552 | + | license@php.net so we can mail you a copy immediately. | | |
2553 | + +----------------------------------------------------------------------+ | |
2554 | + | Authors: Dmitry Stogov <dmitry@zend.com> | | |
2555 | + +----------------------------------------------------------------------+ | |
2556 | +*/ | |
2557 | + | |
2558 | +/* $Id$ */ | |
2559 | + | |
2560 | +#include <php.h> | |
2561 | +#include "fastcgi.h" | |
2562 | + | |
2563 | +#include <string.h> | |
2564 | +#include <stdlib.h> | |
2565 | +#include <stdio.h> | |
2566 | +#include <stdarg.h> | |
2567 | +#include <errno.h> | |
2568 | + | |
2569 | +#ifdef FPM_AUTOCONFIG_H | |
2570 | +#include <fpm_autoconfig.h> | |
2571 | +#else | |
2572 | +#include <php_config.h> | |
2573 | +#endif | |
2574 | +#include <fpm/fpm.h> | |
2575 | +#include <fpm/fpm_request.h> | |
2576 | + | |
2577 | +#ifdef _WIN32 | |
2578 | + | |
2579 | +#include <windows.h> | |
2580 | + | |
2581 | + typedef unsigned int in_addr_t; | |
2582 | + | |
2583 | + struct sockaddr_un { | |
2584 | + short sun_family; | |
2585 | + char sun_path[MAXPATHLEN]; | |
2586 | + }; | |
2587 | + | |
2588 | + static HANDLE fcgi_accept_mutex = INVALID_HANDLE_VALUE; | |
2589 | + static int is_impersonate = 0; | |
2590 | + | |
2591 | +#define FCGI_LOCK(fd) \ | |
2592 | + if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ | |
2593 | + DWORD ret; \ | |
2594 | + while ((ret = WaitForSingleObject(fcgi_accept_mutex, 1000)) == WAIT_TIMEOUT) { \ | |
2595 | + if (in_shutdown) return -1; \ | |
2596 | + } \ | |
2597 | + if (ret == WAIT_FAILED) { \ | |
2598 | + fprintf(stderr, "WaitForSingleObject() failed\n"); \ | |
2599 | + return -1; \ | |
2600 | + } \ | |
2601 | + } | |
2602 | + | |
2603 | +#define FCGI_UNLOCK(fd) \ | |
2604 | + if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \ | |
2605 | + ReleaseMutex(fcgi_accept_mutex); \ | |
2606 | + } | |
2607 | + | |
2608 | +#else | |
2609 | + | |
2610 | +# include <sys/types.h> | |
2611 | +# include <sys/stat.h> | |
2612 | +# include <unistd.h> | |
2613 | +# include <fcntl.h> | |
2614 | +# include <sys/socket.h> | |
2615 | +# include <sys/un.h> | |
2616 | +# include <netinet/in.h> | |
2617 | +# include <arpa/inet.h> | |
2618 | +# include <netdb.h> | |
2619 | +# include <signal.h> | |
2620 | + | |
2621 | +# define closesocket(s) close(s) | |
2622 | + | |
2623 | +# if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL) | |
2624 | +# include <sys/poll.h> | |
2625 | +# endif | |
2626 | +# if defined(HAVE_SYS_SELECT_H) | |
2627 | +# include <sys/select.h> | |
2628 | +# endif | |
2629 | + | |
2630 | +#ifndef INADDR_NONE | |
2631 | +#define INADDR_NONE ((unsigned long) -1) | |
2632 | +#endif | |
2633 | + | |
2634 | +# ifndef HAVE_SOCKLEN_T | |
2635 | + typedef unsigned int socklen_t; | |
2636 | +# endif | |
2637 | + | |
2638 | +# ifdef USE_LOCKING | |
2639 | +# define FCGI_LOCK(fd) \ | |
2640 | + do { \ | |
2641 | + struct flock lock; \ | |
2642 | + lock.l_type = F_WRLCK; \ | |
2643 | + lock.l_start = 0; \ | |
2644 | + lock.l_whence = SEEK_SET; \ | |
2645 | + lock.l_len = 0; \ | |
2646 | + if (fcntl(fd, F_SETLKW, &lock) != -1) { \ | |
2647 | + break; \ | |
2648 | + } else if (errno != EINTR || in_shutdown) { \ | |
2649 | + return -1; \ | |
2650 | + } \ | |
2651 | + } while (1) | |
2652 | + | |
2653 | +# define FCGI_UNLOCK(fd) \ | |
2654 | + do { \ | |
2655 | + int orig_errno = errno; \ | |
2656 | + while (1) { \ | |
2657 | + struct flock lock; \ | |
2658 | + lock.l_type = F_UNLCK; \ | |
2659 | + lock.l_start = 0; \ | |
2660 | + lock.l_whence = SEEK_SET; \ | |
2661 | + lock.l_len = 0; \ | |
2662 | + if (fcntl(fd, F_SETLK, &lock) != -1) { \ | |
2663 | + break; \ | |
2664 | + } else if (errno != EINTR) { \ | |
2665 | + return -1; \ | |
2666 | + } \ | |
2667 | + } \ | |
2668 | + errno = orig_errno; \ | |
2669 | + } while (0) | |
2670 | +# else | |
2671 | +# define FCGI_LOCK(fd) | |
2672 | +# define FCGI_UNLOCK(fd) | |
2673 | +# endif | |
2674 | + | |
2675 | +#endif | |
2676 | + | |
2677 | +typedef union _sa_t { | |
2678 | + struct sockaddr sa; | |
2679 | + struct sockaddr_un sa_unix; | |
2680 | + struct sockaddr_in sa_inet; | |
2681 | +} sa_t; | |
2682 | + | |
2683 | +static HashTable *fcgi_mgmt_vars; | |
2684 | + | |
2685 | +static int is_initialized = 0; | |
2686 | +static int is_fastcgi = 0; | |
2687 | +static int in_shutdown = 0; | |
2688 | +static in_addr_t *allowed_clients = NULL; | |
2689 | + | |
2690 | +#ifdef _WIN32 | |
2691 | + | |
2692 | +static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg) | |
2693 | +{ | |
2694 | + HANDLE shutdown_event = (HANDLE) arg; | |
2695 | + WaitForSingleObject(shutdown_event, INFINITE); | |
2696 | + in_shutdown = 1; | |
2697 | + return 0; | |
2698 | +} | |
2699 | + | |
2700 | +#else | |
2701 | + | |
2702 | +static void fcgi_signal_handler(int signo) | |
2703 | +{ | |
2704 | + if (signo == SIGUSR1 || signo == SIGTERM) { | |
2705 | + in_shutdown = 1; | |
2706 | + } | |
2707 | +} | |
2708 | + | |
2709 | +static void fcgi_setup_signals(void) | |
2710 | +{ | |
2711 | + struct sigaction new_sa, old_sa; | |
2712 | + | |
2713 | + sigemptyset(&new_sa.sa_mask); | |
2714 | + new_sa.sa_flags = 0; | |
2715 | + new_sa.sa_handler = fcgi_signal_handler; | |
2716 | + sigaction(SIGUSR1, &new_sa, NULL); | |
2717 | + sigaction(SIGTERM, &new_sa, NULL); | |
2718 | + sigaction(SIGPIPE, NULL, &old_sa); | |
2719 | + if (old_sa.sa_handler == SIG_DFL) { | |
2720 | + sigaction(SIGPIPE, &new_sa, NULL); | |
2721 | + } | |
2722 | +} | |
2723 | +#endif | |
2724 | + | |
2725 | +int fcgi_in_shutdown(void) | |
2726 | +{ | |
2727 | + return in_shutdown; | |
2728 | +} | |
2729 | + | |
2730 | +int fcgi_init(void) | |
2731 | +{ | |
2732 | + if (!is_initialized) { | |
2733 | + fcgi_mgmt_vars = pemalloc(sizeof(HashTable), 1); | |
2734 | + zend_hash_init(fcgi_mgmt_vars, 3, NULL, fcgi_free_mgmt_var_cb, 1); | |
2735 | + fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1); | |
2736 | + fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1); | |
2737 | + fcgi_set_mgmt_var("FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS")-1, "0", sizeof("0")-1); | |
2738 | +#ifdef _WIN32 | |
2739 | +# if 0 | |
2740 | + /* TODO: Support for TCP sockets */ | |
2741 | + WSADATA wsaData; | |
2742 | + | |
2743 | + if (WSAStartup(MAKEWORD(2,0), &wsaData)) { | |
2744 | + fprintf(stderr, "Error starting Windows Sockets. Error: %d", WSAGetLastError()); | |
2745 | + return 0; | |
2746 | + } | |
2747 | +# endif | |
2748 | + is_initialized = 1; | |
2749 | + | |
2750 | + if ((GetStdHandle(STD_OUTPUT_HANDLE) == INVALID_HANDLE_VALUE) && | |
2751 | + (GetStdHandle(STD_ERROR_HANDLE) == INVALID_HANDLE_VALUE) && | |
2752 | + (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)) { | |
2753 | + char *str; | |
2754 | + DWORD pipe_mode = PIPE_READMODE_BYTE | PIPE_WAIT; | |
2755 | + HANDLE pipe = GetStdHandle(STD_INPUT_HANDLE); | |
2756 | + | |
2757 | + SetNamedPipeHandleState(pipe, &pipe_mode, NULL, NULL); | |
2758 | + | |
2759 | + str = getenv("_FCGI_SHUTDOWN_EVENT_"); | |
2760 | + if (str != NULL) { | |
2761 | + HANDLE shutdown_event = (HANDLE) atoi(str); | |
2762 | + if (!CreateThread(NULL, 0, fcgi_shutdown_thread, | |
2763 | + shutdown_event, 0, NULL)) { | |
2764 | + return -1; | |
2765 | + } | |
2766 | + } | |
2767 | + str = getenv("_FCGI_MUTEX_"); | |
2768 | + if (str != NULL) { | |
2769 | + fcgi_accept_mutex = (HANDLE) atoi(str); | |
2770 | + } | |
2771 | + return is_fastcgi = 1; | |
2772 | + } else { | |
2773 | + return is_fastcgi = 0; | |
2774 | + } | |
2775 | +#else | |
2776 | + sa_t sa; | |
2777 | + socklen_t len = sizeof(sa); | |
2778 | + | |
2779 | + is_initialized = 1; | |
2780 | + errno = 0; | |
2781 | + if (getpeername(0, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) { | |
2782 | + fcgi_setup_signals(); | |
2783 | + return is_fastcgi = 1; | |
2784 | + } else { | |
2785 | + return is_fastcgi = 0; | |
2786 | + } | |
2787 | + | |
2788 | + fcgi_set_allowed_clients(getenv("FCGI_WEB_SERVER_ADDRS")); | |
2789 | +#endif | |
2790 | + } | |
2791 | + return is_fastcgi; | |
2792 | +} | |
2793 | + | |
2794 | + | |
2795 | +int fcgi_is_fastcgi(void) | |
2796 | +{ | |
2797 | + if (!is_initialized) { | |
2798 | + return fcgi_init(); | |
2799 | + } else { | |
2800 | + return is_fastcgi; | |
2801 | + } | |
2802 | +} | |
2803 | + | |
2804 | +void fcgi_set_is_fastcgi(int new_value) | |
2805 | +{ | |
2806 | + is_fastcgi = new_value; | |
2807 | +} | |
2808 | + | |
2809 | +void fcgi_set_in_shutdown(int new_value) | |
2810 | +{ | |
2811 | + in_shutdown = new_value; | |
2812 | +} | |
2813 | + | |
2814 | +void fcgi_shutdown(void) | |
2815 | +{ | |
2816 | + if (is_initialized) { | |
2817 | + zend_hash_destroy(fcgi_mgmt_vars); | |
2818 | + pefree(fcgi_mgmt_vars, 1); | |
2819 | + } | |
2820 | + is_fastcgi = 0; | |
2821 | + | |
2822 | + if (allowed_clients) { | |
2823 | + free(allowed_clients); | |
2824 | + allowed_clients = 0; | |
2825 | + } | |
2826 | +} | |
2827 | + | |
2828 | +#ifdef _WIN32 | |
2829 | +/* Do some black magic with the NT security API. | |
2830 | + * We prepare a DACL (Discretionary Access Control List) so that | |
2831 | + * we, the creator, are allowed all access, while "Everyone Else" | |
2832 | + * is only allowed to read and write to the pipe. | |
2833 | + * This avoids security issues on shared hosts where a luser messes | |
2834 | + * with the lower-level pipe settings and screws up the FastCGI service. | |
2835 | + */ | |
2836 | +static PACL prepare_named_pipe_acl(PSECURITY_DESCRIPTOR sd, LPSECURITY_ATTRIBUTES sa) | |
2837 | +{ | |
2838 | + DWORD req_acl_size; | |
2839 | + char everyone_buf[32], owner_buf[32]; | |
2840 | + PSID sid_everyone, sid_owner; | |
2841 | + SID_IDENTIFIER_AUTHORITY | |
2842 | + siaWorld = SECURITY_WORLD_SID_AUTHORITY, | |
2843 | + siaCreator = SECURITY_CREATOR_SID_AUTHORITY; | |
2844 | + PACL acl; | |
2845 | + | |
2846 | + sid_everyone = (PSID)&everyone_buf; | |
2847 | + sid_owner = (PSID)&owner_buf; | |
2848 | + | |
2849 | + req_acl_size = sizeof(ACL) + | |
2850 | + (2 * ((sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) + GetSidLengthRequired(1))); | |
2851 | + | |
2852 | + acl = malloc(req_acl_size); | |
2853 | + | |
2854 | + if (acl == NULL) { | |
2855 | + return NULL; | |
2856 | + } | |
2857 | + | |
2858 | + if (!InitializeSid(sid_everyone, &siaWorld, 1)) { | |
2859 | + goto out_fail; | |
2860 | + } | |
2861 | + *GetSidSubAuthority(sid_everyone, 0) = SECURITY_WORLD_RID; | |
2862 | + | |
2863 | + if (!InitializeSid(sid_owner, &siaCreator, 1)) { | |
2864 | + goto out_fail; | |
2865 | + } | |
2866 | + *GetSidSubAuthority(sid_owner, 0) = SECURITY_CREATOR_OWNER_RID; | |
2867 | + | |
2868 | + if (!InitializeAcl(acl, req_acl_size, ACL_REVISION)) { | |
2869 | + goto out_fail; | |
2870 | + } | |
2871 | + | |
2872 | + if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_GENERIC_READ | FILE_GENERIC_WRITE, sid_everyone)) { | |
2873 | + goto out_fail; | |
2874 | + } | |
2875 | + | |
2876 | + if (!AddAccessAllowedAce(acl, ACL_REVISION, FILE_ALL_ACCESS, sid_owner)) { | |
2877 | + goto out_fail; | |
2878 | + } | |
2879 | + | |
2880 | + if (!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)) { | |
2881 | + goto out_fail; | |
2882 | + } | |
2883 | + | |
2884 | + if (!SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE)) { | |
2885 | + goto out_fail; | |
2886 | + } | |
2887 | + | |
2888 | + sa->lpSecurityDescriptor = sd; | |
2889 | + | |
2890 | + return acl; | |
2891 | + | |
2892 | +out_fail: | |
2893 | + free(acl); | |
2894 | + return NULL; | |
2895 | +} | |
2896 | +#endif | |
2897 | + | |
2898 | +void fcgi_set_allowed_clients(char *ip) | |
2899 | +{ | |
2900 | + char *cur, *end; | |
2901 | + int n; | |
2902 | + | |
2903 | + if (ip) { | |
2904 | + ip = strdup(ip); | |
2905 | + cur = ip; | |
2906 | + n = 0; | |
2907 | + while (*cur) { | |
2908 | + if (*cur == ',') n++; | |
2909 | + cur++; | |
2910 | + } | |
2911 | + if (allowed_clients) free(allowed_clients); | |
2912 | + allowed_clients = malloc(sizeof(in_addr_t) * (n+2)); | |
2913 | + n = 0; | |
2914 | + cur = ip; | |
2915 | + while (cur) { | |
2916 | + end = strchr(cur, ','); | |
2917 | + if (end) { | |
2918 | + *end = 0; | |
2919 | + end++; | |
2920 | + } | |
2921 | + allowed_clients[n] = inet_addr(cur); | |
2922 | + if (allowed_clients[n] == INADDR_NONE) { | |
2923 | + fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur); | |
2924 | + } | |
2925 | + n++; | |
2926 | + cur = end; | |
2927 | + } | |
2928 | + allowed_clients[n] = INADDR_NONE; | |
2929 | + free(ip); | |
2930 | + } | |
2931 | +} | |
2932 | + | |
2933 | +static int is_port_number(const char *bindpath) | |
2934 | +{ | |
2935 | + while (*bindpath) { | |
2936 | + if (*bindpath < '0' || *bindpath > '9') { | |
2937 | + return 0; | |
2938 | + } | |
2939 | + bindpath++; | |
2940 | + } | |
2941 | + return 1; | |
2942 | +} | |
2943 | + | |
2944 | +int fcgi_listen(const char *path, int backlog) | |
2945 | +{ | |
2946 | + char *s; | |
2947 | + int tcp = 0; | |
2948 | + char host[MAXPATHLEN]; | |
2949 | + short port = 0; | |
2950 | + int listen_socket; | |
2951 | + sa_t sa; | |
2952 | + socklen_t sock_len; | |
2953 | +#ifdef SO_REUSEADDR | |
2954 | +# ifdef _WIN32 | |
2955 | + BOOL reuse = 1; | |
2956 | +# else | |
2957 | + int reuse = 1; | |
2958 | +# endif | |
2959 | +#endif | |
2960 | + | |
2961 | + if ((s = strchr(path, ':'))) { | |
2962 | + port = atoi(s+1); | |
2963 | + if (port != 0 && (s-path) < MAXPATHLEN) { | |
2964 | + strncpy(host, path, s-path); | |
2965 | + host[s-path] = '\0'; | |
2966 | + tcp = 1; | |
2967 | + } | |
2968 | + } else if (is_port_number(path)) { | |
2969 | + port = atoi(path); | |
2970 | + if (port != 0) { | |
2971 | + host[0] = '\0'; | |
2972 | + tcp = 1; | |
2973 | + } | |
2974 | + } | |
2975 | + | |
2976 | + /* Prepare socket address */ | |
2977 | + if (tcp) { | |
2978 | + memset(&sa.sa_inet, 0, sizeof(sa.sa_inet)); | |
2979 | + sa.sa_inet.sin_family = AF_INET; | |
2980 | + sa.sa_inet.sin_port = htons(port); | |
2981 | + sock_len = sizeof(sa.sa_inet); | |
2982 | + | |
2983 | + if (!*host || !strncmp(host, "*", sizeof("*")-1)) { | |
2984 | + sa.sa_inet.sin_addr.s_addr = htonl(INADDR_ANY); | |
2985 | + } else { | |
2986 | + sa.sa_inet.sin_addr.s_addr = inet_addr(host); | |
2987 | + if (sa.sa_inet.sin_addr.s_addr == INADDR_NONE) { | |
2988 | + struct hostent *hep; | |
2989 | + | |
2990 | + hep = gethostbyname(host); | |
2991 | + if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) { | |
2992 | + fprintf(stderr, "Cannot resolve host name '%s'!\n", host); | |
2993 | + return -1; | |
2994 | + } else if (hep->h_addr_list[1]) { | |
2995 | + fprintf(stderr, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host); | |
2996 | + return -1; | |
2997 | + } | |
2998 | + sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr; | |
2999 | + } | |
3000 | + } | |
3001 | + } else { | |
3002 | +#ifdef _WIN32 | |
3003 | + SECURITY_DESCRIPTOR sd; | |
3004 | + SECURITY_ATTRIBUTES sa; | |
3005 | + PACL acl; | |
3006 | + HANDLE namedPipe; | |
3007 | + | |
3008 | + memset(&sa, 0, sizeof(sa)); | |
3009 | + sa.nLength = sizeof(sa); | |
3010 | + sa.bInheritHandle = FALSE; | |
3011 | + acl = prepare_named_pipe_acl(&sd, &sa); | |
3012 | + | |
3013 | + namedPipe = CreateNamedPipe(path, | |
3014 | + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, | |
3015 | + PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_READMODE_BYTE, | |
3016 | + PIPE_UNLIMITED_INSTANCES, | |
3017 | + 8192, 8192, 0, &sa); | |
3018 | + if (namedPipe == INVALID_HANDLE_VALUE) { | |
3019 | + return -1; | |
3020 | + } | |
3021 | + listen_socket = _open_osfhandle((long)namedPipe, 0); | |
3022 | + if (!is_initialized) { | |
3023 | + fcgi_init(); | |
3024 | + } | |
3025 | + is_fastcgi = 1; | |
3026 | + return listen_socket; | |
3027 | + | |
3028 | +#else | |
3029 | + int path_len = strlen(path); | |
3030 | + | |
3031 | + if (path_len >= sizeof(sa.sa_unix.sun_path)) { | |
3032 | + fprintf(stderr, "Listening socket's path name is too long.\n"); | |
3033 | + return -1; | |
3034 | + } | |
3035 | + | |
3036 | + memset(&sa.sa_unix, 0, sizeof(sa.sa_unix)); | |
3037 | + sa.sa_unix.sun_family = AF_UNIX; | |
3038 | + memcpy(sa.sa_unix.sun_path, path, path_len + 1); | |
3039 | + sock_len = (size_t)(((struct sockaddr_un *)0)->sun_path) + path_len; | |
3040 | +#ifdef HAVE_SOCKADDR_UN_SUN_LEN | |
3041 | + sa.sa_unix.sun_len = sock_len; | |
3042 | +#endif | |
3043 | + unlink(path); | |
3044 | +#endif | |
3045 | + } | |
3046 | + | |
3047 | + /* Create, bind socket and start listen on it */ | |
3048 | + if ((listen_socket = socket(sa.sa.sa_family, SOCK_STREAM, 0)) < 0 || | |
3049 | +#ifdef SO_REUSEADDR | |
3050 | + setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0 || | |
3051 | +#endif | |
3052 | + bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 || | |
3053 | + listen(listen_socket, backlog) < 0) { | |
3054 | + | |
3055 | + fprintf(stderr, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno)); | |
3056 | + return -1; | |
3057 | + } | |
3058 | + | |
3059 | + if (!tcp) { | |
3060 | + chmod(path, 0777); | |
3061 | + } | |
3062 | + | |
3063 | + if (!is_initialized) { | |
3064 | + fcgi_init(); | |
3065 | + } | |
3066 | + is_fastcgi = 1; | |
3067 | + | |
3068 | +#ifdef _WIN32 | |
3069 | + if (tcp) { | |
3070 | + listen_socket = _open_osfhandle((long)listen_socket, 0); | |
3071 | + } | |
3072 | +#else | |
3073 | + fcgi_setup_signals(); | |
3074 | +#endif | |
3075 | + return listen_socket; | |
3076 | +} | |
3077 | + | |
3078 | +void fcgi_init_request(fcgi_request *req, int listen_socket) | |
3079 | +{ | |
3080 | + memset(req, 0, sizeof(fcgi_request)); | |
3081 | + req->listen_socket = listen_socket; | |
3082 | + req->fd = -1; | |
3083 | + req->id = -1; | |
3084 | + | |
3085 | + req->in_len = 0; | |
3086 | + req->in_pad = 0; | |
3087 | + | |
3088 | + req->out_hdr = NULL; | |
3089 | + req->out_pos = req->out_buf; | |
3090 | + | |
3091 | +#ifdef _WIN32 | |
3092 | + req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL); | |
3093 | +#endif | |
3094 | +} | |
3095 | + | |
3096 | +static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count) | |
3097 | +{ | |
3098 | + int ret; | |
3099 | + size_t n = 0; | |
3100 | + | |
3101 | + do { | |
3102 | + errno = 0; | |
3103 | +#ifdef _WIN32 | |
3104 | + if (!req->tcp) { | |
3105 | + ret = write(req->fd, ((char*)buf)+n, count-n); | |
3106 | + } else { | |
3107 | + ret = send(req->fd, ((char*)buf)+n, count-n, 0); | |
3108 | + if (ret <= 0) { | |
3109 | + errno = WSAGetLastError(); | |
3110 | + } | |
3111 | + } | |
3112 | +#else | |
3113 | + ret = write(req->fd, ((char*)buf)+n, count-n); | |
3114 | +#endif | |
3115 | + if (ret > 0) { | |
3116 | + n += ret; | |
3117 | + } else if (ret <= 0 && errno != 0 && errno != EINTR) { | |
3118 | + return ret; | |
3119 | + } | |
3120 | + } while (n != count); | |
3121 | + return n; | |
3122 | +} | |
3123 | + | |
3124 | +static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count) | |
3125 | +{ | |
3126 | + int ret; | |
3127 | + size_t n = 0; | |
3128 | + | |
3129 | + do { | |
3130 | + errno = 0; | |
3131 | +#ifdef _WIN32 | |
3132 | + if (!req->tcp) { | |
3133 | + ret = read(req->fd, ((char*)buf)+n, count-n); | |
3134 | + } else { | |
3135 | + ret = recv(req->fd, ((char*)buf)+n, count-n, 0); | |
3136 | + if (ret <= 0) { | |
3137 | + errno = WSAGetLastError(); | |
3138 | + } | |
3139 | + } | |
3140 | +#else | |
3141 | + ret = read(req->fd, ((char*)buf)+n, count-n); | |
3142 | +#endif | |
3143 | + if (ret > 0) { | |
3144 | + n += ret; | |
3145 | + } else if (ret == 0 && errno == 0) { | |
3146 | + return n; | |
3147 | + } else if (ret <= 0 && errno != 0 && errno != EINTR) { | |
3148 | + return ret; | |
3149 | + } | |
3150 | + } while (n != count); | |
3151 | + return n; | |
3152 | +} | |
3153 | + | |
3154 | +static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int req_id, int len) | |
3155 | +{ | |
3156 | + int pad = ((len + 7) & ~7) - len; | |
3157 | + | |
3158 | + hdr->contentLengthB0 = (unsigned char)(len & 0xff); | |
3159 | + hdr->contentLengthB1 = (unsigned char)((len >> 8) & 0xff); | |
3160 | + hdr->paddingLength = (unsigned char)pad; | |
3161 | + hdr->requestIdB0 = (unsigned char)(req_id & 0xff); | |
3162 | + hdr->requestIdB1 = (unsigned char)((req_id >> 8) & 0xff); | |
3163 | + hdr->reserved = 0; | |
3164 | + hdr->type = type; | |
3165 | + hdr->version = FCGI_VERSION_1; | |
3166 | + if (pad) { | |
3167 | + memset(((unsigned char*)hdr) + sizeof(fcgi_header) + len, 0, pad); | |
3168 | + } | |
3169 | + return pad; | |
3170 | +} | |
3171 | + | |
3172 | +static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end) | |
3173 | +{ | |
3174 | + char buf[128]; | |
3175 | + char *tmp = buf; | |
3176 | + int buf_size = sizeof(buf); | |
3177 | + int name_len, val_len; | |
3178 | + char *s; | |
3179 | + int ret = 1; | |
3180 | + | |
3181 | + while (p < end) { | |
3182 | + name_len = *p++; | |
3183 | + if (name_len >= 128) { | |
3184 | + name_len = ((name_len & 0x7f) << 24); | |
3185 | + name_len |= (*p++ << 16); | |
3186 | + name_len |= (*p++ << 8); | |
3187 | + name_len |= *p++; | |
3188 | + } | |
3189 | + val_len = *p++; | |
3190 | + if (val_len >= 128) { | |
3191 | + val_len = ((val_len & 0x7f) << 24); | |
3192 | + val_len |= (*p++ << 16); | |
3193 | + val_len |= (*p++ << 8); | |
3194 | + val_len |= *p++; | |
3195 | + } | |
3196 | + if (name_len + val_len < 0 || | |
3197 | + name_len + val_len > end - p) { | |
3198 | + /* Malformated request */ | |
3199 | + ret = 0; | |
3200 | + break; | |
3201 | + } | |
3202 | + if (name_len+1 >= buf_size) { | |
3203 | + buf_size = name_len + 64; | |
3204 | + tmp = (tmp == buf ? emalloc(buf_size): erealloc(tmp, buf_size)); | |
3205 | + } | |
3206 | + memcpy(tmp, p, name_len); | |
3207 | + tmp[name_len] = 0; | |
3208 | + s = zend_strndup((char*)p + name_len, val_len); | |
3209 | + zend_hash_update(&req->env, tmp, name_len+1, &s, sizeof(char*), NULL); | |
3210 | + p += name_len + val_len; | |
3211 | + } | |
3212 | + if (tmp != buf && tmp != NULL) { | |
3213 | + efree(tmp); | |
3214 | + } | |
3215 | + return ret; | |
3216 | +} | |
3217 | + | |
3218 | +static void fcgi_free_var(char **s) | |
3219 | +{ | |
3220 | + free(*s); | |
3221 | +} | |
3222 | + | |
3223 | +static int fcgi_read_request(fcgi_request *req) | |
3224 | +{ | |
3225 | + fcgi_header hdr; | |
3226 | + int len, padding; | |
3227 | + unsigned char buf[FCGI_MAX_LENGTH+8]; | |
3228 | + | |
3229 | + req->keep = 0; | |
3230 | + req->in_len = 0; | |
3231 | + req->out_hdr = NULL; | |
3232 | + req->out_pos = req->out_buf; | |
3233 | + zend_hash_init(&req->env, 0, NULL, (void (*)(void *)) fcgi_free_var, 1); | |
3234 | + | |
3235 | + if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || | |
3236 | + hdr.version < FCGI_VERSION_1) { | |
3237 | + return 0; | |
3238 | + } | |
3239 | + | |
3240 | + len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; | |
3241 | + padding = hdr.paddingLength; | |
3242 | + | |
3243 | + while (hdr.type == FCGI_STDIN && len == 0) { | |
3244 | + if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || | |
3245 | + hdr.version < FCGI_VERSION_1) { | |
3246 | + return 0; | |
3247 | + } | |
3248 | + | |
3249 | + len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; | |
3250 | + padding = hdr.paddingLength; | |
3251 | + } | |
3252 | + | |
3253 | + if (len + padding > FCGI_MAX_LENGTH) { | |
3254 | + return 0; | |
3255 | + } | |
3256 | + | |
3257 | + req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0; | |
3258 | + | |
3259 | + if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) { | |
3260 | + char *val; | |
3261 | + | |
3262 | + if (safe_read(req, buf, len+padding) != len+padding) { | |
3263 | + return 0; | |
3264 | + } | |
3265 | + | |
3266 | + req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN); | |
3267 | + switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) { | |
3268 | + case FCGI_RESPONDER: | |
3269 | + val = strdup("RESPONDER"); | |
3270 | + zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); | |
3271 | + break; | |
3272 | + case FCGI_AUTHORIZER: | |
3273 | + val = strdup("AUTHORIZER"); | |
3274 | + zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); | |
3275 | + break; | |
3276 | + case FCGI_FILTER: | |
3277 | + val = strdup("FILTER"); | |
3278 | + zend_hash_update(&req->env, "FCGI_ROLE", sizeof("FCGI_ROLE"), &val, sizeof(char*), NULL); | |
3279 | + break; | |
3280 | + default: | |
3281 | + return 0; | |
3282 | + } | |
3283 | + | |
3284 | + if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || | |
3285 | + hdr.version < FCGI_VERSION_1) { | |
3286 | + return 0; | |
3287 | + } | |
3288 | + | |
3289 | + len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; | |
3290 | + padding = hdr.paddingLength; | |
3291 | + | |
3292 | + while (hdr.type == FCGI_PARAMS && len > 0) { | |
3293 | + if (len + padding > FCGI_MAX_LENGTH) { | |
3294 | + return 0; | |
3295 | + } | |
3296 | + | |
3297 | + if (safe_read(req, buf, len+padding) != len+padding) { | |
3298 | + req->keep = 0; | |
3299 | + return 0; | |
3300 | + } | |
3301 | + | |
3302 | + if (!fcgi_get_params(req, buf, buf+len)) { | |
3303 | + req->keep = 0; | |
3304 | + return 0; | |
3305 | + } | |
3306 | + | |
3307 | + if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || | |
3308 | + hdr.version < FCGI_VERSION_1) { | |
3309 | + req->keep = 0; | |
3310 | + return 0; | |
3311 | + } | |
3312 | + len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; | |
3313 | + padding = hdr.paddingLength; | |
3314 | + } | |
3315 | + } else if (hdr.type == FCGI_GET_VALUES) { | |
3316 | + unsigned char *p = buf + sizeof(fcgi_header); | |
3317 | + HashPosition pos; | |
3318 | + char * str_index; | |
3319 | + uint str_length; | |
3320 | + ulong num_index; | |
3321 | + int key_type; | |
3322 | + zval ** value; | |
3323 | + | |
3324 | + if (safe_read(req, buf, len+padding) != len+padding) { | |
3325 | + req->keep = 0; | |
3326 | + return 0; | |
3327 | + } | |
3328 | + | |
3329 | + if (!fcgi_get_params(req, buf, buf+len)) { | |
3330 | + req->keep = 0; | |
3331 | + return 0; | |
3332 | + } | |
3333 | + | |
3334 | + zend_hash_internal_pointer_reset_ex(&req->env, &pos); | |
3335 | + while ((key_type = zend_hash_get_current_key_ex(&req->env, &str_index, &str_length, &num_index, 0, &pos)) != HASH_KEY_NON_EXISTANT) { | |
3336 | + int zlen; | |
3337 | + zend_hash_move_forward_ex(&req->env, &pos); | |
3338 | + if (key_type != HASH_KEY_IS_STRING) { | |
3339 | + continue; | |
3340 | + } | |
3341 | + if (zend_hash_find(fcgi_mgmt_vars, str_index, str_length, (void**) &value) != SUCCESS) { | |
3342 | + continue; | |
3343 | + } | |
3344 | + --str_length; | |
3345 | + zlen = Z_STRLEN_PP(value); | |
3346 | + if ((p + 4 + 4 + str_length + zlen) >= (buf + sizeof(buf))) { | |
3347 | + break; | |
3348 | + } | |
3349 | + if (str_length < 0x80) { | |
3350 | + *p++ = str_length; | |
3351 | + } else { | |
3352 | + *p++ = ((str_length >> 24) & 0xff) | 0x80; | |
3353 | + *p++ = (str_length >> 16) & 0xff; | |
3354 | + *p++ = (str_length >> 8) & 0xff; | |
3355 | + *p++ = str_length & 0xff; | |
3356 | + } | |
3357 | + if (zlen < 0x80) { | |
3358 | + *p++ = zlen; | |
3359 | + } else { | |
3360 | + *p++ = ((zlen >> 24) & 0xff) | 0x80; | |
3361 | + *p++ = (zlen >> 16) & 0xff; | |
3362 | + *p++ = (zlen >> 8) & 0xff; | |
3363 | + *p++ = zlen & 0xff; | |
3364 | + } | |
3365 | + memcpy(p, str_index, str_length); | |
3366 | + p += str_length; | |
3367 | + memcpy(p, Z_STRVAL_PP(value), zlen); | |
3368 | + p += zlen; | |
3369 | + } | |
3370 | + len = p - buf - sizeof(fcgi_header); | |
3371 | + len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len); | |
3372 | + if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) { | |
3373 | + req->keep = 0; | |
3374 | + return 0; | |
3375 | + } | |
3376 | + return 0; | |
3377 | + } else { | |
3378 | + return 0; | |
3379 | + } | |
3380 | + | |
3381 | + return 1; | |
3382 | +} | |
3383 | + | |
3384 | +int fcgi_read(fcgi_request *req, char *str, int len) | |
3385 | +{ | |
3386 | + int ret, n, rest; | |
3387 | + fcgi_header hdr; | |
3388 | + unsigned char buf[255]; | |
3389 | + | |
3390 | + n = 0; | |
3391 | + rest = len; | |
3392 | + while (rest > 0) { | |
3393 | + if (req->in_len == 0) { | |
3394 | + if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) || | |
3395 | + hdr.version < FCGI_VERSION_1 || | |
3396 | + hdr.type != FCGI_STDIN) { | |
3397 | + req->keep = 0; | |
3398 | + return 0; | |
3399 | + } | |
3400 | + req->in_len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0; | |
3401 | + req->in_pad = hdr.paddingLength; | |
3402 | + if (req->in_len == 0) { | |
3403 | + return n; | |
3404 | + } | |
3405 | + } | |
3406 | + | |
3407 | + if (req->in_len >= rest) { | |
3408 | + ret = safe_read(req, str, rest); | |
3409 | + } else { | |
3410 | + ret = safe_read(req, str, req->in_len); | |
3411 | + } | |
3412 | + if (ret < 0) { | |
3413 | + req->keep = 0; | |
3414 | + return ret; | |
3415 | + } else if (ret > 0) { | |
3416 | + req->in_len -= ret; | |
3417 | + rest -= ret; | |
3418 | + n += ret; | |
3419 | + str += ret; | |
3420 | + if (req->in_len == 0) { | |
3421 | + if (req->in_pad) { | |
3422 | + if (safe_read(req, buf, req->in_pad) != req->in_pad) { | |
3423 | + req->keep = 0; | |
3424 | + return ret; | |
3425 | + } | |
3426 | + } | |
3427 | + } else { | |
3428 | + return n; | |
3429 | + } | |
3430 | + } else { | |
3431 | + return n; | |
3432 | + } | |
3433 | + } | |
3434 | + return n; | |
3435 | +} | |
3436 | + | |
3437 | +void fcgi_close(fcgi_request *req, int force, int destroy) | |
3438 | +{ | |
3439 | + if (destroy) { | |
3440 | + zend_hash_destroy(&req->env); | |
3441 | + } | |
3442 | + | |
3443 | +#ifdef _WIN32 | |
3444 | + if (is_impersonate && !req->tcp) { | |
3445 | + RevertToSelf(); | |
3446 | + } | |
3447 | +#endif | |
3448 | + | |
3449 | + if ((force || !req->keep) && req->fd >= 0) { | |
3450 | +#ifdef _WIN32 | |
3451 | + if (!req->tcp) { | |
3452 | + HANDLE pipe = (HANDLE)_get_osfhandle(req->fd); | |
3453 | + | |
3454 | + if (!force) { | |
3455 | + FlushFileBuffers(pipe); | |
3456 | + } | |
3457 | + DisconnectNamedPipe(pipe); | |
3458 | + } else { | |
3459 | + if (!force) { | |
3460 | + char buf[8]; | |
3461 | + | |
3462 | + shutdown(req->fd, 1); | |
3463 | + while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} | |
3464 | + } | |
3465 | + closesocket(req->fd); | |
3466 | + } | |
3467 | +#else | |
3468 | + if (!force) { | |
3469 | + char buf[8]; | |
3470 | + | |
3471 | + shutdown(req->fd, 1); | |
3472 | + while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} | |
3473 | + } | |
3474 | + close(req->fd); | |
3475 | +#endif | |
3476 | + req->fd = -1; | |
3477 | + | |
3478 | + fpm_request_finished(); | |
3479 | + } | |
3480 | +} | |
3481 | + | |
3482 | +int fcgi_accept_request(fcgi_request *req) | |
3483 | +{ | |
3484 | +#ifdef _WIN32 | |
3485 | + HANDLE pipe; | |
3486 | + OVERLAPPED ov; | |
3487 | +#endif | |
3488 | + fcgi_finish_request(req); | |
3489 | + | |
3490 | + while (1) { | |
3491 | + if (req->fd < 0) { | |
3492 | + while (1) { | |
3493 | + if (in_shutdown) { | |
3494 | + return -1; | |
3495 | + } | |
3496 | +#ifdef _WIN32 | |
3497 | + if (!req->tcp) { | |
3498 | + pipe = (HANDLE)_get_osfhandle(req->listen_socket); | |
3499 | + FCGI_LOCK(req->listen_socket); | |
3500 | + ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); | |
3501 | + if (!ConnectNamedPipe(pipe, &ov)) { | |
3502 | + errno = GetLastError(); | |
3503 | + if (errno == ERROR_IO_PENDING) { | |
3504 | + while (WaitForSingleObject(ov.hEvent, 1000) == WAIT_TIMEOUT) { | |
3505 | + if (in_shutdown) { | |
3506 | + CloseHandle(ov.hEvent); | |
3507 | + FCGI_UNLOCK(req->listen_socket); | |
3508 | + return -1; | |
3509 | + } | |
3510 | + } | |
3511 | + } else if (errno != ERROR_PIPE_CONNECTED) { | |
3512 | + } | |
3513 | + } | |
3514 | + CloseHandle(ov.hEvent); | |
3515 | + req->fd = req->listen_socket; | |
3516 | + FCGI_UNLOCK(req->listen_socket); | |
3517 | + } else { | |
3518 | + SOCKET listen_socket = (SOCKET)_get_osfhandle(req->listen_socket); | |
3519 | +#else | |
3520 | + { | |
3521 | + int listen_socket = req->listen_socket; | |
3522 | +#endif | |
3523 | + sa_t sa; | |
3524 | + socklen_t len = sizeof(sa); | |
3525 | + | |
3526 | + fpm_request_accepting(); | |
3527 | + | |
3528 | + FCGI_LOCK(req->listen_socket); | |
3529 | + req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len); | |
3530 | + FCGI_UNLOCK(req->listen_socket); | |
3531 | + if (req->fd >= 0 && allowed_clients) { | |
3532 | + int n = 0; | |
3533 | + int allowed = 0; | |
3534 | + | |
3535 | + while (allowed_clients[n] != INADDR_NONE) { | |
3536 | + if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) { | |
3537 | + allowed = 1; | |
3538 | + break; | |
3539 | + } | |
3540 | + n++; | |
3541 | + } | |
3542 | + if (!allowed) { | |
3543 | + fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr)); | |
3544 | + closesocket(req->fd); | |
3545 | + req->fd = -1; | |
3546 | + continue; | |
3547 | + } | |
3548 | + } | |
3549 | + } | |
3550 | + | |
3551 | +#ifdef _WIN32 | |
3552 | + if (req->fd < 0 && (in_shutdown || errno != EINTR)) { | |
3553 | +#else | |
3554 | + if (req->fd < 0 && (in_shutdown || (errno != EINTR && errno != ECONNABORTED))) { | |
3555 | +#endif | |
3556 | + return -1; | |
3557 | + } | |
3558 | + | |
3559 | +#ifdef _WIN32 | |
3560 | + break; | |
3561 | +#else | |
3562 | + if (req->fd >= 0) { | |
3563 | + | |
3564 | + fpm_request_reading_headers(); | |
3565 | + | |
3566 | +#if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL) | |
3567 | + struct pollfd fds; | |
3568 | + int ret; | |
3569 | + | |
3570 | + fds.fd = req->fd; | |
3571 | + fds.events = POLLIN; | |
3572 | + fds.revents = 0; | |
3573 | + do { | |
3574 | + errno = 0; | |
3575 | + ret = poll(&fds, 1, 5000); | |
3576 | + } while (ret < 0 && errno == EINTR); | |
3577 | + if (ret > 0 && (fds.revents & POLLIN)) { | |
3578 | + break; | |
3579 | + } | |
3580 | + fcgi_close(req, 1, 0); | |
3581 | +#else | |
3582 | + if (req->fd < FD_SETSIZE) { | |
3583 | + struct timeval tv = {5,0}; | |
3584 | + fd_set set; | |
3585 | + int ret; | |
3586 | + | |
3587 | + FD_ZERO(&set); | |
3588 | + FD_SET(req->fd, &set); | |
3589 | + do { | |
3590 | + errno = 0; | |
3591 | + ret = select(req->fd + 1, &set, NULL, NULL, &tv) >= 0; | |
3592 | + } while (ret < 0 && errno == EINTR); | |
3593 | + if (ret > 0 && FD_ISSET(req->fd, &set)) { | |
3594 | + break; | |
3595 | + } | |
3596 | + fcgi_close(req, 1, 0); | |
3597 | + } else { | |
3598 | + fprintf(stderr, "Too many open file descriptors. FD_SETSIZE limit exceeded."); | |
3599 | + fcgi_close(req, 1, 0); | |
3600 | + } | |
3601 | +#endif | |
3602 | + } | |
3603 | +#endif | |
3604 | + } | |
3605 | + } else if (in_shutdown) { | |
3606 | + return -1; | |
3607 | + } | |
3608 | + if (fcgi_read_request(req)) { | |
3609 | +#ifdef _WIN32 | |
3610 | + if (is_impersonate && !req->tcp) { | |
3611 | + pipe = (HANDLE)_get_osfhandle(req->fd); | |
3612 | + if (!ImpersonateNamedPipeClient(pipe)) { | |
3613 | + fcgi_close(req, 1, 1); | |
3614 | + continue; | |
3615 | + } | |
3616 | + } | |
3617 | +#endif | |
3618 | + return req->fd; | |
3619 | + } else { | |
3620 | + fcgi_close(req, 1, 1); | |
3621 | + } | |
3622 | + } | |
3623 | +} | |
3624 | + | |
3625 | +static inline fcgi_header* open_packet(fcgi_request *req, fcgi_request_type type) | |
3626 | +{ | |
3627 | + req->out_hdr = (fcgi_header*) req->out_pos; | |
3628 | + req->out_hdr->type = type; | |
3629 | + req->out_pos += sizeof(fcgi_header); | |
3630 | + return req->out_hdr; | |
3631 | +} | |
3632 | + | |
3633 | +static inline void close_packet(fcgi_request *req) | |
3634 | +{ | |
3635 | + if (req->out_hdr) { | |
3636 | + int len = req->out_pos - ((unsigned char*)req->out_hdr + sizeof(fcgi_header)); | |
3637 | + | |
3638 | + req->out_pos += fcgi_make_header(req->out_hdr, (fcgi_request_type)req->out_hdr->type, req->id, len); | |
3639 | + req->out_hdr = NULL; | |
3640 | + } | |
3641 | +} | |
3642 | + | |
3643 | +int fcgi_flush(fcgi_request *req, int close) | |
3644 | +{ | |
3645 | + int len; | |
3646 | + | |
3647 | + close_packet(req); | |
3648 | + | |
3649 | + len = req->out_pos - req->out_buf; | |
3650 | + | |
3651 | + if (close) { | |
3652 | + fcgi_end_request_rec *rec = (fcgi_end_request_rec*)(req->out_pos); | |
3653 | + | |
3654 | + fcgi_make_header(&rec->hdr, FCGI_END_REQUEST, req->id, sizeof(fcgi_end_request)); | |
3655 | + rec->body.appStatusB3 = 0; | |
3656 | + rec->body.appStatusB2 = 0; | |
3657 | + rec->body.appStatusB1 = 0; | |
3658 | + rec->body.appStatusB0 = 0; | |
3659 | + rec->body.protocolStatus = FCGI_REQUEST_COMPLETE; | |
3660 | + len += sizeof(fcgi_end_request_rec); | |
3661 | + } | |
3662 | + | |
3663 | + if (safe_write(req, req->out_buf, len) != len) { | |
3664 | + req->keep = 0; | |
3665 | + return 0; | |
3666 | + } | |
3667 | + | |
3668 | + req->out_pos = req->out_buf; | |
3669 | + return 1; | |
3670 | +} | |
3671 | + | |
3672 | +int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len) | |
3673 | +{ | |
3674 | + int limit, rest; | |
3675 | + | |
3676 | + if (len <= 0) { | |
3677 | + return 0; | |
3678 | + } | |
3679 | + | |
3680 | + if (req->out_hdr && req->out_hdr->type != type) { | |
3681 | + close_packet(req); | |
3682 | + } | |
3683 | +#if 0 | |
3684 | + /* Unoptimized, but clear version */ | |
3685 | + rest = len; | |
3686 | + while (rest > 0) { | |
3687 | + limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); | |
3688 | + | |
3689 | + if (!req->out_hdr) { | |
3690 | + if (limit < sizeof(fcgi_header)) { | |
3691 | + if (!fcgi_flush(req, 0)) { | |
3692 | + return -1; | |
3693 | + } | |
3694 | + } | |
3695 | + open_packet(req, type); | |
3696 | + } | |
3697 | + limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); | |
3698 | + if (rest < limit) { | |
3699 | + memcpy(req->out_pos, str, rest); | |
3700 | + req->out_pos += rest; | |
3701 | + return len; | |
3702 | + } else { | |
3703 | + memcpy(req->out_pos, str, limit); | |
3704 | + req->out_pos += limit; | |
3705 | + rest -= limit; | |
3706 | + str += limit; | |
3707 | + if (!fcgi_flush(req, 0)) { | |
3708 | + return -1; | |
3709 | + } | |
3710 | + } | |
3711 | + } | |
3712 | +#else | |
3713 | + /* Optimized version */ | |
3714 | + limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf); | |
3715 | + if (!req->out_hdr) { | |
3716 | + limit -= sizeof(fcgi_header); | |
3717 | + if (limit < 0) limit = 0; | |
3718 | + } | |
3719 | + | |
3720 | + if (len < limit) { | |
3721 | + if (!req->out_hdr) { | |
3722 | + open_packet(req, type); | |
3723 | + } | |
3724 | + memcpy(req->out_pos, str, len); | |
3725 | + req->out_pos += len; | |
3726 | + } else if (len - limit < sizeof(req->out_buf) - sizeof(fcgi_header)) { | |
3727 | + if (!req->out_hdr) { | |
3728 | + open_packet(req, type); | |
3729 | + } | |
3730 | + if (limit > 0) { | |
3731 | + memcpy(req->out_pos, str, limit); | |
3732 | + req->out_pos += limit; | |
3733 | + } | |
3734 | + if (!fcgi_flush(req, 0)) { | |
3735 | + return -1; | |
3736 | + } | |
3737 | + if (len > limit) { | |
3738 | + open_packet(req, type); | |
3739 | + memcpy(req->out_pos, str + limit, len - limit); | |
3740 | + req->out_pos += len - limit; | |
3741 | + } | |
3742 | + } else { | |
3743 | + int pos = 0; | |
3744 | + int pad; | |
3745 | + | |
3746 | + close_packet(req); | |
3747 | + while ((len - pos) > 0xffff) { | |
3748 | + open_packet(req, type); | |
3749 | + fcgi_make_header(req->out_hdr, type, req->id, 0xfff8); | |
3750 | + req->out_hdr = NULL; | |
3751 | + if (!fcgi_flush(req, 0)) { | |
3752 | + return -1; | |
3753 | + } | |
3754 | + if (safe_write(req, str + pos, 0xfff8) != 0xfff8) { | |
3755 | + req->keep = 0; | |
3756 | + return -1; | |
3757 | + } | |
3758 | + pos += 0xfff8; | |
3759 | + } | |
3760 | + | |
3761 | + pad = (((len - pos) + 7) & ~7) - (len - pos); | |
3762 | + rest = pad ? 8 - pad : 0; | |
3763 | + | |
3764 | + open_packet(req, type); | |
3765 | + fcgi_make_header(req->out_hdr, type, req->id, (len - pos) - rest); | |
3766 | + req->out_hdr = NULL; | |
3767 | + if (!fcgi_flush(req, 0)) { | |
3768 | + return -1; | |
3769 | + } | |
3770 | + if (safe_write(req, str + pos, (len - pos) - rest) != (len - pos) - rest) { | |
3771 | + req->keep = 0; | |
3772 | + return -1; | |
3773 | + } | |
3774 | + if (pad) { | |
3775 | + open_packet(req, type); | |
3776 | + memcpy(req->out_pos, str + len - rest, rest); | |
3777 | + req->out_pos += rest; | |
3778 | + } | |
3779 | + } | |
3780 | +#endif | |
3781 | + return len; | |
3782 | +} | |
3783 | + | |
3784 | +int fcgi_finish_request(fcgi_request *req) | |
3785 | +{ | |
3786 | + if (req->fd >= 0) { | |
3787 | + fcgi_flush(req, 1); | |
3788 | + fcgi_close(req, 0, 1); | |
3789 | + } | |
3790 | + return 1; | |
3791 | +} | |
3792 | + | |
3793 | +char* fcgi_getenv(fcgi_request *req, const char* var, int var_len) | |
3794 | +{ | |
3795 | + char **val; | |
3796 | + | |
3797 | + if (!req) return NULL; | |
3798 | + | |
3799 | + if (zend_hash_find(&req->env, (char*)var, var_len+1, (void**)&val) == SUCCESS) { | |
3800 | + return *val; | |
3801 | + } | |
3802 | + return NULL; | |
3803 | +} | |
3804 | + | |
3805 | +char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val) | |
3806 | +{ | |
3807 | + if (var && req) { | |
3808 | + if (val == NULL) { | |
3809 | + zend_hash_del(&req->env, var, var_len+1); | |
3810 | + } else { | |
3811 | + char **ret; | |
3812 | + | |
3813 | + val = strdup(val); | |
3814 | + if (zend_hash_update(&req->env, var, var_len+1, &val, sizeof(char*), (void**)&ret) == SUCCESS) { | |
3815 | + return *ret; | |
3816 | + } | |
3817 | + } | |
3818 | + } | |
3819 | + return NULL; | |
3820 | +} | |
3821 | + | |
3822 | +#ifdef _WIN32 | |
3823 | +void fcgi_impersonate(void) | |
3824 | +{ | |
3825 | + char *os_name; | |
3826 | + | |
3827 | + os_name = getenv("OS"); | |
3828 | + if (os_name && stricmp(os_name, "Windows_NT") == 0) { | |
3829 | + is_impersonate = 1; | |
3830 | + } | |
3831 | +} | |
3832 | +#endif | |
3833 | + | |
3834 | +void fcgi_set_mgmt_var(char * name, size_t name_len, const char * value, size_t value_len) | |
3835 | +{ | |
3836 | + zval * zvalue; | |
3837 | + zvalue = pemalloc(sizeof(*zvalue), 1); | |
3838 | + Z_TYPE_P(zvalue) = IS_STRING; | |
3839 | + Z_STRVAL_P(zvalue) = pestrndup(value, value_len, 1); | |
3840 | + Z_STRLEN_P(zvalue) = value_len; | |
3841 | + zend_hash_update(fcgi_mgmt_vars, name, name_len + 1, &zvalue, sizeof(zvalue), NULL); | |
3842 | +} | |
3843 | + | |
3844 | +void fcgi_free_mgmt_var_cb(void * ptr) | |
3845 | +{ | |
3846 | + zval ** var = (zval **)ptr; | |
3847 | + pefree(Z_STRVAL_PP(var), 1); | |
3848 | + pefree(*var, 1); | |
3849 | +} | |
3850 | + | |
3851 | +/* | |
3852 | + * Local variables: | |
3853 | + * tab-width: 4 | |
3854 | + * c-basic-offset: 4 | |
3855 | + * End: | |
3856 | + * vim600: sw=4 ts=4 fdm=marker | |
3857 | + * vim<600: sw=4 ts=4 | |
3858 | + */ | |
3859 | diff -Naur php-src-vanilla/sapi/fpm/cgi/fastcgi.h php-src/sapi/fpm/cgi/fastcgi.h | |
3860 | --- php-src-vanilla/sapi/fpm/cgi/fastcgi.h 1970-01-01 01:00:00.000000000 +0100 | |
3861 | +++ php-src/sapi/fpm/cgi/fastcgi.h 2009-10-18 21:05:39.302497288 +0100 | |
3862 | @@ -0,0 +1,150 @@ | |
3863 | +/* | |
3864 | + +----------------------------------------------------------------------+ | |
3865 | + | PHP Version 5 | | |
3866 | + +----------------------------------------------------------------------+ | |
3867 | + | Copyright (c) 1997-2008 The PHP Group | | |
3868 | + +----------------------------------------------------------------------+ | |
3869 | + | This source file is subject to version 3.01 of the PHP license, | | |
3870 | + | that is bundled with this package in the file LICENSE, and is | | |
3871 | + | available through the world-wide-web at the following url: | | |
3872 | + | http://www.php.net/license/3_01.txt | | |
3873 | + | If you did not receive a copy of the PHP license and are unable to | | |
3874 | + | obtain it through the world-wide-web, please send a note to | | |
3875 | + | license@php.net so we can mail you a copy immediately. | | |
3876 | + +----------------------------------------------------------------------+ | |
3877 | + | Authors: Dmitry Stogov <dmitry@zend.com> | | |
3878 | + +----------------------------------------------------------------------+ | |
3879 | +*/ | |
3880 | + | |
3881 | +/* $Id$ */ | |
3882 | + | |
3883 | +/* FastCGI protocol */ | |
3884 | + | |
3885 | +#define FCGI_VERSION_1 1 | |
3886 | + | |
3887 | +#define FCGI_MAX_LENGTH 0xffff | |
3888 | + | |
3889 | +#define FCGI_KEEP_CONN 1 | |
3890 | + | |
3891 | +typedef enum _fcgi_role { | |
3892 | + FCGI_RESPONDER = 1, | |
3893 | + FCGI_AUTHORIZER = 2, | |
3894 | + FCGI_FILTER = 3 | |
3895 | +} fcgi_role; | |
3896 | + | |
3897 | +typedef enum _fcgi_request_type { | |
3898 | + FCGI_BEGIN_REQUEST = 1, /* [in] */ | |
3899 | + FCGI_ABORT_REQUEST = 2, /* [in] (not supported) */ | |
3900 | + FCGI_END_REQUEST = 3, /* [out] */ | |
3901 | + FCGI_PARAMS = 4, /* [in] environment variables */ | |
3902 | + FCGI_STDIN = 5, /* [in] post data */ | |
3903 | + FCGI_STDOUT = 6, /* [out] response */ | |
3904 | + FCGI_STDERR = 7, /* [out] errors */ | |
3905 | + FCGI_DATA = 8, /* [in] filter data (not supported) */ | |
3906 | + FCGI_GET_VALUES = 9, /* [in] */ | |
3907 | + FCGI_GET_VALUES_RESULT = 10 /* [out] */ | |
3908 | +} fcgi_request_type; | |
3909 | + | |
3910 | +typedef enum _fcgi_protocol_status { | |
3911 | + FCGI_REQUEST_COMPLETE = 0, | |
3912 | + FCGI_CANT_MPX_CONN = 1, | |
3913 | + FCGI_OVERLOADED = 2, | |
3914 | + FCGI_UNKNOWN_ROLE = 3 | |
3915 | +} dcgi_protocol_status; | |
3916 | + | |
3917 | +typedef struct _fcgi_header { | |
3918 | + unsigned char version; | |
3919 | + unsigned char type; | |
3920 | + unsigned char requestIdB1; | |
3921 | + unsigned char requestIdB0; | |
3922 | + unsigned char contentLengthB1; | |
3923 | + unsigned char contentLengthB0; | |
3924 | + unsigned char paddingLength; | |
3925 | + unsigned char reserved; | |
3926 | +} fcgi_header; | |
3927 | + | |
3928 | +typedef struct _fcgi_begin_request { | |
3929 | + unsigned char roleB1; | |
3930 | + unsigned char roleB0; | |
3931 | + unsigned char flags; | |
3932 | + unsigned char reserved[5]; | |
3933 | +} fcgi_begin_request; | |
3934 | + | |
3935 | +typedef struct _fcgi_begin_request_rec { | |
3936 | + fcgi_header hdr; | |
3937 | + fcgi_begin_request body; | |
3938 | +} fcgi_begin_request_rec; | |
3939 | + | |
3940 | +typedef struct _fcgi_end_request { | |
3941 | + unsigned char appStatusB3; | |
3942 | + unsigned char appStatusB2; | |
3943 | + unsigned char appStatusB1; | |
3944 | + unsigned char appStatusB0; | |
3945 | + unsigned char protocolStatus; | |
3946 | + unsigned char reserved[3]; | |
3947 | +} fcgi_end_request; | |
3948 | + | |
3949 | +typedef struct _fcgi_end_request_rec { | |
3950 | + fcgi_header hdr; | |
3951 | + fcgi_end_request body; | |
3952 | +} fcgi_end_request_rec; | |
3953 | + | |
3954 | +/* FastCGI client API */ | |
3955 | + | |
3956 | +typedef struct _fcgi_request { | |
3957 | + int listen_socket; | |
3958 | +#ifdef _WIN32 | |
3959 | + int tcp; | |
3960 | +#endif | |
3961 | + int fd; | |
3962 | + int id; | |
3963 | + int keep; | |
3964 | + | |
3965 | + int in_len; | |
3966 | + int in_pad; | |
3967 | + | |
3968 | + fcgi_header *out_hdr; | |
3969 | + unsigned char *out_pos; | |
3970 | + unsigned char out_buf[1024*8]; | |
3971 | + unsigned char reserved[sizeof(fcgi_end_request_rec)]; | |
3972 | + | |
3973 | + HashTable env; | |
3974 | +} fcgi_request; | |
3975 | + | |
3976 | +int fcgi_init(void); | |
3977 | +void fcgi_shutdown(void); | |
3978 | +int fcgi_is_fastcgi(void); | |
3979 | +void fcgi_set_is_fastcgi(int); | |
3980 | +void fcgi_set_in_shutdown(int); | |
3981 | +void fcgi_set_allowed_clients(char *); | |
3982 | +int fcgi_in_shutdown(void); | |
3983 | +int fcgi_listen(const char *path, int backlog); | |
3984 | +void fcgi_init_request(fcgi_request *req, int listen_socket); | |
3985 | +int fcgi_accept_request(fcgi_request *req); | |
3986 | +int fcgi_finish_request(fcgi_request *req); | |
3987 | + | |
3988 | +char* fcgi_getenv(fcgi_request *req, const char* var, int var_len); | |
3989 | +char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val); | |
3990 | + | |
3991 | +int fcgi_read(fcgi_request *req, char *str, int len); | |
3992 | + | |
3993 | +int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len); | |
3994 | +int fcgi_flush(fcgi_request *req, int close); | |
3995 | + | |
3996 | +void fcgi_close(fcgi_request *req, int force, int destroy); | |
3997 | + | |
3998 | +#ifdef PHP_WIN32 | |
3999 | +void fcgi_impersonate(void); | |
4000 | +#endif | |
4001 | + | |
4002 | +void fcgi_set_mgmt_var(char * name, size_t name_len, const char * value, size_t value_len); | |
4003 | +void fcgi_free_mgmt_var_cb(void * ptr); | |
4004 | + | |
4005 | +/* | |
4006 | + * Local variables: | |
4007 | + * tab-width: 4 | |
4008 | + * c-basic-offset: 4 | |
4009 | + * End: | |
4010 | + * vim600: sw=4 ts=4 fdm=marker | |
4011 | + * vim<600: sw=4 ts=4 | |
4012 | + */ | |
4013 | diff -Naur php-src-vanilla/sapi/fpm/cgi/php_getopt.h php-src/sapi/fpm/cgi/php_getopt.h | |
4014 | --- php-src-vanilla/sapi/fpm/cgi/php_getopt.h 1970-01-01 01:00:00.000000000 +0100 | |
4015 | +++ php-src/sapi/fpm/cgi/php_getopt.h 2009-10-18 21:05:39.302497288 +0100 | |
4016 | @@ -0,0 +1,39 @@ | |
4017 | +/* | |
4018 | + +----------------------------------------------------------------------+ | |
4019 | + | PHP Version 5 | | |
4020 | + +----------------------------------------------------------------------+ | |
4021 | + | Copyright (c) 1997-2008 The PHP Group | | |
4022 | + +----------------------------------------------------------------------+ | |
4023 | + | This source file is subject to version 3.01 of the PHP license, | | |
4024 | + | that is bundled with this package in the file LICENSE, and is | | |
4025 | + | available through the world-wide-web at the following url: | | |
4026 | + | http://www.php.net/license/3_01.txt | | |
4027 | + | If you did not receive a copy of the PHP license and are unable to | | |
4028 | + | obtain it through the world-wide-web, please send a note to | | |
4029 | + | license@php.net so we can mail you a copy immediately. | | |
4030 | + +----------------------------------------------------------------------+ | |
4031 | + | Author: Marcus Boerger <helly@php.net> | | |
4032 | + +----------------------------------------------------------------------+ | |
4033 | +*/ | |
4034 | + | |
4035 | +/* $Id$ */ | |
4036 | + | |
4037 | +#include <php.h> | |
4038 | + | |
4039 | +#ifdef NETWARE | |
4040 | +/* | |
4041 | +As NetWare LibC has optind and optarg macros defined in unistd.h our local variables were getting mistakenly preprocessed so undeffing optind and optarg | |
4042 | +*/ | |
4043 | +#undef optarg | |
4044 | +#undef optind | |
4045 | +#endif | |
4046 | +/* Define structure for one recognized option (both single char and long name). | |
4047 | + * If short_open is '-' this is the last option. | |
4048 | + */ | |
4049 | +typedef struct _opt_struct { | |
4050 | + const char opt_char; | |
4051 | + const int need_param; | |
4052 | + const char * opt_name; | |
4053 | +} opt_struct; | |
4054 | + | |
4055 | +int php_getopt(int argc, char* const *argv, const opt_struct opts[], char **optarg, int *optind, int show_err); | |
4056 | diff -Naur php-src-vanilla/sapi/fpm/conf/init.d.php-fpm.in php-src/sapi/fpm/conf/init.d.php-fpm.in | |
4057 | --- php-src-vanilla/sapi/fpm/conf/init.d.php-fpm.in 1970-01-01 01:00:00.000000000 +0100 | |
4058 | +++ php-src/sapi/fpm/conf/init.d.php-fpm.in 2009-10-18 21:05:39.298456068 +0100 | |
4059 | @@ -0,0 +1,135 @@ | |
4060 | +#! /bin/sh | |
4061 | + | |
4062 | +### BEGIN INIT INFO | |
4063 | +# Provides: @php_fpm_bin@ | |
4064 | +# Required-Start: $all | |
4065 | +# Required-Stop: $all | |
4066 | +# Default-Start: 2 3 4 5 | |
4067 | +# Default-Stop: 0 1 6 | |
4068 | +# Short-Description: starts @php_fpm_bin@ | |
4069 | +# Description: starts the PHP FastCGI Process Manager daemon | |
4070 | +### END INIT INFO | |
4071 | + | |
4072 | +php_fpm_BIN=@php_fpm_bin_path@ | |
4073 | +php_fpm_CONF=@php_fpm_conf_path@ | |
4074 | +php_fpm_PID=@php_fpm_pid_path@ | |
4075 | + | |
4076 | + | |
4077 | +php_opts="--fpm-config $php_fpm_CONF" | |
4078 | + | |
4079 | + | |
4080 | +wait_for_pid () { | |
4081 | + try=0 | |
4082 | + | |
4083 | + while test $try -lt 35 ; do | |
4084 | + | |
4085 | + case "$1" in | |
4086 | + 'created') | |
4087 | + if [ -f "$2" ] ; then | |
4088 | + try='' | |
4089 | + break | |
4090 | + fi | |
4091 | + ;; | |
4092 | + | |
4093 | + 'removed') | |
4094 | + if [ ! -f "$2" ] ; then | |
4095 | + try='' | |
4096 | + break | |
4097 | + fi | |
4098 | + ;; | |
4099 | + esac | |
4100 | + | |
4101 | + echo -n . | |
4102 | + try=`expr $try + 1` | |
4103 | + sleep 1 | |
4104 | + | |
4105 | + done | |
4106 | + | |
4107 | +} | |
4108 | + | |
4109 | +case "$1" in | |
4110 | + start) | |
4111 | + echo -n "Starting @php_fpm_bin@ " | |
4112 | + | |
4113 | + $php_fpm_BIN $php_opts | |
4114 | + | |
4115 | + if [ "$?" != 0 ] ; then | |
4116 | + echo " failed" | |
4117 | + exit 1 | |
4118 | + fi | |
4119 | + | |
4120 | + wait_for_pid created $php_fpm_PID | |
4121 | + | |
4122 | + if [ -n "$try" ] ; then | |
4123 | + echo " failed" | |
4124 | + exit 1 | |
4125 | + else | |
4126 | + echo " done" | |
4127 | + fi | |
4128 | + ;; | |
4129 | + | |
4130 | + stop) | |
4131 | + echo -n "Gracefully shutting down @php_fpm_bin@ " | |
4132 | + | |
4133 | + if [ ! -r $php_fpm_PID ] ; then | |
4134 | + echo "warning, no pid file found - php-fpm is not running ?" | |
4135 | + exit 1 | |
4136 | + fi | |
4137 | + | |
4138 | + kill -QUIT `cat $php_fpm_PID` | |
4139 | + | |
4140 | + wait_for_pid removed $php_fpm_PID | |
4141 | + | |
4142 | + if [ -n "$try" ] ; then | |
4143 | + echo " failed. Use force-exit" | |
4144 | + exit 1 | |
4145 | + else | |
4146 | + echo " done" | |
4147 | + fi | |
4148 | + ;; | |
4149 | + | |
4150 | + force-quit) | |
4151 | + echo -n "Terminating @php_fpm_bin@ " | |
4152 | + | |
4153 | + if [ ! -r $php_fpm_PID ] ; then | |
4154 | + echo "warning, no pid file found - php-fpm is not running ?" | |
4155 | + exit 1 | |
4156 | + fi | |
4157 | + | |
4158 | + kill -TERM `cat $php_fpm_PID` | |
4159 | + | |
4160 | + wait_for_pid removed $php_fpm_PID | |
4161 | + | |
4162 | + if [ -n "$try" ] ; then | |
4163 | + echo " failed" | |
4164 | + exit 1 | |
4165 | + else | |
4166 | + echo " done" | |
4167 | + fi | |
4168 | + ;; | |
4169 | + | |
4170 | + restart) | |
4171 | + $0 stop | |
4172 | + $0 start | |
4173 | + ;; | |
4174 | + | |
4175 | + reload) | |
4176 | + | |
4177 | + echo -n "Reload service @php_fpm_bin@ " | |
4178 | + | |
4179 | + if [ ! -r $php_fpm_PID ] ; then | |
4180 | + echo "warning, no pid file found - @php_fpm_bin@ is not running ?" | |
4181 | + exit 1 | |
4182 | + fi | |
4183 | + | |
4184 | + kill -USR2 `cat $php_fpm_PID` | |
4185 | + | |
4186 | + echo " done" | |
4187 | + ;; | |
4188 | + | |
4189 | + *) | |
4190 | + echo "Usage: $0 {start|stop|force-quit|restart|reload}" | |
4191 | + exit 1 | |
4192 | + ;; | |
4193 | + | |
4194 | +esac | |
4195 | diff -Naur php-src-vanilla/sapi/fpm/conf/nginx-site-conf.sample.in php-src/sapi/fpm/conf/nginx-site-conf.sample.in | |
4196 | --- php-src-vanilla/sapi/fpm/conf/nginx-site-conf.sample.in 1970-01-01 01:00:00.000000000 +0100 | |
4197 | +++ php-src/sapi/fpm/conf/nginx-site-conf.sample.in 2009-10-18 21:05:39.298456068 +0100 | |
4198 | @@ -0,0 +1,46 @@ | |
4199 | +# @php_fpm_bin@ - PHP FastCGI Process Manager 'PHP-FPM' | |
4200 | +# | |
4201 | +# nginx-site-conf.sample: | |
4202 | +# Php Site configuration for nginx webserver | |
4203 | +# | |
4204 | +# 1. set server root /path/to/your/website; | |
4205 | +# 2. Rename this file. Copy it to /etc/nginx/sites-available, /etc/nginx/sites-enabled | |
4206 | +# or otherwise ensure that this file is included by the nginx.conf | |
4207 | +# 3. Restart nginx webserver, and @php_fpm_bin@ service. | |
4208 | +# | |
4209 | + | |
4210 | +server { | |
4211 | + | |
4212 | + root /var/www/nginx-site; | |
4213 | + | |
4214 | + server_name localhost; | |
4215 | + listen 80; | |
4216 | + | |
4217 | + access_log /var/log/nginx/localhost.access.log; | |
4218 | + | |
4219 | + location / { | |
4220 | + index index.html index.htm; | |
4221 | + } | |
4222 | + | |
4223 | + #error_page 404 /404.html; | |
4224 | + | |
4225 | + # redirect server error pages to the static page /50x.html | |
4226 | + # | |
4227 | + error_page 500 502 503 504 /50x.html; | |
4228 | + location = /50x.html { | |
4229 | + root /var/www/nginx-default; | |
4230 | + } | |
4231 | + | |
4232 | + # pass the *.php scripts to @php_fpm_bin@ listening on tcp port @php_fpm_port@ | |
4233 | + # | |
4234 | + location ~ \.php$ { | |
4235 | + | |
4236 | + fastcgi_pass 127.0.0.1:@php_fpm_port@; | |
4237 | + fastcgi_index index.php; | |
4238 | + | |
4239 | + include fastcgi_params; | |
4240 | + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | |
4241 | + fastcgi_param SERVER_NAME $http_host; | |
4242 | + fastcgi_ignore_client_abort on; | |
4243 | + } | |
4244 | +} | |
4245 | diff -Naur php-src-vanilla/sapi/fpm/conf/php-fpm.conf.in php-src/sapi/fpm/conf/php-fpm.conf.in | |
4246 | --- php-src-vanilla/sapi/fpm/conf/php-fpm.conf.in 1970-01-01 01:00:00.000000000 +0100 | |
4247 | +++ php-src/sapi/fpm/conf/php-fpm.conf.in 2009-10-18 21:05:39.298456068 +0100 | |
4248 | @@ -0,0 +1,159 @@ | |
4249 | +<?xml version="1.0" ?> | |
4250 | +<configuration> | |
4251 | + | |
4252 | + All relative paths in this config are relative to php's install prefix | |
4253 | + | |
4254 | + <section name="global_options"> | |
4255 | + | |
4256 | + Pid file | |
4257 | + <value name="pid_file">@php_fpm_pid_path@</value> | |
4258 | + | |
4259 | + Error log file | |
4260 | + <value name="error_log">@php_fpm_log_path@</value> | |
4261 | + | |
4262 | + Log level | |
4263 | + <value name="log_level">notice</value> | |
4264 | + | |
4265 | + When this amount of php processes exited with SIGSEGV or SIGBUS ... | |
4266 | + <value name="emergency_restart_threshold">10</value> | |
4267 | + | |
4268 | + ... in a less than this interval of time, a graceful restart will be initiated. | |
4269 | + Useful to work around accidental curruptions in accelerator's shared memory. | |
4270 | + <value name="emergency_restart_interval">1m</value> | |
4271 | + | |
4272 | + Time limit on waiting child's reaction on signals from master | |
4273 | + <value name="process_control_timeout">5s</value> | |
4274 | + | |
4275 | + Set to 'no' to debug fpm | |
4276 | + <value name="daemonize">yes</value> | |
4277 | + | |
4278 | + </section> | |
4279 | + | |
4280 | + <workers> | |
4281 | + | |
4282 | + <section name="pool"> | |
4283 | + | |
4284 | + Name of pool. Used in logs and stats. | |
4285 | + <value name="name">default</value> | |
4286 | + | |
4287 | + Address to accept fastcgi requests on. | |
4288 | + Valid syntax is 'ip.ad.re.ss:port' or just 'port' or '/path/to/unix/socket' | |
4289 | + <value name="listen_address">127.0.0.1:@php_fpm_port@</value> | |
4290 | + | |
4291 | + <value name="listen_options"> | |
4292 | + | |
4293 | + Set listen(2) backlog | |
4294 | + <value name="backlog">-1</value> | |
4295 | + | |
4296 | + Set permissions for unix socket, if one used. | |
4297 | + In Linux read/write permissions must be set in order to allow connections from web server. | |
4298 | + Many BSD-derrived systems allow connections regardless of permissions. | |
4299 | + <value name="owner">@php_fpm_user@</value> | |
4300 | + <value name="group">@php_fpm_group@</value> | |
4301 | + <value name="mode">0666</value> | |
4302 | + </value> | |
4303 | + | |
4304 | + Additional php.ini defines, specific to this pool of workers. | |
4305 | + These settings overwrite the values previously defined in the php.ini. | |
4306 | + <value name="php_defines"> | |
4307 | + <!-- <value name="sendmail_path">/usr/sbin/sendmail -t -i</value> --> | |
4308 | + <!-- <value name="display_errors">0</value> --> | |
4309 | + <!-- <value name="error_log">/var/log/php-error.log</value> --> | |
4310 | + <!-- <value name="log_errors">true</value> --> | |
4311 | + </value> | |
4312 | + | |
4313 | + Unix user of processes | |
4314 | + <value name="user">@php_fpm_user@</value> | |
4315 | + | |
4316 | + Unix group of processes | |
4317 | + <value name="group">@php_fpm_group@</value> | |
4318 | + | |
4319 | + Process manager settings | |
4320 | + <value name="pm"> | |
4321 | + | |
4322 | + Sets style of controling worker process count. | |
4323 | + Valid values are 'static' and 'apache-like' | |
4324 | + <value name="style">static</value> | |
4325 | + | |
4326 | + Sets the limit on the number of simultaneous requests that will be served. | |
4327 | + Equivalent to Apache MaxClients directive. | |
4328 | + Equivalent to PHP_FCGI_CHILDREN environment in original php.fcgi | |
4329 | + Used with any pm_style. | |
4330 | + <value name="max_children">5</value> | |
4331 | + | |
4332 | + Settings group for 'apache-like' pm style | |
4333 | + <value name="apache_like"> | |
4334 | + | |
4335 | + Sets the number of server processes created on startup. | |
4336 | + Used only when 'apache-like' pm_style is selected | |
4337 | + <value name="StartServers">20</value> | |
4338 | + | |
4339 | + Sets the desired minimum number of idle server processes. | |
4340 | + Used only when 'apache-like' pm_style is selected | |
4341 | + <value name="MinSpareServers">5</value> | |
4342 | + | |
4343 | + Sets the desired maximum number of idle server processes. | |
4344 | + Used only when 'apache-like' pm_style is selected | |
4345 | + <value name="MaxSpareServers">35</value> | |
4346 | + | |
4347 | + </value> | |
4348 | + | |
4349 | + </value> | |
4350 | + | |
4351 | + The timeout (in seconds) for serving a single request after which the worker process will be terminated | |
4352 | + Should be used when 'max_execution_time' ini option does not stop script execution for some reason | |
4353 | + '0s' means 'off' | |
4354 | + <value name="request_terminate_timeout">0s</value> | |
4355 | + | |
4356 | + The timeout (in seconds) for serving of single request after which a php backtrace will be dumped to slow.log file | |
4357 | + '0s' means 'off' | |
4358 | + <value name="request_slowlog_timeout">0s</value> | |
4359 | + | |
4360 | + The log file for slow requests | |
4361 | + <value name="slowlog">@php_fpm_log_path@.slow</value> | |
4362 | + | |
4363 | + Set open file desc rlimit | |
4364 | + <value name="rlimit_files">1024</value> | |
4365 | + | |
4366 | + Set max core size rlimit | |
4367 | + <value name="rlimit_core">0</value> | |
4368 | + | |
4369 | + Chroot to this directory at the start, absolute path | |
4370 | + <value name="chroot"></value> | |
4371 | + | |
4372 | + Chdir to this directory at the start, absolute path | |
4373 | + <value name="chdir"></value> | |
4374 | + | |
4375 | + Redirect workers' stdout and stderr into main error log. | |
4376 | + If not set, they will be redirected to /dev/null, according to FastCGI specs | |
4377 | + <value name="catch_workers_output">yes</value> | |
4378 | + | |
4379 | + How much requests each process should execute before respawn. | |
4380 | + Useful to work around memory leaks in 3rd party libraries. | |
4381 | + For endless request processing please specify 0 | |
4382 | + Equivalent to PHP_FCGI_MAX_REQUESTS | |
4383 | + <value name="max_requests">500</value> | |
4384 | + | |
4385 | + Comma separated list of ipv4 addresses of FastCGI clients that allowed to connect. | |
4386 | + Equivalent to FCGI_WEB_SERVER_ADDRS environment in original php.fcgi (5.2.2+) | |
4387 | + Makes sense only with AF_INET listening socket. | |
4388 | + <value name="allowed_clients">127.0.0.1</value> | |
4389 | + | |
4390 | + Pass environment variables like LD_LIBRARY_PATH | |
4391 | + All $VARIABLEs are taken from current environment | |
4392 | + <value name="environment"> | |
4393 | + <value name="HOSTNAME">$HOSTNAME</value> | |
4394 | + <value name="PATH">/usr/local/bin:/usr/bin:/bin</value> | |
4395 | + <value name="TMP">/tmp</value> | |
4396 | + <value name="TMPDIR">/tmp</value> | |
4397 | + <value name="TEMP">/tmp</value> | |
4398 | + <value name="OSTYPE">$OSTYPE</value> | |
4399 | + <value name="MACHTYPE">$MACHTYPE</value> | |
4400 | + <value name="MALLOC_CHECK_">2</value> | |
4401 | + </value> | |
4402 | + | |
4403 | + </section> | |
4404 | + | |
4405 | + </workers> | |
4406 | + | |
4407 | +</configuration> | |
4408 | diff -Naur php-src-vanilla/sapi/fpm/config.m4 php-src/sapi/fpm/config.m4 | |
4409 | --- php-src-vanilla/sapi/fpm/config.m4 1970-01-01 01:00:00.000000000 +0100 | |
4410 | +++ php-src/sapi/fpm/config.m4 2009-10-18 21:05:39.302497288 +0100 | |
4411 | @@ -0,0 +1,26 @@ | |
4412 | +dnl | |
4413 | +dnl $Id$ | |
4414 | +dnl | |
4415 | + | |
4416 | +PHP_ARG_WITH(fpm,, | |
4417 | +[ --with-fpm Build PHP FastCGI - FPM executable], no) | |
4418 | + | |
4419 | +if test "$PHP_FPM" != "no"; then | |
4420 | + | |
4421 | + PHP_CONFIGURE_PART(Configuring fpm) | |
4422 | + | |
4423 | + sinclude(sapi/fpm/ac/fpm_libevent.m4) | |
4424 | + AC_LIB_EVENT([1.4.3],[1.4.11]) | |
4425 | + | |
4426 | + sinclude(sapi/fpm/ac/fpm_checks.m4) | |
4427 | + AC_FPM_CHECKS | |
4428 | + | |
4429 | + sinclude(sapi/fpm/ac/fpm_conf.m4) | |
4430 | + fpm_version="0.6" | |
4431 | + AC_FPM_CONF | |
4432 | + | |
4433 | + sinclude(sapi/fpm/ac/fpm_build.m4) | |
4434 | + AC_FPM_BUILD_SAPI | |
4435 | + | |
4436 | + AC_MSG_RESULT() | |
4437 | +fi | |
4438 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_arrays.h php-src/sapi/fpm/fpm/fpm_arrays.h | |
4439 | --- php-src-vanilla/sapi/fpm/fpm/fpm_arrays.h 1970-01-01 01:00:00.000000000 +0100 | |
4440 | +++ php-src/sapi/fpm/fpm/fpm_arrays.h 2009-10-18 21:05:39.308376784 +0100 | |
4441 | @@ -0,0 +1,110 @@ | |
4442 | + | |
4443 | + /* $Id$ */ | |
4444 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
4445 | + | |
4446 | +#ifndef FPM_ARRAYS_H | |
4447 | +#define FPM_ARRAYS_H 1 | |
4448 | + | |
4449 | +#include <stdlib.h> | |
4450 | +#include <string.h> | |
4451 | + | |
4452 | +struct fpm_array_s { | |
4453 | + void *data; | |
4454 | + size_t sz; | |
4455 | + size_t used; | |
4456 | + size_t allocated; | |
4457 | +}; | |
4458 | + | |
4459 | +static inline struct fpm_array_s *fpm_array_init(struct fpm_array_s *a, unsigned int sz, unsigned int initial_num) | |
4460 | +{ | |
4461 | + void *allocated = 0; | |
4462 | + | |
4463 | + if (!a) { | |
4464 | + a = malloc(sizeof(struct fpm_array_s)); | |
4465 | + | |
4466 | + if (!a) { | |
4467 | + return 0; | |
4468 | + } | |
4469 | + | |
4470 | + allocated = a; | |
4471 | + } | |
4472 | + | |
4473 | + a->sz = sz; | |
4474 | + | |
4475 | + a->data = calloc(sz, initial_num); | |
4476 | + | |
4477 | + if (!a->data) { | |
4478 | + free(allocated); | |
4479 | + return 0; | |
4480 | + } | |
4481 | + | |
4482 | + a->allocated = initial_num; | |
4483 | + a->used = 0; | |
4484 | + | |
4485 | + return a; | |
4486 | +} | |
4487 | + | |
4488 | +static inline void *fpm_array_item(struct fpm_array_s *a, unsigned int n) | |
4489 | +{ | |
4490 | + char *ret; | |
4491 | + | |
4492 | + ret = (char *) a->data + a->sz * n; | |
4493 | + | |
4494 | + return ret; | |
4495 | +} | |
4496 | + | |
4497 | +static inline void *fpm_array_item_last(struct fpm_array_s *a) | |
4498 | +{ | |
4499 | + return fpm_array_item(a, a->used - 1); | |
4500 | +} | |
4501 | + | |
4502 | +static inline int fpm_array_item_remove(struct fpm_array_s *a, unsigned int n) | |
4503 | +{ | |
4504 | + int ret = -1; | |
4505 | + | |
4506 | + if (n < a->used - 1) { | |
4507 | + void *last = fpm_array_item(a, a->used - 1); | |
4508 | + void *to_remove = fpm_array_item(a, n); | |
4509 | + | |
4510 | + memcpy(to_remove, last, a->sz); | |
4511 | + | |
4512 | + ret = n; | |
4513 | + } | |
4514 | + | |
4515 | + --a->used; | |
4516 | + | |
4517 | + return ret; | |
4518 | +} | |
4519 | + | |
4520 | +static inline void *fpm_array_push(struct fpm_array_s *a) | |
4521 | +{ | |
4522 | + void *ret; | |
4523 | + | |
4524 | + if (a->used == a->allocated) { | |
4525 | + size_t new_allocated = a->allocated ? a->allocated * 2 : 20; | |
4526 | + void *new_ptr = realloc(a->data, a->sz * new_allocated); | |
4527 | + | |
4528 | + if (!new_ptr) { | |
4529 | + return 0; | |
4530 | + } | |
4531 | + | |
4532 | + a->data = new_ptr; | |
4533 | + a->allocated = new_allocated; | |
4534 | + } | |
4535 | + | |
4536 | + ret = fpm_array_item(a, a->used); | |
4537 | + | |
4538 | + ++a->used; | |
4539 | + | |
4540 | + return ret; | |
4541 | +} | |
4542 | + | |
4543 | +static inline void fpm_array_free(struct fpm_array_s *a) | |
4544 | +{ | |
4545 | + free(a->data); | |
4546 | + a->data = 0; | |
4547 | + a->sz = 0; | |
4548 | + a->used = a->allocated = 0; | |
4549 | +} | |
4550 | + | |
4551 | +#endif | |
4552 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_atomic.h php-src/sapi/fpm/fpm/fpm_atomic.h | |
4553 | --- php-src-vanilla/sapi/fpm/fpm/fpm_atomic.h 1970-01-01 01:00:00.000000000 +0100 | |
4554 | +++ php-src/sapi/fpm/fpm/fpm_atomic.h 2009-10-18 21:05:39.308376784 +0100 | |
4555 | @@ -0,0 +1,139 @@ | |
4556 | + | |
4557 | + /* $Id$ */ | |
4558 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
4559 | + | |
4560 | +#ifndef FPM_ATOMIC_H | |
4561 | +#define FPM_ATOMIC_H 1 | |
4562 | + | |
4563 | +#if HAVE_INTTYPES_H | |
4564 | +#include <inttypes.h> | |
4565 | +#else | |
4566 | +#include <stdint.h> | |
4567 | +#endif | |
4568 | +#include <sched.h> | |
4569 | + | |
4570 | +#if ( __i386__ || __i386 ) | |
4571 | + | |
4572 | +typedef int32_t atomic_int_t; | |
4573 | +typedef uint32_t atomic_uint_t; | |
4574 | +typedef volatile atomic_uint_t atomic_t; | |
4575 | + | |
4576 | + | |
4577 | +static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add) | |
4578 | +{ | |
4579 | + __asm__ volatile ( "lock;" "xaddl %0, %1;" : | |
4580 | + "+r" (add) : "m" (*value) : "memory"); | |
4581 | + | |
4582 | + return add; | |
4583 | +} | |
4584 | + | |
4585 | +static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) | |
4586 | +{ | |
4587 | + unsigned char res; | |
4588 | + | |
4589 | + __asm__ volatile ( "lock;" "cmpxchgl %3, %1;" "sete %0;" : | |
4590 | + "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory"); | |
4591 | + | |
4592 | + return res; | |
4593 | +} | |
4594 | + | |
4595 | +#elif ( __amd64__ || __amd64 ) | |
4596 | + | |
4597 | +typedef int64_t atomic_int_t; | |
4598 | +typedef uint64_t atomic_uint_t; | |
4599 | +typedef volatile atomic_uint_t atomic_t; | |
4600 | + | |
4601 | +static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add) | |
4602 | +{ | |
4603 | + __asm__ volatile ( "lock;" "xaddq %0, %1;" : | |
4604 | + "+r" (add) : "m" (*value) : "memory"); | |
4605 | + | |
4606 | + return add; | |
4607 | +} | |
4608 | + | |
4609 | +static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) | |
4610 | +{ | |
4611 | + unsigned char res; | |
4612 | + | |
4613 | + __asm__ volatile ( "lock;" "cmpxchgq %3, %1;" "sete %0;" : | |
4614 | + "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory"); | |
4615 | + | |
4616 | + return res; | |
4617 | +} | |
4618 | + | |
4619 | +#if (__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)) | |
4620 | + | |
4621 | +#elif ( __arm__ || __arm ) /* W-Mark Kubacki */ | |
4622 | + | |
4623 | +#if (__arch64__ || __arch64) | |
4624 | +typedef int64_t atomic_int_t; | |
4625 | +typedef uint64_t atomic_uint_t; | |
4626 | +#else | |
4627 | +typedef int32_t atomic_int_t; | |
4628 | +typedef uint32_t atomic_uint_t; | |
4629 | +#endif | |
4630 | + | |
4631 | +#define atomic_cmp_set(a,b,c) __sync_bool_compare_and_swap(a,b,c) | |
4632 | + | |
4633 | +#endif /* defined (__GNUC__) &&... */ | |
4634 | + | |
4635 | +#elif ( __sparc__ || __sparc ) /* Marcin Ochab */ | |
4636 | + | |
4637 | +#if (__arch64__ || __arch64) | |
4638 | +typedef uint64_t atomic_uint_t; | |
4639 | +typedef volatile atomic_uint_t atomic_t; | |
4640 | + | |
4641 | +static inline int atomic_cas_64(atomic_t *lock, atomic_uint_t old, atomic_uint_t new) | |
4642 | +{ | |
4643 | + __asm__ __volatile__("casx [%2], %3, %0 " : "=&r"(new) : "0"(new), "r"(lock), "r"(old): "memory"); | |
4644 | + | |
4645 | + return new; | |
4646 | +} | |
4647 | + | |
4648 | +static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) | |
4649 | +{ | |
4650 | + return (atomic_cas_64(lock, old, set)==old); | |
4651 | +} | |
4652 | +#else | |
4653 | +typedef uint32_t atomic_uint_t; | |
4654 | +typedef volatile atomic_uint_t atomic_t; | |
4655 | + | |
4656 | +static inline int atomic_cas_32(atomic_t *lock, atomic_uint_t old, atomic_uint_t new) | |
4657 | +{ | |
4658 | + __asm__ __volatile__("cas [%2], %3, %0 " : "=&r"(new) : "0"(new), "r"(lock), "r"(old): "memory"); | |
4659 | + | |
4660 | + return new; | |
4661 | +} | |
4662 | + | |
4663 | +static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set) | |
4664 | +{ | |
4665 | + return (atomic_cas_32(lock, old, set)==old); | |
4666 | +} | |
4667 | +#endif | |
4668 | + | |
4669 | +#else | |
4670 | + | |
4671 | +#error unsupported architecture. please write a patch and send it in | |
4672 | + | |
4673 | +#endif | |
4674 | + | |
4675 | +static inline int fpm_spinlock(atomic_t *lock, int try_once) | |
4676 | +{ | |
4677 | + if (try_once) { | |
4678 | + return atomic_cmp_set(lock, 0, 1) ? 0 : -1; | |
4679 | + } | |
4680 | + | |
4681 | + for (;;) { | |
4682 | + | |
4683 | + if (atomic_cmp_set(lock, 0, 1)) { | |
4684 | + break; | |
4685 | + } | |
4686 | + | |
4687 | + sched_yield(); | |
4688 | + } | |
4689 | + | |
4690 | + return 0; | |
4691 | +} | |
4692 | + | |
4693 | +#endif | |
4694 | + | |
4695 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm.c php-src/sapi/fpm/fpm/fpm.c | |
4696 | --- php-src-vanilla/sapi/fpm/fpm/fpm.c 1970-01-01 01:00:00.000000000 +0100 | |
4697 | +++ php-src/sapi/fpm/fpm/fpm.c 2009-10-18 21:05:39.308376784 +0100 | |
4698 | @@ -0,0 +1,82 @@ | |
4699 | + | |
4700 | + /* $Id$ */ | |
4701 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
4702 | + | |
4703 | +#include "fpm_config.h" | |
4704 | + | |
4705 | +#include <stdlib.h> /* for exit */ | |
4706 | + | |
4707 | +#include "fpm.h" | |
4708 | +#include "fpm_children.h" | |
4709 | +#include "fpm_signals.h" | |
4710 | +#include "fpm_env.h" | |
4711 | +#include "fpm_events.h" | |
4712 | +#include "fpm_cleanup.h" | |
4713 | +#include "fpm_php.h" | |
4714 | +#include "fpm_sockets.h" | |
4715 | +#include "fpm_unix.h" | |
4716 | +#include "fpm_process_ctl.h" | |
4717 | +#include "fpm_conf.h" | |
4718 | +#include "fpm_worker_pool.h" | |
4719 | +#include "fpm_stdio.h" | |
4720 | +#include "zlog.h" | |
4721 | + | |
4722 | +struct fpm_globals_s fpm_globals; | |
4723 | + | |
4724 | +int fpm_init(int argc, char **argv, char *config) | |
4725 | +{ | |
4726 | + fpm_globals.argc = argc; | |
4727 | + fpm_globals.argv = argv; | |
4728 | + fpm_globals.config = config; | |
4729 | + | |
4730 | + if (0 > fpm_php_init_main() || | |
4731 | + 0 > fpm_stdio_init_main() || | |
4732 | + 0 > fpm_conf_init_main() || | |
4733 | + 0 > fpm_unix_init_main() || | |
4734 | + 0 > fpm_env_init_main() || | |
4735 | + 0 > fpm_signals_init_main() || | |
4736 | + 0 > fpm_pctl_init_main() || | |
4737 | + 0 > fpm_children_init_main() || | |
4738 | + 0 > fpm_sockets_init_main() || | |
4739 | + 0 > fpm_worker_pool_init_main() || | |
4740 | + 0 > fpm_event_init_main()) { | |
4741 | + return -1; | |
4742 | + } | |
4743 | + | |
4744 | + if (0 > fpm_conf_write_pid()) { | |
4745 | + return -1; | |
4746 | + } | |
4747 | + | |
4748 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "fpm is running, pid %d", (int) fpm_globals.parent_pid); | |
4749 | + | |
4750 | + return 0; | |
4751 | +} | |
4752 | + | |
4753 | +/* children: return listening socket | |
4754 | + parent: never return */ | |
4755 | +int fpm_run(int *max_requests) | |
4756 | +{ | |
4757 | + struct fpm_worker_pool_s *wp; | |
4758 | + | |
4759 | + /* create initial children in all pools */ | |
4760 | + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { | |
4761 | + int is_parent; | |
4762 | + | |
4763 | + is_parent = fpm_children_create_initial(wp); | |
4764 | + | |
4765 | + if (!is_parent) { | |
4766 | + goto run_child; | |
4767 | + } | |
4768 | + } | |
4769 | + | |
4770 | + /* run event loop forever */ | |
4771 | + fpm_event_loop(); | |
4772 | + | |
4773 | +run_child: /* only workers reach this point */ | |
4774 | + | |
4775 | + fpm_cleanups_run(FPM_CLEANUP_CHILD); | |
4776 | + | |
4777 | + *max_requests = fpm_globals.max_requests; | |
4778 | + return fpm_globals.listening_socket; | |
4779 | +} | |
4780 | + | |
4781 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_children.c php-src/sapi/fpm/fpm/fpm_children.c | |
4782 | --- php-src-vanilla/sapi/fpm/fpm/fpm_children.c 1970-01-01 01:00:00.000000000 +0100 | |
4783 | +++ php-src/sapi/fpm/fpm/fpm_children.c 2009-10-18 21:05:39.308376784 +0100 | |
4784 | @@ -0,0 +1,387 @@ | |
4785 | + | |
4786 | + /* $Id$ */ | |
4787 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
4788 | + | |
4789 | +#include "fpm_config.h" | |
4790 | + | |
4791 | +#include <sys/types.h> | |
4792 | +#include <sys/wait.h> | |
4793 | +#include <time.h> | |
4794 | +#include <unistd.h> | |
4795 | +#include <string.h> | |
4796 | +#include <stdio.h> | |
4797 | + | |
4798 | +#include "fpm.h" | |
4799 | +#include "fpm_children.h" | |
4800 | +#include "fpm_signals.h" | |
4801 | +#include "fpm_worker_pool.h" | |
4802 | +#include "fpm_sockets.h" | |
4803 | +#include "fpm_process_ctl.h" | |
4804 | +#include "fpm_php.h" | |
4805 | +#include "fpm_conf.h" | |
4806 | +#include "fpm_cleanup.h" | |
4807 | +#include "fpm_events.h" | |
4808 | +#include "fpm_clock.h" | |
4809 | +#include "fpm_stdio.h" | |
4810 | +#include "fpm_unix.h" | |
4811 | +#include "fpm_env.h" | |
4812 | +#include "fpm_shm_slots.h" | |
4813 | + | |
4814 | +#include "zlog.h" | |
4815 | + | |
4816 | +static time_t *last_faults; | |
4817 | +static int fault; | |
4818 | + | |
4819 | +static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop); | |
4820 | + | |
4821 | +static void fpm_children_cleanup(int which, void *arg) | |
4822 | +{ | |
4823 | + free(last_faults); | |
4824 | +} | |
4825 | + | |
4826 | +static struct fpm_child_s *fpm_child_alloc() | |
4827 | +{ | |
4828 | + struct fpm_child_s *ret; | |
4829 | + | |
4830 | + ret = malloc(sizeof(struct fpm_child_s)); | |
4831 | + | |
4832 | + if (!ret) { return 0; } | |
4833 | + | |
4834 | + memset(ret, 0, sizeof(*ret)); | |
4835 | + | |
4836 | + return ret; | |
4837 | +} | |
4838 | + | |
4839 | +static void fpm_child_free(struct fpm_child_s *child) | |
4840 | +{ | |
4841 | + free(child); | |
4842 | +} | |
4843 | + | |
4844 | +static void fpm_child_close(struct fpm_child_s *child, int in_event_loop) | |
4845 | +{ | |
4846 | + if (child->fd_stdout != -1) { | |
4847 | + if (in_event_loop) { | |
4848 | + fpm_event_fire(&child->ev_stdout); | |
4849 | + } | |
4850 | + if (child->fd_stdout != -1) { | |
4851 | + close(child->fd_stdout); | |
4852 | + } | |
4853 | + } | |
4854 | + | |
4855 | + if (child->fd_stderr != -1) { | |
4856 | + if (in_event_loop) { | |
4857 | + fpm_event_fire(&child->ev_stderr); | |
4858 | + } | |
4859 | + if (child->fd_stderr != -1) { | |
4860 | + close(child->fd_stderr); | |
4861 | + } | |
4862 | + } | |
4863 | + | |
4864 | + fpm_child_free(child); | |
4865 | +} | |
4866 | + | |
4867 | +static void fpm_child_link(struct fpm_child_s *child) | |
4868 | +{ | |
4869 | + struct fpm_worker_pool_s *wp = child->wp; | |
4870 | + | |
4871 | + ++wp->running_children; | |
4872 | + ++fpm_globals.running_children; | |
4873 | + | |
4874 | + child->next = wp->children; | |
4875 | + if (child->next) { child->next->prev = child; } | |
4876 | + child->prev = 0; | |
4877 | + wp->children = child; | |
4878 | +} | |
4879 | + | |
4880 | +static void fpm_child_unlink(struct fpm_child_s *child) | |
4881 | +{ | |
4882 | + --child->wp->running_children; | |
4883 | + --fpm_globals.running_children; | |
4884 | + | |
4885 | + if (child->prev) { child->prev->next = child->next; } | |
4886 | + else { child->wp->children = child->next; } | |
4887 | + if (child->next) { child->next->prev = child->prev; } | |
4888 | + | |
4889 | +} | |
4890 | + | |
4891 | +static struct fpm_child_s *fpm_child_find(pid_t pid) | |
4892 | +{ | |
4893 | + struct fpm_worker_pool_s *wp; | |
4894 | + struct fpm_child_s *child = 0; | |
4895 | + | |
4896 | + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { | |
4897 | + | |
4898 | + for (child = wp->children; child; child = child->next) { | |
4899 | + if (child->pid == pid) { | |
4900 | + break; | |
4901 | + } | |
4902 | + } | |
4903 | + | |
4904 | + if (child) { | |
4905 | + break; | |
4906 | + } | |
4907 | + } | |
4908 | + | |
4909 | + if (!child) { | |
4910 | + return 0; | |
4911 | + } | |
4912 | + | |
4913 | + return child; | |
4914 | +} | |
4915 | + | |
4916 | +static void fpm_child_init(struct fpm_worker_pool_s *wp) | |
4917 | +{ | |
4918 | + fpm_globals.max_requests = wp->config->max_requests; | |
4919 | + | |
4920 | + if (0 > fpm_stdio_init_child(wp) || | |
4921 | + 0 > fpm_unix_init_child(wp) || | |
4922 | + 0 > fpm_signals_init_child() || | |
4923 | + 0 > fpm_env_init_child(wp) || | |
4924 | + 0 > fpm_php_init_child(wp)) { | |
4925 | + | |
4926 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "child failed to initialize (pool %s)", wp->config->name); | |
4927 | + exit(255); | |
4928 | + } | |
4929 | +} | |
4930 | + | |
4931 | +int fpm_children_free(struct fpm_child_s *child) | |
4932 | +{ | |
4933 | + struct fpm_child_s *next; | |
4934 | + | |
4935 | + for (; child; child = next) { | |
4936 | + next = child->next; | |
4937 | + fpm_child_close(child, 0 /* in_event_loop */); | |
4938 | + } | |
4939 | + | |
4940 | + return 0; | |
4941 | +} | |
4942 | + | |
4943 | +void fpm_children_bury() | |
4944 | +{ | |
4945 | + int status; | |
4946 | + pid_t pid; | |
4947 | + struct fpm_child_s *child; | |
4948 | + | |
4949 | + while ( (pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) { | |
4950 | + char buf[128]; | |
4951 | + int severity = ZLOG_NOTICE; | |
4952 | + | |
4953 | + child = fpm_child_find(pid); | |
4954 | + | |
4955 | + if (WIFEXITED(status)) { | |
4956 | + | |
4957 | + snprintf(buf, sizeof(buf), "with code %d", WEXITSTATUS(status)); | |
4958 | + | |
4959 | + if (WEXITSTATUS(status) != 0) { | |
4960 | + severity = ZLOG_WARNING; | |
4961 | + } | |
4962 | + | |
4963 | + } | |
4964 | + else if (WIFSIGNALED(status)) { | |
4965 | + const char *signame = fpm_signal_names[WTERMSIG(status)]; | |
4966 | + const char *have_core = WCOREDUMP(status) ? " (core dumped)" : ""; | |
4967 | + | |
4968 | + if (signame == NULL) { | |
4969 | + signame = ""; | |
4970 | + } | |
4971 | + | |
4972 | + snprintf(buf, sizeof(buf), "on signal %d %s%s", WTERMSIG(status), signame, have_core); | |
4973 | + | |
4974 | + if (WTERMSIG(status) != SIGQUIT) { /* possible request loss */ | |
4975 | + severity = ZLOG_WARNING; | |
4976 | + } | |
4977 | + } | |
4978 | + else if (WIFSTOPPED(status)) { | |
4979 | + | |
4980 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "child %d stopped for tracing", (int) pid); | |
4981 | + | |
4982 | + if (child && child->tracer) { | |
4983 | + child->tracer(child); | |
4984 | + } | |
4985 | + | |
4986 | + continue; | |
4987 | + } | |
4988 | + | |
4989 | + if (child) { | |
4990 | + struct fpm_worker_pool_s *wp = child->wp; | |
4991 | + struct timeval tv1, tv2; | |
4992 | + | |
4993 | + fpm_child_unlink(child); | |
4994 | + | |
4995 | + fpm_shm_slots_discard_slot(child); | |
4996 | + | |
4997 | + fpm_clock_get(&tv1); | |
4998 | + | |
4999 | + timersub(&tv1, &child->started, &tv2); | |
5000 | + | |
5001 | + zlog(ZLOG_STUFF, severity, "child %d (pool %s) exited %s after %ld.%06d seconds from start", (int) pid, | |
5002 | + child->wp->config->name, buf, tv2.tv_sec, (int) tv2.tv_usec); | |
5003 | + | |
5004 | + fpm_child_close(child, 1 /* in event_loop */); | |
5005 | + | |
5006 | + fpm_pctl_child_exited(); | |
5007 | + | |
5008 | + if (last_faults && (WTERMSIG(status) == SIGSEGV || WTERMSIG(status) == SIGBUS)) { | |
5009 | + time_t now = tv1.tv_sec; | |
5010 | + int restart_condition = 1; | |
5011 | + int i; | |
5012 | + | |
5013 | + last_faults[fault++] = now; | |
5014 | + | |
5015 | + if (fault == fpm_global_config.emergency_restart_threshold) { | |
5016 | + fault = 0; | |
5017 | + } | |
5018 | + | |
5019 | + for (i = 0; i < fpm_global_config.emergency_restart_threshold; i++) { | |
5020 | + if (now - last_faults[i] > fpm_global_config.emergency_restart_interval) { | |
5021 | + restart_condition = 0; | |
5022 | + break; | |
5023 | + } | |
5024 | + } | |
5025 | + | |
5026 | + if (restart_condition) { | |
5027 | + | |
5028 | + zlog(ZLOG_STUFF, ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload", | |
5029 | + fpm_global_config.emergency_restart_threshold, fpm_global_config.emergency_restart_interval); | |
5030 | + | |
5031 | + fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET); | |
5032 | + } | |
5033 | + } | |
5034 | + | |
5035 | + fpm_children_make(wp, 1 /* in event loop */); | |
5036 | + | |
5037 | + if (fpm_globals.is_child) { | |
5038 | + break; | |
5039 | + } | |
5040 | + } | |
5041 | + else { | |
5042 | + zlog(ZLOG_STUFF, ZLOG_ALERT, "oops, unknown child exited %s", buf); | |
5043 | + } | |
5044 | + } | |
5045 | + | |
5046 | +} | |
5047 | + | |
5048 | +static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) | |
5049 | +{ | |
5050 | + struct fpm_child_s *c; | |
5051 | + | |
5052 | + c = fpm_child_alloc(); | |
5053 | + | |
5054 | + if (!c) { | |
5055 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "malloc failed (pool %s)", wp->config->name); | |
5056 | + return 0; | |
5057 | + } | |
5058 | + | |
5059 | + c->wp = wp; | |
5060 | + c->fd_stdout = -1; c->fd_stderr = -1; | |
5061 | + | |
5062 | + if (0 > fpm_stdio_prepare_pipes(c)) { | |
5063 | + fpm_child_free(c); | |
5064 | + return 0; | |
5065 | + } | |
5066 | + | |
5067 | + if (0 > fpm_shm_slots_prepare_slot(c)) { | |
5068 | + fpm_stdio_discard_pipes(c); | |
5069 | + fpm_child_free(c); | |
5070 | + return 0; | |
5071 | + } | |
5072 | + | |
5073 | + return c; | |
5074 | +} | |
5075 | + | |
5076 | +static void fpm_resources_discard(struct fpm_child_s *child) | |
5077 | +{ | |
5078 | + fpm_shm_slots_discard_slot(child); | |
5079 | + fpm_stdio_discard_pipes(child); | |
5080 | + fpm_child_free(child); | |
5081 | +} | |
5082 | + | |
5083 | +static void fpm_child_resources_use(struct fpm_child_s *child) | |
5084 | +{ | |
5085 | + fpm_shm_slots_child_use_slot(child); | |
5086 | + fpm_stdio_child_use_pipes(child); | |
5087 | + fpm_child_free(child); | |
5088 | +} | |
5089 | + | |
5090 | +static void fpm_parent_resources_use(struct fpm_child_s *child) | |
5091 | +{ | |
5092 | + fpm_shm_slots_parent_use_slot(child); | |
5093 | + fpm_stdio_parent_use_pipes(child); | |
5094 | + fpm_child_link(child); | |
5095 | +} | |
5096 | + | |
5097 | +static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop) | |
5098 | +{ | |
5099 | + int enough = 0; | |
5100 | + pid_t pid; | |
5101 | + struct fpm_child_s *child; | |
5102 | + | |
5103 | + while (!enough && fpm_pctl_can_spawn_children() && wp->running_children < wp->config->pm->max_children) { | |
5104 | + | |
5105 | + child = fpm_resources_prepare(wp); | |
5106 | + | |
5107 | + if (!child) { | |
5108 | + enough = 1; | |
5109 | + break; | |
5110 | + } | |
5111 | + | |
5112 | + pid = fork(); | |
5113 | + | |
5114 | + switch (pid) { | |
5115 | + | |
5116 | + case 0 : | |
5117 | + fpm_child_resources_use(child); | |
5118 | + fpm_globals.is_child = 1; | |
5119 | + if (in_event_loop) { | |
5120 | + fpm_event_exit_loop(); | |
5121 | + } | |
5122 | + fpm_child_init(wp); | |
5123 | + return 0; | |
5124 | + | |
5125 | + case -1 : | |
5126 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fork() failed"); | |
5127 | + enough = 1; | |
5128 | + | |
5129 | + fpm_resources_discard(child); | |
5130 | + | |
5131 | + break; /* dont try any more on error */ | |
5132 | + | |
5133 | + default : | |
5134 | + child->pid = pid; | |
5135 | + fpm_clock_get(&child->started); | |
5136 | + fpm_parent_resources_use(child); | |
5137 | + | |
5138 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "child %d (pool %s) started", (int) pid, wp->config->name); | |
5139 | + } | |
5140 | + | |
5141 | + } | |
5142 | + | |
5143 | + return 1; /* we are done */ | |
5144 | +} | |
5145 | + | |
5146 | +int fpm_children_create_initial(struct fpm_worker_pool_s *wp) | |
5147 | +{ | |
5148 | + return fpm_children_make(wp, 0 /* not in event loop yet */); | |
5149 | +} | |
5150 | + | |
5151 | +int fpm_children_init_main() | |
5152 | +{ | |
5153 | + if (fpm_global_config.emergency_restart_threshold && | |
5154 | + fpm_global_config.emergency_restart_interval) { | |
5155 | + | |
5156 | + last_faults = malloc(sizeof(time_t) * fpm_global_config.emergency_restart_threshold); | |
5157 | + | |
5158 | + if (!last_faults) { | |
5159 | + return -1; | |
5160 | + } | |
5161 | + | |
5162 | + memset(last_faults, 0, sizeof(time_t) * fpm_global_config.emergency_restart_threshold); | |
5163 | + } | |
5164 | + | |
5165 | + if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_children_cleanup, 0)) { | |
5166 | + return -1; | |
5167 | + } | |
5168 | + | |
5169 | + return 0; | |
5170 | +} | |
5171 | + | |
5172 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_children.h php-src/sapi/fpm/fpm/fpm_children.h | |
5173 | --- php-src-vanilla/sapi/fpm/fpm/fpm_children.h 1970-01-01 01:00:00.000000000 +0100 | |
5174 | +++ php-src/sapi/fpm/fpm/fpm_children.h 2009-10-18 21:05:39.308376784 +0100 | |
5175 | @@ -0,0 +1,33 @@ | |
5176 | + | |
5177 | + /* $Id$ */ | |
5178 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
5179 | + | |
5180 | +#ifndef FPM_CHILDREN_H | |
5181 | +#define FPM_CHILDREN_H 1 | |
5182 | + | |
5183 | +#include <sys/time.h> | |
5184 | +#include <sys/types.h> | |
5185 | +#include <event.h> | |
5186 | + | |
5187 | +#include "fpm_worker_pool.h" | |
5188 | + | |
5189 | +int fpm_children_create_initial(struct fpm_worker_pool_s *wp); | |
5190 | +int fpm_children_free(struct fpm_child_s *child); | |
5191 | +void fpm_children_bury(); | |
5192 | +int fpm_children_init_main(); | |
5193 | + | |
5194 | +struct fpm_child_s; | |
5195 | + | |
5196 | +struct fpm_child_s { | |
5197 | + struct fpm_child_s *prev, *next; | |
5198 | + struct timeval started; | |
5199 | + struct fpm_worker_pool_s *wp; | |
5200 | + struct event ev_stdout, ev_stderr; | |
5201 | + int shm_slot_i; | |
5202 | + int fd_stdout, fd_stderr; | |
5203 | + void (*tracer)(struct fpm_child_s *); | |
5204 | + struct timeval slow_logged; | |
5205 | + pid_t pid; | |
5206 | +}; | |
5207 | + | |
5208 | +#endif | |
5209 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_cleanup.c php-src/sapi/fpm/fpm/fpm_cleanup.c | |
5210 | --- php-src-vanilla/sapi/fpm/fpm/fpm_cleanup.c 1970-01-01 01:00:00.000000000 +0100 | |
5211 | +++ php-src/sapi/fpm/fpm/fpm_cleanup.c 2009-10-18 21:05:39.310440424 +0100 | |
5212 | @@ -0,0 +1,51 @@ | |
5213 | + | |
5214 | + /* $Id$ */ | |
5215 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
5216 | + | |
5217 | +#include "fpm_config.h" | |
5218 | + | |
5219 | +#include <stdlib.h> | |
5220 | + | |
5221 | +#include "fpm_arrays.h" | |
5222 | +#include "fpm_cleanup.h" | |
5223 | +#include "zlog.h" | |
5224 | + | |
5225 | +struct cleanup_s { | |
5226 | + int type; | |
5227 | + void (*cleanup)(int, void *); | |
5228 | + void *arg; | |
5229 | +}; | |
5230 | + | |
5231 | +static struct fpm_array_s cleanups = { .sz = sizeof(struct cleanup_s) }; | |
5232 | + | |
5233 | +int fpm_cleanup_add(int type, void (*cleanup)(int, void *), void *arg) | |
5234 | +{ | |
5235 | + struct cleanup_s *c; | |
5236 | + | |
5237 | + c = fpm_array_push(&cleanups); | |
5238 | + | |
5239 | + if (!c) { | |
5240 | + return -1; | |
5241 | + } | |
5242 | + | |
5243 | + c->type = type; | |
5244 | + c->cleanup = cleanup; | |
5245 | + c->arg = arg; | |
5246 | + | |
5247 | + return 0; | |
5248 | +} | |
5249 | + | |
5250 | +void fpm_cleanups_run(int type) | |
5251 | +{ | |
5252 | + struct cleanup_s *c = fpm_array_item_last(&cleanups); | |
5253 | + int cl = cleanups.used; | |
5254 | + | |
5255 | + for ( ; cl--; c--) { | |
5256 | + if (c->type & type) { | |
5257 | + c->cleanup(type, c->arg); | |
5258 | + } | |
5259 | + } | |
5260 | + | |
5261 | + fpm_array_free(&cleanups); | |
5262 | +} | |
5263 | + | |
5264 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_cleanup.h php-src/sapi/fpm/fpm/fpm_cleanup.h | |
5265 | --- php-src-vanilla/sapi/fpm/fpm/fpm_cleanup.h 1970-01-01 01:00:00.000000000 +0100 | |
5266 | +++ php-src/sapi/fpm/fpm/fpm_cleanup.h 2009-10-18 21:05:39.308376784 +0100 | |
5267 | @@ -0,0 +1,21 @@ | |
5268 | + | |
5269 | + /* $Id$ */ | |
5270 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
5271 | + | |
5272 | +#ifndef FPM_CLEANUP_H | |
5273 | +#define FPM_CLEANUP_H 1 | |
5274 | + | |
5275 | +int fpm_cleanup_add(int type, void (*cleanup)(int, void *), void *); | |
5276 | +void fpm_cleanups_run(int type); | |
5277 | + | |
5278 | +enum { | |
5279 | + FPM_CLEANUP_CHILD = (1 << 0), | |
5280 | + FPM_CLEANUP_PARENT_EXIT = (1 << 1), | |
5281 | + FPM_CLEANUP_PARENT_EXIT_MAIN = (1 << 2), | |
5282 | + FPM_CLEANUP_PARENT_EXEC = (1 << 3), | |
5283 | + FPM_CLEANUP_PARENT = (1 << 1) | (1 << 2) | (1 << 3), | |
5284 | + FPM_CLEANUP_ALL = ~0, | |
5285 | +}; | |
5286 | + | |
5287 | +#endif | |
5288 | + | |
5289 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_clock.c php-src/sapi/fpm/fpm/fpm_clock.c | |
5290 | --- php-src-vanilla/sapi/fpm/fpm/fpm_clock.c 1970-01-01 01:00:00.000000000 +0100 | |
5291 | +++ php-src/sapi/fpm/fpm/fpm_clock.c 2009-10-18 21:05:39.308376784 +0100 | |
5292 | @@ -0,0 +1,115 @@ | |
5293 | + | |
5294 | + /* $Id$ */ | |
5295 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
5296 | + | |
5297 | +#include "fpm_config.h" | |
5298 | + | |
5299 | +#if defined(HAVE_CLOCK_GETTIME) | |
5300 | +#include <time.h> /* for CLOCK_MONOTONIC */ | |
5301 | +#endif | |
5302 | + | |
5303 | +#include "fpm_clock.h" | |
5304 | +#include "zlog.h" | |
5305 | + | |
5306 | + | |
5307 | +/* posix monotonic clock - preferred source of time */ | |
5308 | +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) | |
5309 | + | |
5310 | +static int monotonic_works; | |
5311 | + | |
5312 | +int fpm_clock_init() | |
5313 | +{ | |
5314 | + struct timespec ts; | |
5315 | + | |
5316 | + monotonic_works = 0; | |
5317 | + | |
5318 | + if (0 == clock_gettime(CLOCK_MONOTONIC, &ts)) { | |
5319 | + monotonic_works = 1; | |
5320 | + } | |
5321 | + | |
5322 | + return 0; | |
5323 | +} | |
5324 | + | |
5325 | +int fpm_clock_get(struct timeval *tv) | |
5326 | +{ | |
5327 | + if (monotonic_works) { | |
5328 | + struct timespec ts; | |
5329 | + | |
5330 | + if (0 > clock_gettime(CLOCK_MONOTONIC, &ts)) { | |
5331 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "clock_gettime() failed"); | |
5332 | + return -1; | |
5333 | + } | |
5334 | + | |
5335 | + tv->tv_sec = ts.tv_sec; | |
5336 | + tv->tv_usec = ts.tv_nsec / 1000; | |
5337 | + return 0; | |
5338 | + } | |
5339 | + | |
5340 | + return gettimeofday(tv, 0); | |
5341 | +} | |
5342 | + | |
5343 | +/* macosx clock */ | |
5344 | +#elif defined(HAVE_CLOCK_GET_TIME) | |
5345 | + | |
5346 | +#include <mach/mach.h> | |
5347 | +#include <mach/clock.h> | |
5348 | +#include <mach/mach_error.h> | |
5349 | + | |
5350 | +static clock_serv_t mach_clock; | |
5351 | + | |
5352 | +/* this code borrowed from here: http://lists.apple.com/archives/Darwin-development/2002/Mar/msg00746.html */ | |
5353 | +/* mach_clock also should be re-initialized in child process after fork */ | |
5354 | +int fpm_clock_init() | |
5355 | +{ | |
5356 | + kern_return_t ret; | |
5357 | + mach_timespec_t aTime; | |
5358 | + | |
5359 | + ret = host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &mach_clock); | |
5360 | + | |
5361 | + if (ret != KERN_SUCCESS) { | |
5362 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "host_get_clock_service() failed: %s", mach_error_string(ret)); | |
5363 | + return -1; | |
5364 | + } | |
5365 | + | |
5366 | + /* test if it works */ | |
5367 | + ret = clock_get_time(mach_clock, &aTime); | |
5368 | + | |
5369 | + if (ret != KERN_SUCCESS) { | |
5370 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret)); | |
5371 | + return -1; | |
5372 | + } | |
5373 | + | |
5374 | + return 0; | |
5375 | +} | |
5376 | + | |
5377 | +int fpm_clock_get(struct timeval *tv) | |
5378 | +{ | |
5379 | + kern_return_t ret; | |
5380 | + mach_timespec_t aTime; | |
5381 | + | |
5382 | + ret = clock_get_time(mach_clock, &aTime); | |
5383 | + | |
5384 | + if (ret != KERN_SUCCESS) { | |
5385 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret)); | |
5386 | + return -1; | |
5387 | + } | |
5388 | + | |
5389 | + tv->tv_sec = aTime.tv_sec; | |
5390 | + tv->tv_usec = aTime.tv_nsec / 1000; | |
5391 | + | |
5392 | + return 0; | |
5393 | +} | |
5394 | + | |
5395 | +#else /* no clock */ | |
5396 | + | |
5397 | +int fpm_clock_init() | |
5398 | +{ | |
5399 | + return 0; | |
5400 | +} | |
5401 | + | |
5402 | +int fpm_clock_get(struct timeval *tv) | |
5403 | +{ | |
5404 | + return gettimeofday(tv, 0); | |
5405 | +} | |
5406 | + | |
5407 | +#endif | |
5408 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_clock.h php-src/sapi/fpm/fpm/fpm_clock.h | |
5409 | --- php-src-vanilla/sapi/fpm/fpm/fpm_clock.h 1970-01-01 01:00:00.000000000 +0100 | |
5410 | +++ php-src/sapi/fpm/fpm/fpm_clock.h 2009-10-18 21:05:39.310440424 +0100 | |
5411 | @@ -0,0 +1,13 @@ | |
5412 | + | |
5413 | + /* $Id$ */ | |
5414 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
5415 | + | |
5416 | +#ifndef FPM_CLOCK_H | |
5417 | +#define FPM_CLOCK_H 1 | |
5418 | + | |
5419 | +#include <sys/time.h> | |
5420 | + | |
5421 | +int fpm_clock_init(); | |
5422 | +int fpm_clock_get(struct timeval *tv); | |
5423 | + | |
5424 | +#endif | |
5425 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_conf.c php-src/sapi/fpm/fpm/fpm_conf.c | |
5426 | --- php-src-vanilla/sapi/fpm/fpm/fpm_conf.c 1970-01-01 01:00:00.000000000 +0100 | |
5427 | +++ php-src/sapi/fpm/fpm/fpm_conf.c 2009-10-18 21:05:39.310440424 +0100 | |
5428 | @@ -0,0 +1,537 @@ | |
5429 | + | |
5430 | + /* $Id$ */ | |
5431 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
5432 | + | |
5433 | +#include "fpm_config.h" | |
5434 | + | |
5435 | +#include <sys/types.h> | |
5436 | +#include <sys/stat.h> | |
5437 | +#include <fcntl.h> | |
5438 | +#include <string.h> | |
5439 | +#include <stdlib.h> | |
5440 | +#include <stddef.h> | |
5441 | +#if HAVE_INTTYPES_H | |
5442 | +#include <inttypes.h> | |
5443 | +#else | |
5444 | +#include <stdint.h> | |
5445 | +#endif | |
5446 | + | |
5447 | +#include <stdio.h> | |
5448 | +#include <unistd.h> | |
5449 | + | |
5450 | +#include "fpm.h" | |
5451 | +#include "fpm_conf.h" | |
5452 | +#include "fpm_stdio.h" | |
5453 | +#include "fpm_worker_pool.h" | |
5454 | +#include "fpm_cleanup.h" | |
5455 | +#include "fpm_php.h" | |
5456 | +#include "fpm_sockets.h" | |
5457 | +#include "xml_config.h" | |
5458 | +#include "zlog.h" | |
5459 | + | |
5460 | + | |
5461 | +struct fpm_global_config_s fpm_global_config; | |
5462 | + | |
5463 | +static void *fpm_global_config_ptr() | |
5464 | +{ | |
5465 | + return &fpm_global_config; | |
5466 | +} | |
5467 | + | |
5468 | +static char *fpm_conf_set_log_level(void **conf, char *name, void *vv, intptr_t offset) | |
5469 | +{ | |
5470 | + char *value = vv; | |
5471 | + | |
5472 | + if (!strcmp(value, "debug")) { | |
5473 | + fpm_globals.log_level = ZLOG_DEBUG; | |
5474 | + } | |
5475 | + else if (!strcmp(value, "notice")) { | |
5476 | + fpm_globals.log_level = ZLOG_NOTICE; | |
5477 | + } | |
5478 | + else if (!strcmp(value, "warn")) { | |
5479 | + fpm_globals.log_level = ZLOG_WARNING; | |
5480 | + } | |
5481 | + else if (!strcmp(value, "error")) { | |
5482 | + fpm_globals.log_level = ZLOG_ERROR; | |
5483 | + } | |
5484 | + else if (!strcmp(value, "alert")) { | |
5485 | + fpm_globals.log_level = ZLOG_ALERT; | |
5486 | + } | |
5487 | + else { | |
5488 | + return "invalid value for 'log_level'"; | |
5489 | + } | |
5490 | + | |
5491 | + return NULL; | |
5492 | +} | |
5493 | + | |
5494 | +static struct xml_conf_section xml_section_fpm_global_options = { | |
5495 | + .conf = &fpm_global_config_ptr, | |
5496 | + .path = "/configuration/global_options", | |
5497 | + .parsers = (struct xml_value_parser []) { | |
5498 | + { XML_CONF_SCALAR, "emergency_restart_threshold", &xml_conf_set_slot_integer, offsetof(struct fpm_global_config_s, emergency_restart_threshold) }, | |
5499 | + { XML_CONF_SCALAR, "emergency_restart_interval", &xml_conf_set_slot_time, offsetof(struct fpm_global_config_s, emergency_restart_interval) }, | |
5500 | + { XML_CONF_SCALAR, "process_control_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_global_config_s, process_control_timeout) }, | |
5501 | + { XML_CONF_SCALAR, "daemonize", &xml_conf_set_slot_boolean, offsetof(struct fpm_global_config_s, daemonize) }, | |
5502 | + { XML_CONF_SCALAR, "pid_file", &xml_conf_set_slot_string, offsetof(struct fpm_global_config_s, pid_file) }, | |
5503 | + { XML_CONF_SCALAR, "error_log", &xml_conf_set_slot_string, offsetof(struct fpm_global_config_s, error_log) }, | |
5504 | + { XML_CONF_SCALAR, "log_level", &fpm_conf_set_log_level, 0 }, | |
5505 | + { 0, 0, 0, 0 } | |
5506 | + } | |
5507 | +}; | |
5508 | + | |
5509 | +static char *fpm_conf_set_pm_style(void **conf, char *name, void *vv, intptr_t offset) | |
5510 | +{ | |
5511 | + char *value = vv; | |
5512 | + struct fpm_pm_s *c = *conf; | |
5513 | + | |
5514 | + if (!strcmp(value, "static")) { | |
5515 | + c->style = PM_STYLE_STATIC; | |
5516 | + } | |
5517 | + else if (!strcmp(value, "apache-like")) { | |
5518 | + c->style = PM_STYLE_APACHE_LIKE; | |
5519 | + } | |
5520 | + else { | |
5521 | + return "invalid value for 'style'"; | |
5522 | + } | |
5523 | + | |
5524 | + return NULL; | |
5525 | +} | |
5526 | + | |
5527 | +static char *fpm_conf_set_rlimit_core(void **conf, char *name, void *vv, intptr_t offset) | |
5528 | +{ | |
5529 | + char *value = vv; | |
5530 | + struct fpm_worker_pool_config_s *c = *conf; | |
5531 | + | |
5532 | + if (!strcmp(value, "unlimited")) { | |
5533 | + c->rlimit_core = -1; | |
5534 | + } | |
5535 | + else { | |
5536 | + int int_value; | |
5537 | + void *subconf = &int_value; | |
5538 | + char *error; | |
5539 | + | |
5540 | + error = xml_conf_set_slot_integer(&subconf, name, vv, 0); | |
5541 | + | |
5542 | + if (error) { return error; } | |
5543 | + | |
5544 | + if (int_value < 0) { return "invalid value for 'rlimit_core'"; } | |
5545 | + | |
5546 | + c->rlimit_core = int_value; | |
5547 | + } | |
5548 | + | |
5549 | + return NULL; | |
5550 | +} | |
5551 | + | |
5552 | +static char *fpm_conf_set_catch_workers_output(void **conf, char *name, void *vv, intptr_t offset) | |
5553 | +{ | |
5554 | + struct fpm_worker_pool_config_s *c = *conf; | |
5555 | + int int_value; | |
5556 | + void *subconf = &int_value; | |
5557 | + char *error; | |
5558 | + | |
5559 | + error = xml_conf_set_slot_boolean(&subconf, name, vv, 0); | |
5560 | + | |
5561 | + if (error) { return error; } | |
5562 | + | |
5563 | + c->catch_workers_output = int_value; | |
5564 | + | |
5565 | + return NULL; | |
5566 | +} | |
5567 | + | |
5568 | +static struct xml_conf_section fpm_conf_set_apache_like_subsection_conf = { | |
5569 | + .path = "apache_like somewhere", /* fixme */ | |
5570 | + .parsers = (struct xml_value_parser []) { | |
5571 | + { XML_CONF_SCALAR, "StartServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.StartServers) }, | |
5572 | + { XML_CONF_SCALAR, "MinSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MinSpareServers) }, | |
5573 | + { XML_CONF_SCALAR, "MaxSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MaxSpareServers) }, | |
5574 | + { 0, 0, 0, 0 } | |
5575 | + } | |
5576 | +}; | |
5577 | + | |
5578 | +static char *fpm_conf_set_apache_like_subsection(void **conf, char *name, void *xml_node, intptr_t offset) | |
5579 | +{ | |
5580 | + return xml_conf_parse_section(conf, &fpm_conf_set_apache_like_subsection_conf, xml_node); | |
5581 | +} | |
5582 | + | |
5583 | +static struct xml_conf_section fpm_conf_set_listen_options_subsection_conf = { | |
5584 | + .path = "listen options somewhere", /* fixme */ | |
5585 | + .parsers = (struct xml_value_parser []) { | |
5586 | + { XML_CONF_SCALAR, "backlog", &xml_conf_set_slot_integer, offsetof(struct fpm_listen_options_s, backlog) }, | |
5587 | + { XML_CONF_SCALAR, "owner", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, owner) }, | |
5588 | + { XML_CONF_SCALAR, "group", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, group) }, | |
5589 | + { XML_CONF_SCALAR, "mode", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, mode) }, | |
5590 | + { 0, 0, 0, 0 } | |
5591 | + } | |
5592 | +}; | |
5593 | + | |
5594 | +static char *fpm_conf_set_listen_options_subsection(void **conf, char *name, void *xml_node, intptr_t offset) | |
5595 | +{ | |
5596 | + void *subconf = (char *) *conf + offset; | |
5597 | + struct fpm_listen_options_s *lo; | |
5598 | + | |
5599 | + lo = malloc(sizeof(*lo)); | |
5600 | + | |
5601 | + if (!lo) { | |
5602 | + return "malloc() failed"; | |
5603 | + } | |
5604 | + | |
5605 | + memset(lo, 0, sizeof(*lo)); | |
5606 | + | |
5607 | + lo->backlog = -1; | |
5608 | + | |
5609 | + * (struct fpm_listen_options_s **) subconf = lo; | |
5610 | + | |
5611 | + subconf = lo; | |
5612 | + | |
5613 | + return xml_conf_parse_section(&subconf, &fpm_conf_set_listen_options_subsection_conf, xml_node); | |
5614 | +} | |
5615 | + | |
5616 | +static struct xml_conf_section fpm_conf_set_pm_subsection_conf = { | |
5617 | + .path = "pm settings somewhere", /* fixme */ | |
5618 | + .parsers = (struct xml_value_parser []) { | |
5619 | + { XML_CONF_SCALAR, "style", &fpm_conf_set_pm_style, 0 }, | |
5620 | + { XML_CONF_SCALAR, "max_children", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, max_children) }, | |
5621 | + { XML_CONF_SUBSECTION, "apache_like", &fpm_conf_set_apache_like_subsection, offsetof(struct fpm_pm_s, options_apache_like) }, | |
5622 | + { 0, 0, 0, 0 } | |
5623 | + } | |
5624 | +}; | |
5625 | + | |
5626 | +static char *fpm_conf_set_pm_subsection(void **conf, char *name, void *xml_node, intptr_t offset) | |
5627 | +{ | |
5628 | + void *subconf = (char *) *conf + offset; | |
5629 | + struct fpm_pm_s *pm; | |
5630 | + | |
5631 | + pm = malloc(sizeof(*pm)); | |
5632 | + | |
5633 | + if (!pm) { | |
5634 | + return "fpm_conf_set_pm_subsection(): malloc failed"; | |
5635 | + } | |
5636 | + | |
5637 | + memset(pm, 0, sizeof(*pm)); | |
5638 | + | |
5639 | + * (struct fpm_pm_s **) subconf = pm; | |
5640 | + | |
5641 | + subconf = pm; | |
5642 | + | |
5643 | + return xml_conf_parse_section(&subconf, &fpm_conf_set_pm_subsection_conf, xml_node); | |
5644 | +} | |
5645 | + | |
5646 | +static char *xml_conf_set_slot_key_value_pair(void **conf, char *name, void *vv, intptr_t offset) | |
5647 | +{ | |
5648 | + char *value = vv; | |
5649 | + struct key_value_s *kv; | |
5650 | + struct key_value_s ***parent = (struct key_value_s ***) conf; | |
5651 | + | |
5652 | + kv = malloc(sizeof(*kv)); | |
5653 | + | |
5654 | + if (!kv) { | |
5655 | + return "malloc() failed"; | |
5656 | + } | |
5657 | + | |
5658 | + memset(kv, 0, sizeof(*kv)); | |
5659 | + | |
5660 | + kv->key = strdup(name); | |
5661 | + kv->value = strdup(value); | |
5662 | + | |
5663 | + if (!kv->key || !kv->value) { | |
5664 | + return "xml_conf_set_slot_key_value_pair(): strdup() failed"; | |
5665 | + } | |
5666 | + | |
5667 | + **parent = kv; | |
5668 | + | |
5669 | + *parent = &kv->next; | |
5670 | + | |
5671 | + return NULL; | |
5672 | +} | |
5673 | + | |
5674 | +static struct xml_conf_section fpm_conf_set_key_value_pairs_subsection_conf = { | |
5675 | + .path = "key_value_pairs somewhere", /* fixme */ | |
5676 | + .parsers = (struct xml_value_parser []) { | |
5677 | + { XML_CONF_SCALAR, 0, &xml_conf_set_slot_key_value_pair, 0 }, | |
5678 | + { 0, 0, 0, 0 } | |
5679 | + } | |
5680 | +}; | |
5681 | + | |
5682 | +static char *fpm_conf_set_key_value_pairs_subsection(void **conf, char *name, void *xml_node, intptr_t offset) | |
5683 | +{ | |
5684 | + void *next_kv = (char *) *conf + offset; | |
5685 | + | |
5686 | + return xml_conf_parse_section(&next_kv, &fpm_conf_set_key_value_pairs_subsection_conf, xml_node); | |
5687 | +} | |
5688 | + | |
5689 | +static void *fpm_worker_pool_config_alloc() | |
5690 | +{ | |
5691 | + static struct fpm_worker_pool_s *current_wp = 0; | |
5692 | + struct fpm_worker_pool_s *wp; | |
5693 | + | |
5694 | + wp = fpm_worker_pool_alloc(); | |
5695 | + | |
5696 | + if (!wp) { return 0; } | |
5697 | + | |
5698 | + wp->config = malloc(sizeof(struct fpm_worker_pool_config_s)); | |
5699 | + | |
5700 | + if (!wp->config) { return 0; } | |
5701 | + | |
5702 | + memset(wp->config, 0, sizeof(struct fpm_worker_pool_config_s)); | |
5703 | + | |
5704 | + if (current_wp) { current_wp->next = wp; } | |
5705 | + | |
5706 | + current_wp = wp; | |
5707 | + | |
5708 | + return wp->config; | |
5709 | +} | |
5710 | + | |
5711 | +int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc) | |
5712 | +{ | |
5713 | + struct key_value_s *kv, *kv_next; | |
5714 | + | |
5715 | + free(wpc->name); | |
5716 | + free(wpc->listen_address); | |
5717 | + if (wpc->listen_options) { | |
5718 | + free(wpc->listen_options->owner); | |
5719 | + free(wpc->listen_options->group); | |
5720 | + free(wpc->listen_options->mode); | |
5721 | + free(wpc->listen_options); | |
5722 | + } | |
5723 | + for (kv = wpc->php_defines; kv; kv = kv_next) { | |
5724 | + kv_next = kv->next; | |
5725 | + free(kv->key); | |
5726 | + free(kv->value); | |
5727 | + free(kv); | |
5728 | + } | |
5729 | + for (kv = wpc->environment; kv; kv = kv_next) { | |
5730 | + kv_next = kv->next; | |
5731 | + free(kv->key); | |
5732 | + free(kv->value); | |
5733 | + free(kv); | |
5734 | + } | |
5735 | + free(wpc->pm); | |
5736 | + free(wpc->user); | |
5737 | + free(wpc->group); | |
5738 | + free(wpc->chroot); | |
5739 | + free(wpc->chdir); | |
5740 | + free(wpc->allowed_clients); | |
5741 | + free(wpc->slowlog); | |
5742 | + | |
5743 | + return 0; | |
5744 | +} | |
5745 | + | |
5746 | +static struct xml_conf_section xml_section_fpm_worker_pool_config = { | |
5747 | + .conf = &fpm_worker_pool_config_alloc, | |
5748 | + .path = "/configuration/workers/pool", | |
5749 | + .parsers = (struct xml_value_parser []) { | |
5750 | + { XML_CONF_SCALAR, "name", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, name) }, | |
5751 | + { XML_CONF_SCALAR, "listen_address", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, listen_address) }, | |
5752 | + { XML_CONF_SUBSECTION, "listen_options", &fpm_conf_set_listen_options_subsection, offsetof(struct fpm_worker_pool_config_s, listen_options) }, | |
5753 | + { XML_CONF_SUBSECTION, "php_defines", &fpm_conf_set_key_value_pairs_subsection, offsetof(struct fpm_worker_pool_config_s, php_defines) }, | |
5754 | + { XML_CONF_SCALAR, "user", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, user) }, | |
5755 | + { XML_CONF_SCALAR, "group", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, group) }, | |
5756 | + { XML_CONF_SCALAR, "chroot", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, chroot) }, | |
5757 | + { XML_CONF_SCALAR, "chdir", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, chdir) }, | |
5758 | + { XML_CONF_SCALAR, "allowed_clients", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, allowed_clients) }, | |
5759 | + { XML_CONF_SUBSECTION, "environment", &fpm_conf_set_key_value_pairs_subsection, offsetof(struct fpm_worker_pool_config_s, environment) }, | |
5760 | + { XML_CONF_SCALAR, "request_terminate_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_worker_pool_config_s, request_terminate_timeout) }, | |
5761 | + { XML_CONF_SCALAR, "request_slowlog_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_worker_pool_config_s, request_slowlog_timeout) }, | |
5762 | + { XML_CONF_SCALAR, "slowlog", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, slowlog) }, | |
5763 | + { XML_CONF_SCALAR, "rlimit_files", &xml_conf_set_slot_integer, offsetof(struct fpm_worker_pool_config_s, rlimit_files) }, | |
5764 | + { XML_CONF_SCALAR, "rlimit_core", &fpm_conf_set_rlimit_core, 0 }, | |
5765 | + { XML_CONF_SCALAR, "max_requests", &xml_conf_set_slot_integer, offsetof(struct fpm_worker_pool_config_s, max_requests) }, | |
5766 | + { XML_CONF_SCALAR, "catch_workers_output", &fpm_conf_set_catch_workers_output, 0 }, | |
5767 | + { XML_CONF_SUBSECTION, "pm", &fpm_conf_set_pm_subsection, offsetof(struct fpm_worker_pool_config_s, pm) }, | |
5768 | + { 0, 0, 0, 0 } | |
5769 | + } | |
5770 | +}; | |
5771 | + | |
5772 | +static struct xml_conf_section *fpm_conf_all_sections[] = { | |
5773 | + &xml_section_fpm_global_options, | |
5774 | + &xml_section_fpm_worker_pool_config, | |
5775 | + 0 | |
5776 | +}; | |
5777 | + | |
5778 | +static int fpm_evaluate_full_path(char **path) | |
5779 | +{ | |
5780 | + if (**path != '/') { | |
5781 | + char *full_path; | |
5782 | + | |
5783 | + full_path = malloc(sizeof(PHP_PREFIX) + strlen(*path) + 1); | |
5784 | + | |
5785 | + if (!full_path) { return -1; } | |
5786 | + | |
5787 | + sprintf(full_path, "%s/%s", PHP_PREFIX, *path); | |
5788 | + | |
5789 | + free(*path); | |
5790 | + | |
5791 | + *path = full_path; | |
5792 | + } | |
5793 | + | |
5794 | + return 0; | |
5795 | +} | |
5796 | + | |
5797 | +static int fpm_conf_process_all_pools() | |
5798 | +{ | |
5799 | + struct fpm_worker_pool_s *wp; | |
5800 | + | |
5801 | + if (!fpm_worker_all_pools) { | |
5802 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "at least one pool section must be specified in config file"); | |
5803 | + return -1; | |
5804 | + } | |
5805 | + | |
5806 | + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { | |
5807 | + | |
5808 | + if (wp->config->listen_address && *wp->config->listen_address) { | |
5809 | + | |
5810 | + wp->listen_address_domain = fpm_sockets_domain_from_address(wp->config->listen_address); | |
5811 | + | |
5812 | + if (wp->listen_address_domain == FPM_AF_UNIX && *wp->config->listen_address != '/') { | |
5813 | + fpm_evaluate_full_path(&wp->config->listen_address); | |
5814 | + } | |
5815 | + | |
5816 | + } | |
5817 | + else { | |
5818 | + | |
5819 | + wp->is_template = 1; | |
5820 | + | |
5821 | + } | |
5822 | + | |
5823 | + if (wp->config->request_slowlog_timeout) { | |
5824 | +#if HAVE_FPM_TRACE | |
5825 | + if (! (wp->config->slowlog && *wp->config->slowlog)) { | |
5826 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "pool %s: 'slowlog' must be specified for use with 'request_slowlog_timeout'", | |
5827 | + wp->config->name); | |
5828 | + return -1; | |
5829 | + } | |
5830 | +#else | |
5831 | + static int warned = 0; | |
5832 | + | |
5833 | + if (!warned) { | |
5834 | + zlog(ZLOG_STUFF, ZLOG_WARNING, "pool %s: 'request_slowlog_timeout' is not supported on your system", | |
5835 | + wp->config->name); | |
5836 | + warned = 1; | |
5837 | + } | |
5838 | + | |
5839 | + wp->config->request_slowlog_timeout = 0; | |
5840 | +#endif | |
5841 | + } | |
5842 | + | |
5843 | + if (wp->config->request_slowlog_timeout && wp->config->slowlog && *wp->config->slowlog) { | |
5844 | + int fd; | |
5845 | + | |
5846 | + fpm_evaluate_full_path(&wp->config->slowlog); | |
5847 | + | |
5848 | + if (wp->config->request_slowlog_timeout) { | |
5849 | + fd = open(wp->config->slowlog, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); | |
5850 | + | |
5851 | + if (0 > fd) { | |
5852 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(%s) failed", wp->config->slowlog); | |
5853 | + return -1; | |
5854 | + } | |
5855 | + close(fd); | |
5856 | + } | |
5857 | + } | |
5858 | + } | |
5859 | + | |
5860 | + return 0; | |
5861 | +} | |
5862 | + | |
5863 | +int fpm_conf_unlink_pid() | |
5864 | +{ | |
5865 | + if (fpm_global_config.pid_file) { | |
5866 | + | |
5867 | + if (0 > unlink(fpm_global_config.pid_file)) { | |
5868 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "unlink(\"%s\") failed", fpm_global_config.pid_file); | |
5869 | + return -1; | |
5870 | + } | |
5871 | + | |
5872 | + } | |
5873 | + | |
5874 | + return 0; | |
5875 | +} | |
5876 | + | |
5877 | +int fpm_conf_write_pid() | |
5878 | +{ | |
5879 | + int fd; | |
5880 | + | |
5881 | + if (fpm_global_config.pid_file) { | |
5882 | + char buf[64]; | |
5883 | + int len; | |
5884 | + | |
5885 | + unlink(fpm_global_config.pid_file); | |
5886 | + | |
5887 | + fd = creat(fpm_global_config.pid_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | |
5888 | + | |
5889 | + if (fd < 0) { | |
5890 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "creat(\"%s\") failed", fpm_global_config.pid_file); | |
5891 | + return -1; | |
5892 | + } | |
5893 | + | |
5894 | + len = sprintf(buf, "%d", (int) fpm_globals.parent_pid); | |
5895 | + | |
5896 | + if (len != write(fd, buf, len)) { | |
5897 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "write() failed"); | |
5898 | + return -1; | |
5899 | + } | |
5900 | + | |
5901 | + close(fd); | |
5902 | + } | |
5903 | + | |
5904 | + return 0; | |
5905 | +} | |
5906 | + | |
5907 | +static int fpm_conf_post_process() | |
5908 | +{ | |
5909 | + if (fpm_global_config.pid_file) { | |
5910 | + fpm_evaluate_full_path(&fpm_global_config.pid_file); | |
5911 | + } | |
5912 | + | |
5913 | + if (!fpm_global_config.error_log) { | |
5914 | + fpm_global_config.error_log = strdup(PHP_FPM_LOG_PATH); | |
5915 | + } | |
5916 | + | |
5917 | + fpm_evaluate_full_path(&fpm_global_config.error_log); | |
5918 | + | |
5919 | + if (0 > fpm_stdio_open_error_log(0)) { | |
5920 | + return -1; | |
5921 | + } | |
5922 | + | |
5923 | + return fpm_conf_process_all_pools(); | |
5924 | +} | |
5925 | + | |
5926 | +static void fpm_conf_cleanup(int which, void *arg) | |
5927 | +{ | |
5928 | + free(fpm_global_config.pid_file); | |
5929 | + free(fpm_global_config.error_log); | |
5930 | + fpm_global_config.pid_file = 0; | |
5931 | + fpm_global_config.error_log = 0; | |
5932 | +} | |
5933 | + | |
5934 | +int fpm_conf_init_main() | |
5935 | +{ | |
5936 | + char *filename = fpm_globals.config; | |
5937 | + char *err; | |
5938 | + | |
5939 | + if (0 > xml_conf_sections_register(fpm_conf_all_sections)) { | |
5940 | + return -1; | |
5941 | + } | |
5942 | + | |
5943 | + if (filename == NULL) { | |
5944 | + filename = PHP_FPM_CONF_PATH; | |
5945 | + } | |
5946 | + | |
5947 | + err = xml_conf_load_file(filename); | |
5948 | + | |
5949 | + if (err) { | |
5950 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "failed to load configuration file: %s", err); | |
5951 | + return -1; | |
5952 | + } | |
5953 | + | |
5954 | + if (0 > fpm_conf_post_process()) { | |
5955 | + return -1; | |
5956 | + } | |
5957 | + | |
5958 | + xml_conf_clean(); | |
5959 | + | |
5960 | + if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_conf_cleanup, 0)) { | |
5961 | + return -1; | |
5962 | + } | |
5963 | + | |
5964 | + return 0; | |
5965 | +} | |
5966 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_conf.h php-src/sapi/fpm/fpm/fpm_conf.h | |
5967 | --- php-src-vanilla/sapi/fpm/fpm/fpm_conf.h 1970-01-01 01:00:00.000000000 +0100 | |
5968 | +++ php-src/sapi/fpm/fpm/fpm_conf.h 2009-10-18 21:05:39.308376784 +0100 | |
5969 | @@ -0,0 +1,73 @@ | |
5970 | + | |
5971 | + /* $Id$ */ | |
5972 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
5973 | + | |
5974 | +#ifndef FPM_CONF_H | |
5975 | +#define FPM_CONF_H 1 | |
5976 | + | |
5977 | +struct key_value_s; | |
5978 | + | |
5979 | +struct key_value_s { | |
5980 | + struct key_value_s *next; | |
5981 | + char *key; | |
5982 | + char *value; | |
5983 | +}; | |
5984 | + | |
5985 | +struct fpm_global_config_s { | |
5986 | + int emergency_restart_threshold; | |
5987 | + int emergency_restart_interval; | |
5988 | + int process_control_timeout; | |
5989 | + int daemonize; | |
5990 | + char *pid_file; | |
5991 | + char *error_log; | |
5992 | +}; | |
5993 | + | |
5994 | +extern struct fpm_global_config_s fpm_global_config; | |
5995 | + | |
5996 | +struct fpm_pm_s { | |
5997 | + int style; | |
5998 | + int max_children; | |
5999 | + struct { | |
6000 | + int StartServers; | |
6001 | + int MinSpareServers; | |
6002 | + int MaxSpareServers; | |
6003 | + } options_apache_like; | |
6004 | +}; | |
6005 | + | |
6006 | +struct fpm_listen_options_s { | |
6007 | + int backlog; | |
6008 | + char *owner; | |
6009 | + char *group; | |
6010 | + char *mode; | |
6011 | +}; | |
6012 | + | |
6013 | +struct fpm_worker_pool_config_s { | |
6014 | + char *name; | |
6015 | + char *listen_address; | |
6016 | + struct fpm_listen_options_s *listen_options; | |
6017 | + struct key_value_s *php_defines; | |
6018 | + char *user; | |
6019 | + char *group; | |
6020 | + char *chroot; | |
6021 | + char *chdir; | |
6022 | + char *allowed_clients; | |
6023 | + struct key_value_s *environment; | |
6024 | + struct fpm_pm_s *pm; | |
6025 | + int request_terminate_timeout; | |
6026 | + int request_slowlog_timeout; | |
6027 | + char *slowlog; | |
6028 | + int max_requests; | |
6029 | + int rlimit_files; | |
6030 | + int rlimit_core; | |
6031 | + unsigned catch_workers_output:1; | |
6032 | +}; | |
6033 | + | |
6034 | +enum { PM_STYLE_STATIC = 1, PM_STYLE_APACHE_LIKE = 2 }; | |
6035 | + | |
6036 | +int fpm_conf_init_main(); | |
6037 | +int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc); | |
6038 | +int fpm_conf_write_pid(); | |
6039 | +int fpm_conf_unlink_pid(); | |
6040 | + | |
6041 | +#endif | |
6042 | + | |
6043 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_config.h php-src/sapi/fpm/fpm/fpm_config.h | |
6044 | --- php-src-vanilla/sapi/fpm/fpm/fpm_config.h 1970-01-01 01:00:00.000000000 +0100 | |
6045 | +++ php-src/sapi/fpm/fpm/fpm_config.h 2009-10-18 21:05:39.310440424 +0100 | |
6046 | @@ -0,0 +1,40 @@ | |
6047 | + | |
6048 | + /* $Id$ */ | |
6049 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
6050 | + | |
6051 | +#include <php_config.h> | |
6052 | +#ifdef FPM_AUTOCONFIG_H | |
6053 | +#include <fpm_autoconfig.h> | |
6054 | +#endif | |
6055 | + | |
6056 | +/* Solaris does not have it */ | |
6057 | +#ifndef INADDR_NONE | |
6058 | +#define INADDR_NONE (-1) | |
6059 | +#endif | |
6060 | + | |
6061 | + | |
6062 | +/* If we're not using GNU C, elide __attribute__ */ | |
6063 | +#ifndef __GNUC__ | |
6064 | +# define __attribute__(x) /*NOTHING*/ | |
6065 | +#endif | |
6066 | + | |
6067 | + | |
6068 | +/* Solaris does not have it */ | |
6069 | +#ifndef timersub | |
6070 | +#define timersub(tvp, uvp, vvp) \ | |
6071 | + do { \ | |
6072 | + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ | |
6073 | + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ | |
6074 | + if ((vvp)->tv_usec < 0) { \ | |
6075 | + (vvp)->tv_sec--; \ | |
6076 | + (vvp)->tv_usec += 1000000; \ | |
6077 | + } \ | |
6078 | + } while (0) | |
6079 | +#endif | |
6080 | + | |
6081 | +#if defined(HAVE_PTRACE) || defined(PROC_MEM_FILE) || defined(HAVE_MACH_VM_READ) | |
6082 | +#define HAVE_FPM_TRACE 1 | |
6083 | +#else | |
6084 | +#define HAVE_FPM_TRACE 0 | |
6085 | +#endif | |
6086 | + | |
6087 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_env.c php-src/sapi/fpm/fpm/fpm_env.c | |
6088 | --- php-src-vanilla/sapi/fpm/fpm/fpm_env.c 1970-01-01 01:00:00.000000000 +0100 | |
6089 | +++ php-src/sapi/fpm/fpm/fpm_env.c 2009-10-18 21:05:39.308376784 +0100 | |
6090 | @@ -0,0 +1,175 @@ | |
6091 | + | |
6092 | + /* $Id$ */ | |
6093 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
6094 | + | |
6095 | +#include "fpm_config.h" | |
6096 | + | |
6097 | +#ifdef HAVE_ALLOCA_H | |
6098 | +#include <alloca.h> | |
6099 | +#endif | |
6100 | +#include <stdio.h> | |
6101 | +#include <stdlib.h> | |
6102 | +#include <string.h> | |
6103 | + | |
6104 | +#include "fpm_env.h" | |
6105 | +#include "zlog.h" | |
6106 | + | |
6107 | +#ifndef HAVE_SETENV | |
6108 | +#ifdef (__sparc__ || __sparc) | |
6109 | +int setenv(name, value, clobber) | |
6110 | +char *name; | |
6111 | +char *value; | |
6112 | +int clobber; | |
6113 | +{ | |
6114 | + char *malloc(); | |
6115 | + char *getenv(); | |
6116 | + char *cp; | |
6117 | + | |
6118 | + if (clobber == 0 && getenv(name) != 0) | |
6119 | + { return (0); } | |
6120 | + if ((cp = malloc(strlen(name) + strlen(value) + 2)) == 0) | |
6121 | + { return (1); } | |
6122 | + sprintf(cp, "%s=%s", name, value); | |
6123 | + return (putenv(cp)); | |
6124 | +} | |
6125 | +#else | |
6126 | +int setenv(char *name, char *value, int overwrite) | |
6127 | +{ | |
6128 | + int name_len = strlen(name); | |
6129 | + int value_len = strlen(value); | |
6130 | + char *var = alloca(name_len + 1 + value_len + 1); | |
6131 | + | |
6132 | + memcpy(var, name, name_len); | |
6133 | + | |
6134 | + var[name_len] = '='; | |
6135 | + | |
6136 | + memcpy(var + name_len + 1, value, value_len); | |
6137 | + | |
6138 | + var[name_len + 1 + value_len] = '\0'; | |
6139 | + | |
6140 | + return putenv(var); | |
6141 | +} | |
6142 | +#endif | |
6143 | +#endif | |
6144 | + | |
6145 | +#ifndef HAVE_CLEARENV | |
6146 | +void clearenv() | |
6147 | +{ | |
6148 | + char **envp; | |
6149 | + char *s; | |
6150 | + | |
6151 | + /* this algo is the only one known to me | |
6152 | + that works well on all systems */ | |
6153 | + while (*(envp = environ)) { | |
6154 | + char *eq = strchr(*envp, '='); | |
6155 | + | |
6156 | + s = strdup(*envp); | |
6157 | + | |
6158 | + if (eq) { s[eq - *envp] = '\0'; } | |
6159 | + | |
6160 | + unsetenv(s); | |
6161 | + free(s); | |
6162 | + } | |
6163 | + | |
6164 | +} | |
6165 | +#endif | |
6166 | + | |
6167 | +#ifndef HAVE_UNSETENV | |
6168 | +void unsetenv(const char *name) | |
6169 | +{ | |
6170 | + if(getenv(name)!=NULL) | |
6171 | + { | |
6172 | + int ct=0; | |
6173 | + int del=0; | |
6174 | + | |
6175 | + while(environ[ct] != NULL) | |
6176 | + { | |
6177 | + if (nvmatch(name, environ[ct]) != 0) del=ct; | |
6178 | + { ct++; } | |
6179 | + } | |
6180 | + /* isn't needed free here?? */ | |
6181 | + environ[del]=environ[ct-1]; | |
6182 | + environ[ct-1]=NULL; | |
6183 | + } | |
6184 | +} | |
6185 | +static char * nvmatch(s1, s2) | |
6186 | +register char *s1, *s2; | |
6187 | +{ | |
6188 | + while(*s1 == *s2++) | |
6189 | + { | |
6190 | + if(*s1++ == '=') | |
6191 | + { return(s2); } | |
6192 | + } | |
6193 | + if(*s1 == '\0' && *(s2-1) == '=') | |
6194 | + { return(s2); } | |
6195 | + return(NULL); | |
6196 | +} | |
6197 | +#endif | |
6198 | + | |
6199 | +int fpm_env_init_child(struct fpm_worker_pool_s *wp) | |
6200 | +{ | |
6201 | + struct key_value_s *kv; | |
6202 | + | |
6203 | + clearenv(); | |
6204 | + | |
6205 | + for (kv = wp->config->environment; kv; kv = kv->next) { | |
6206 | + setenv(kv->key, kv->value, 1); | |
6207 | + } | |
6208 | + | |
6209 | + if (wp->user) { | |
6210 | + setenv("USER", wp->user, 1); | |
6211 | + } | |
6212 | + | |
6213 | + if (wp->home) { | |
6214 | + setenv("HOME", wp->home, 1); | |
6215 | + } | |
6216 | + | |
6217 | + return 0; | |
6218 | +} | |
6219 | + | |
6220 | +static int fpm_env_conf_wp(struct fpm_worker_pool_s *wp) | |
6221 | +{ | |
6222 | + struct key_value_s *kv; | |
6223 | + | |
6224 | + kv = wp->config->environment; | |
6225 | + | |
6226 | + for (kv = wp->config->environment; kv; kv = kv->next) { | |
6227 | + if (*kv->value == '$') { | |
6228 | + char *value = getenv(kv->value + 1); | |
6229 | + | |
6230 | + if (!value) { value = ""; } | |
6231 | + | |
6232 | + free(kv->value); | |
6233 | + kv->value = strdup(value); | |
6234 | + } | |
6235 | + | |
6236 | + /* autodetected values should be removed | |
6237 | + if these vars specified in config */ | |
6238 | + if (!strcmp(kv->key, "USER")) { | |
6239 | + free(wp->user); | |
6240 | + wp->user = 0; | |
6241 | + } | |
6242 | + | |
6243 | + if (!strcmp(kv->key, "HOME")) { | |
6244 | + free(wp->home); | |
6245 | + wp->home = 0; | |
6246 | + } | |
6247 | + } | |
6248 | + | |
6249 | + return 0; | |
6250 | +} | |
6251 | + | |
6252 | +int fpm_env_init_main() | |
6253 | +{ | |
6254 | + struct fpm_worker_pool_s *wp; | |
6255 | + | |
6256 | + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { | |
6257 | + | |
6258 | + if (0 > fpm_env_conf_wp(wp)) { | |
6259 | + return -1; | |
6260 | + } | |
6261 | + | |
6262 | + } | |
6263 | + | |
6264 | + return 0; | |
6265 | +} | |
6266 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_env.h php-src/sapi/fpm/fpm/fpm_env.h | |
6267 | --- php-src-vanilla/sapi/fpm/fpm/fpm_env.h 1970-01-01 01:00:00.000000000 +0100 | |
6268 | +++ php-src/sapi/fpm/fpm/fpm_env.h 2009-10-18 21:05:39.308376784 +0100 | |
6269 | @@ -0,0 +1,24 @@ | |
6270 | + | |
6271 | + /* $Id$ */ | |
6272 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
6273 | + | |
6274 | +#ifndef FPM_ENV_H | |
6275 | +#define FPM_ENV_H 1 | |
6276 | + | |
6277 | +#include "fpm_worker_pool.h" | |
6278 | + | |
6279 | +int fpm_env_init_child(struct fpm_worker_pool_s *wp); | |
6280 | +int fpm_env_init_main(); | |
6281 | + | |
6282 | +extern char **environ; | |
6283 | + | |
6284 | +#ifndef HAVE_SETENV | |
6285 | +int setenv(char *name, char *value, int overwrite); | |
6286 | +#endif | |
6287 | + | |
6288 | +#ifndef HAVE_CLEARENV | |
6289 | +void clearenv(); | |
6290 | +#endif | |
6291 | + | |
6292 | +#endif | |
6293 | + | |
6294 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_events.c php-src/sapi/fpm/fpm/fpm_events.c | |
6295 | --- php-src-vanilla/sapi/fpm/fpm/fpm_events.c 1970-01-01 01:00:00.000000000 +0100 | |
6296 | +++ php-src/sapi/fpm/fpm/fpm_events.c 2009-10-18 21:05:39.310440424 +0100 | |
6297 | @@ -0,0 +1,135 @@ | |
6298 | + | |
6299 | + /* $Id$ */ | |
6300 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
6301 | + | |
6302 | +#include "fpm_config.h" | |
6303 | + | |
6304 | +#include <unistd.h> | |
6305 | +#include <errno.h> | |
6306 | +#include <stdlib.h> /* for putenv */ | |
6307 | +#include <string.h> | |
6308 | +#include <sys/types.h> /* for event.h below */ | |
6309 | +#include <event.h> | |
6310 | + | |
6311 | +#include "fpm.h" | |
6312 | +#include "fpm_process_ctl.h" | |
6313 | +#include "fpm_events.h" | |
6314 | +#include "fpm_cleanup.h" | |
6315 | +#include "fpm_stdio.h" | |
6316 | +#include "fpm_signals.h" | |
6317 | +#include "fpm_children.h" | |
6318 | +#include "zlog.h" | |
6319 | + | |
6320 | +static void fpm_event_cleanup(int which, void *arg) | |
6321 | +{ | |
6322 | + event_base_free(0); | |
6323 | +} | |
6324 | + | |
6325 | +static void fpm_got_signal(int fd, short ev, void *arg) | |
6326 | +{ | |
6327 | + char c; | |
6328 | + int res; | |
6329 | + | |
6330 | + do { | |
6331 | + | |
6332 | + do { | |
6333 | + res = read(fd, &c, 1); | |
6334 | + } while (res == -1 && errno == EINTR); | |
6335 | + | |
6336 | + if (res <= 0) { | |
6337 | + if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { | |
6338 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed"); | |
6339 | + } | |
6340 | + return; | |
6341 | + } | |
6342 | + | |
6343 | + switch (c) { | |
6344 | + case 'C' : /* SIGCHLD */ | |
6345 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGCHLD"); | |
6346 | + fpm_children_bury(); | |
6347 | + break; | |
6348 | + case 'I' : /* SIGINT */ | |
6349 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGINT"); | |
6350 | + fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET); | |
6351 | + break; | |
6352 | + case 'T' : /* SIGTERM */ | |
6353 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGTERM"); | |
6354 | + fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET); | |
6355 | + break; | |
6356 | + case 'Q' : /* SIGQUIT */ | |
6357 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGQUIT"); | |
6358 | + fpm_pctl(FPM_PCTL_STATE_FINISHING, FPM_PCTL_ACTION_SET); | |
6359 | + break; | |
6360 | + case '1' : /* SIGUSR1 */ | |
6361 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGUSR1"); | |
6362 | + if (0 == fpm_stdio_open_error_log(1)) { | |
6363 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "log file re-opened"); | |
6364 | + } | |
6365 | + break; | |
6366 | + case '2' : /* SIGUSR2 */ | |
6367 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGUSR2"); | |
6368 | + fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET); | |
6369 | + break; | |
6370 | + } | |
6371 | + | |
6372 | + if (fpm_globals.is_child) { | |
6373 | + break; | |
6374 | + } | |
6375 | + | |
6376 | + } while (1); | |
6377 | + | |
6378 | + return; | |
6379 | +} | |
6380 | + | |
6381 | +int fpm_event_init_main() | |
6382 | +{ | |
6383 | + event_init(); | |
6384 | + | |
6385 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "libevent: using %s", event_get_method()); | |
6386 | + | |
6387 | + if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_event_cleanup, 0)) { | |
6388 | + return -1; | |
6389 | + } | |
6390 | + | |
6391 | + return 0; | |
6392 | +} | |
6393 | + | |
6394 | +int fpm_event_loop() | |
6395 | +{ | |
6396 | + static struct event signal_fd_event; | |
6397 | + | |
6398 | + event_set(&signal_fd_event, fpm_signals_get_fd(), EV_PERSIST | EV_READ, &fpm_got_signal, 0); | |
6399 | + | |
6400 | + event_add(&signal_fd_event, 0); | |
6401 | + | |
6402 | + fpm_pctl_heartbeat(-1, 0, 0); | |
6403 | + | |
6404 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "libevent: entering main loop"); | |
6405 | + | |
6406 | + event_loop(0); | |
6407 | + | |
6408 | + return 0; | |
6409 | +} | |
6410 | + | |
6411 | +int fpm_event_add(int fd, struct event *ev, void (*callback)(int, short, void *), void *arg) | |
6412 | +{ | |
6413 | + event_set(ev, fd, EV_PERSIST | EV_READ, callback, arg); | |
6414 | + | |
6415 | + return event_add(ev, 0); | |
6416 | +} | |
6417 | + | |
6418 | +int fpm_event_del(struct event *ev) | |
6419 | +{ | |
6420 | + return event_del(ev); | |
6421 | +} | |
6422 | + | |
6423 | +void fpm_event_exit_loop() | |
6424 | +{ | |
6425 | + event_loopbreak(); | |
6426 | +} | |
6427 | + | |
6428 | +void fpm_event_fire(struct event *ev) | |
6429 | +{ | |
6430 | + (*ev->ev_callback)( (int) ev->ev_fd, (short) ev->ev_res, ev->ev_arg); | |
6431 | +} | |
6432 | + | |
6433 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_events.h php-src/sapi/fpm/fpm/fpm_events.h | |
6434 | --- php-src-vanilla/sapi/fpm/fpm/fpm_events.h 1970-01-01 01:00:00.000000000 +0100 | |
6435 | +++ php-src/sapi/fpm/fpm/fpm_events.h 2009-10-18 21:05:39.310440424 +0100 | |
6436 | @@ -0,0 +1,16 @@ | |
6437 | + | |
6438 | + /* $Id$ */ | |
6439 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
6440 | + | |
6441 | +#ifndef FPM_EVENTS_H | |
6442 | +#define FPM_EVENTS_H 1 | |
6443 | + | |
6444 | +void fpm_event_exit_loop(); | |
6445 | +int fpm_event_loop(); | |
6446 | +int fpm_event_add(int fd, struct event *ev, void (*callback)(int, short, void *), void *arg); | |
6447 | +int fpm_event_del(struct event *ev); | |
6448 | +void fpm_event_fire(struct event *ev); | |
6449 | +int fpm_event_init_main(); | |
6450 | + | |
6451 | + | |
6452 | +#endif | |
6453 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm.h php-src/sapi/fpm/fpm/fpm.h | |
6454 | --- php-src-vanilla/sapi/fpm/fpm/fpm.h 1970-01-01 01:00:00.000000000 +0100 | |
6455 | +++ php-src/sapi/fpm/fpm/fpm.h 2009-10-18 21:05:39.308376784 +0100 | |
6456 | @@ -0,0 +1,28 @@ | |
6457 | + | |
6458 | + /* $Id$ */ | |
6459 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
6460 | + | |
6461 | +#ifndef FPM_H | |
6462 | +#define FPM_H 1 | |
6463 | + | |
6464 | +#include <unistd.h> | |
6465 | + | |
6466 | +int fpm_run(int *max_requests); | |
6467 | +int fpm_init(int argc, char **argv, char *config); | |
6468 | + | |
6469 | +struct fpm_globals_s { | |
6470 | + pid_t parent_pid; | |
6471 | + int argc; | |
6472 | + char **argv; | |
6473 | + char *config; | |
6474 | + int running_children; | |
6475 | + int error_log_fd; | |
6476 | + int log_level; | |
6477 | + int listening_socket; /* for this child */ | |
6478 | + int max_requests; /* for this child */ | |
6479 | + int is_child; | |
6480 | +}; | |
6481 | + | |
6482 | +extern struct fpm_globals_s fpm_globals; | |
6483 | + | |
6484 | +#endif | |
6485 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_php.c php-src/sapi/fpm/fpm/fpm_php.c | |
6486 | --- php-src-vanilla/sapi/fpm/fpm/fpm_php.c 1970-01-01 01:00:00.000000000 +0100 | |
6487 | +++ php-src/sapi/fpm/fpm/fpm_php.c 2009-10-18 21:05:39.310440424 +0100 | |
6488 | @@ -0,0 +1,189 @@ | |
6489 | + | |
6490 | + /* $Id$ */ | |
6491 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
6492 | + | |
6493 | +#include "fpm_config.h" | |
6494 | + | |
6495 | +#include <stdlib.h> | |
6496 | +#include <string.h> | |
6497 | +#include <stdio.h> | |
6498 | + | |
6499 | +#include "php.h" | |
6500 | +#include "php_main.h" | |
6501 | +#include "php_ini.h" | |
6502 | +#include "ext/standard/dl.h" | |
6503 | + | |
6504 | +#include "cgi/fastcgi.h" | |
6505 | + | |
6506 | +#include "fpm.h" | |
6507 | +#include "fpm_php.h" | |
6508 | +#include "fpm_cleanup.h" | |
6509 | +#include "fpm_worker_pool.h" | |
6510 | + | |
6511 | +static int zend_ini_alter_master(char *name, int name_length, char *new_value, int new_value_length, int stage TSRMLS_DC) | |
6512 | +{ | |
6513 | + zend_ini_entry *ini_entry; | |
6514 | + char *duplicate; | |
6515 | + | |
6516 | + if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == FAILURE) { | |
6517 | + return FAILURE; | |
6518 | + } | |
6519 | + | |
6520 | + duplicate = strdup(new_value); | |
6521 | + | |
6522 | + if (!ini_entry->on_modify | |
6523 | + || ini_entry->on_modify(ini_entry, duplicate, new_value_length, | |
6524 | + ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC) == SUCCESS) { | |
6525 | + ini_entry->value = duplicate; | |
6526 | + ini_entry->value_length = new_value_length; | |
6527 | + } else { | |
6528 | + free(duplicate); | |
6529 | + } | |
6530 | + | |
6531 | + return SUCCESS; | |
6532 | +} | |
6533 | + | |
6534 | +static void fpm_php_disable(char *value, int (*zend_disable)(char *, uint TSRMLS_DC) TSRMLS_DC) | |
6535 | +{ | |
6536 | + char *s = 0, *e = value; | |
6537 | + | |
6538 | + while (*e) { | |
6539 | + switch (*e) { | |
6540 | + case ' ': | |
6541 | + case ',': | |
6542 | + if (s) { | |
6543 | + *e = '\0'; | |
6544 | + zend_disable(s, e - s TSRMLS_CC); | |
6545 | + s = 0; | |
6546 | + } | |
6547 | + break; | |
6548 | + default: | |
6549 | + if (!s) { | |
6550 | + s = e; | |
6551 | + } | |
6552 | + break; | |
6553 | + } | |
6554 | + e++; | |
6555 | + } | |
6556 | + | |
6557 | + if (s) { | |
6558 | + zend_disable(s, e - s TSRMLS_CC); | |
6559 | + } | |
6560 | +} | |
6561 | + | |
6562 | +static int fpm_php_apply_defines(struct fpm_worker_pool_s *wp) | |
6563 | +{ | |
6564 | + TSRMLS_FETCH(); | |
6565 | + struct key_value_s *kv; | |
6566 | + | |
6567 | + for (kv = wp->config->php_defines; kv; kv = kv->next) { | |
6568 | + char *name = kv->key; | |
6569 | + char *value = kv->value; | |
6570 | + int name_len = strlen(name); | |
6571 | + int value_len = strlen(value); | |
6572 | + | |
6573 | + if (!strcmp(name, "extension") && *value) { | |
6574 | + zval zv; | |
6575 | + | |
6576 | +#if defined(PHP_VERSION_ID) && (PHP_VERSION_ID >= 50300) | |
6577 | + php_dl(value, MODULE_PERSISTENT, &zv, 1 TSRMLS_CC); | |
6578 | +#else | |
6579 | + zval filename; | |
6580 | + ZVAL_STRINGL(&filename, value, value_len, 0); | |
6581 | +#if (PHP_MAJOR_VERSION >= 5) | |
6582 | + php_dl(&filename, MODULE_PERSISTENT, &zv, 1 TSRMLS_CC); | |
6583 | +#else | |
6584 | + php_dl(&filename, MODULE_PERSISTENT, &zv TSRMLS_CC); | |
6585 | +#endif | |
6586 | +#endif | |
6587 | + continue; | |
6588 | + } | |
6589 | + | |
6590 | + zend_ini_alter_master(name, name_len + 1, value, value_len, PHP_INI_STAGE_ACTIVATE TSRMLS_CC); | |
6591 | + | |
6592 | + if (!strcmp(name, "disable_functions") && *value) { | |
6593 | + char *v = strdup(value); | |
6594 | +#if (PHP_MAJOR_VERSION >= 5) | |
6595 | + PG(disable_functions) = v; | |
6596 | +#endif | |
6597 | + fpm_php_disable(v, zend_disable_function TSRMLS_CC); | |
6598 | + } | |
6599 | + else if (!strcmp(name, "disable_classes") && *value) { | |
6600 | + char *v = strdup(value); | |
6601 | +#if (PHP_MAJOR_VERSION >= 5) | |
6602 | + PG(disable_classes) = v; | |
6603 | +#endif | |
6604 | + fpm_php_disable(v, zend_disable_class TSRMLS_CC); | |
6605 | + } | |
6606 | + } | |
6607 | + | |
6608 | + return 0; | |
6609 | +} | |
6610 | + | |
6611 | +static int fpm_php_set_allowed_clients(struct fpm_worker_pool_s *wp) | |
6612 | +{ | |
6613 | + if (wp->listen_address_domain == FPM_AF_INET) { | |
6614 | + fcgi_set_allowed_clients(wp->config->allowed_clients); | |
6615 | + } | |
6616 | + | |
6617 | + return 0; | |
6618 | +} | |
6619 | + | |
6620 | +static int fpm_php_set_fcgi_mgmt_vars(struct fpm_worker_pool_s *wp) | |
6621 | +{ | |
6622 | + char max_workers[10 + 1]; /* 4294967295 */ | |
6623 | + int len; | |
6624 | + | |
6625 | + len = sprintf(max_workers, "%u", (unsigned int) wp->config->pm->max_children); | |
6626 | + | |
6627 | + fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, max_workers, len); | |
6628 | + fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, max_workers, len); | |
6629 | + | |
6630 | + return 0; | |
6631 | +} | |
6632 | + | |
6633 | +char *fpm_php_script_filename(TSRMLS_D) | |
6634 | +{ | |
6635 | + return SG(request_info).path_translated; | |
6636 | +} | |
6637 | + | |
6638 | +char *fpm_php_request_method(TSRMLS_D) | |
6639 | +{ | |
6640 | + return (char *) SG(request_info).request_method; | |
6641 | +} | |
6642 | + | |
6643 | +size_t fpm_php_content_length(TSRMLS_D) | |
6644 | +{ | |
6645 | + return SG(request_info).content_length; | |
6646 | +} | |
6647 | + | |
6648 | +static void fpm_php_cleanup(int which, void *arg) | |
6649 | +{ | |
6650 | + TSRMLS_FETCH(); | |
6651 | + php_module_shutdown(TSRMLS_C); | |
6652 | + sapi_shutdown(); | |
6653 | +} | |
6654 | + | |
6655 | +void fpm_php_soft_quit() | |
6656 | +{ | |
6657 | + fcgi_set_in_shutdown(1); | |
6658 | +} | |
6659 | + | |
6660 | +int fpm_php_init_main() | |
6661 | +{ | |
6662 | + if (0 > fpm_cleanup_add(FPM_CLEANUP_PARENT, fpm_php_cleanup, 0)) { | |
6663 | + return -1; | |
6664 | + } | |
6665 | + | |
6666 | + return 0; | |
6667 | +} | |
6668 | + | |
6669 | +int fpm_php_init_child(struct fpm_worker_pool_s *wp) | |
6670 | +{ | |
6671 | + if (0 > fpm_php_apply_defines(wp) || | |
6672 | + 0 > fpm_php_set_allowed_clients(wp)) { | |
6673 | + return -1; | |
6674 | + } | |
6675 | + | |
6676 | + return 0; | |
6677 | +} | |
6678 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_php.h php-src/sapi/fpm/fpm/fpm_php.h | |
6679 | --- php-src-vanilla/sapi/fpm/fpm/fpm_php.h 1970-01-01 01:00:00.000000000 +0100 | |
6680 | +++ php-src/sapi/fpm/fpm/fpm_php.h 2009-10-18 21:05:39.302497288 +0100 | |
6681 | @@ -0,0 +1,22 @@ | |
6682 | + | |
6683 | + /* $Id$ */ | |
6684 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
6685 | + | |
6686 | +#ifndef FPM_PHP_H | |
6687 | +#define FPM_PHP_H 1 | |
6688 | + | |
6689 | +#include <TSRM.h> | |
6690 | + | |
6691 | +#include "build-defs.h" /* for PHP_ defines */ | |
6692 | + | |
6693 | +struct fpm_worker_pool_s; | |
6694 | + | |
6695 | +int fpm_php_init_child(struct fpm_worker_pool_s *wp); | |
6696 | +char *fpm_php_script_filename(TSRMLS_D); | |
6697 | +char *fpm_php_request_method(TSRMLS_D); | |
6698 | +size_t fpm_php_content_length(TSRMLS_D); | |
6699 | +void fpm_php_soft_quit(); | |
6700 | +int fpm_php_init_main(); | |
6701 | + | |
6702 | +#endif | |
6703 | + | |
6704 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_php_trace.c php-src/sapi/fpm/fpm/fpm_php_trace.c | |
6705 | --- php-src-vanilla/sapi/fpm/fpm/fpm_php_trace.c 1970-01-01 01:00:00.000000000 +0100 | |
6706 | +++ php-src/sapi/fpm/fpm/fpm_php_trace.c 2009-10-18 21:05:39.310440424 +0100 | |
6707 | @@ -0,0 +1,176 @@ | |
6708 | + | |
6709 | + /* $Id$ */ | |
6710 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
6711 | + | |
6712 | +#include "fpm_config.h" | |
6713 | + | |
6714 | +#if HAVE_FPM_TRACE | |
6715 | + | |
6716 | +#include "php.h" | |
6717 | +#include "php_main.h" | |
6718 | + | |
6719 | +#include <stdio.h> | |
6720 | +#include <stddef.h> | |
6721 | +#if HAVE_INTTYPES_H | |
6722 | +#include <inttypes.h> | |
6723 | +#else | |
6724 | +#include <stdint.h> | |
6725 | +#endif | |
6726 | + | |
6727 | +#include <unistd.h> | |
6728 | +#include <sys/time.h> | |
6729 | +#include <sys/types.h> | |
6730 | +#include <errno.h> | |
6731 | + | |
6732 | +#include "fpm_trace.h" | |
6733 | +#include "fpm_php_trace.h" | |
6734 | +#include "fpm_children.h" | |
6735 | +#include "fpm_worker_pool.h" | |
6736 | +#include "fpm_process_ctl.h" | |
6737 | + | |
6738 | +#include "zlog.h" | |
6739 | + | |
6740 | + | |
6741 | +#define valid_ptr(p) ((p) && 0 == ((p) & (sizeof(long) - 1))) | |
6742 | + | |
6743 | +#if SIZEOF_LONG == 4 | |
6744 | +#define PTR_FMT "08" | |
6745 | +#elif SIZEOF_LONG == 8 | |
6746 | +#define PTR_FMT "016" | |
6747 | +#endif | |
6748 | + | |
6749 | + | |
6750 | +static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog TSRMLS_DC) | |
6751 | +{ | |
6752 | + int callers_limit = 20; | |
6753 | + pid_t pid = child->pid; | |
6754 | + struct timeval tv; | |
6755 | + static const int buf_size = 1024; | |
6756 | + char buf[buf_size]; | |
6757 | + long execute_data; | |
6758 | + long l; | |
6759 | + | |
6760 | + gettimeofday(&tv, 0); | |
6761 | + | |
6762 | + zlog_print_time(&tv, buf, buf_size); | |
6763 | + | |
6764 | + fprintf(slowlog, "\n%s pid %d (pool %s)\n", buf, (int) pid, child->wp->config->name); | |
6765 | + | |
6766 | + if (0 > fpm_trace_get_strz(buf, buf_size, (long) &SG(request_info).path_translated)) { | |
6767 | + return -1; | |
6768 | + } | |
6769 | + | |
6770 | + fprintf(slowlog, "script_filename = %s\n", buf); | |
6771 | + | |
6772 | + if (0 > fpm_trace_get_long((long) &EG(current_execute_data), &l)) { | |
6773 | + return -1; | |
6774 | + } | |
6775 | + | |
6776 | + execute_data = l; | |
6777 | + | |
6778 | + while (execute_data) { | |
6779 | + long function; | |
6780 | + uint lineno = 0; | |
6781 | + | |
6782 | + fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data); | |
6783 | + | |
6784 | + if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) { | |
6785 | + return -1; | |
6786 | + } | |
6787 | + | |
6788 | + function = l; | |
6789 | + | |
6790 | + if (valid_ptr(function)) { | |
6791 | + if (0 > fpm_trace_get_strz(buf, buf_size, function + offsetof(zend_function, common.function_name))) { | |
6792 | + return -1; | |
6793 | + } | |
6794 | + | |
6795 | + fprintf(slowlog, "%s()", buf); | |
6796 | + } | |
6797 | + else { | |
6798 | + fprintf(slowlog, "???"); | |
6799 | + } | |
6800 | + | |
6801 | + if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, op_array), &l)) { | |
6802 | + return -1; | |
6803 | + } | |
6804 | + | |
6805 | + *buf = '\0'; | |
6806 | + | |
6807 | + if (valid_ptr(l)) { | |
6808 | + long op_array = l; | |
6809 | + | |
6810 | + if (0 > fpm_trace_get_strz(buf, buf_size, op_array + offsetof(zend_op_array, filename))) { | |
6811 | + return -1; | |
6812 | + } | |
6813 | + } | |
6814 | + | |
6815 | + if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, opline), &l)) { | |
6816 | + return -1; | |
6817 | + } | |
6818 | + | |
6819 | + if (valid_ptr(l)) { | |
6820 | + long opline = l; | |
6821 | + uint *lu = (uint *) &l; | |
6822 | + | |
6823 | + if (0 > fpm_trace_get_long(opline + offsetof(struct _zend_op, lineno), &l)) { | |
6824 | + return -1; | |
6825 | + } | |
6826 | + | |
6827 | + lineno = *lu; | |
6828 | + } | |
6829 | + | |
6830 | + fprintf(slowlog, " %s:%u\n", *buf ? buf : "unknown", lineno); | |
6831 | + | |
6832 | + if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, prev_execute_data), &l)) { | |
6833 | + return -1; | |
6834 | + } | |
6835 | + | |
6836 | + execute_data = l; | |
6837 | + | |
6838 | + if (0 == --callers_limit) { | |
6839 | + break; | |
6840 | + } | |
6841 | + } | |
6842 | + | |
6843 | + return 0; | |
6844 | +} | |
6845 | + | |
6846 | +void fpm_php_trace(struct fpm_child_s *child) | |
6847 | +{ | |
6848 | + TSRMLS_FETCH(); | |
6849 | + FILE *slowlog; | |
6850 | + | |
6851 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "about to trace %d", (int) child->pid); | |
6852 | + | |
6853 | + slowlog = fopen(child->wp->config->slowlog, "a+"); | |
6854 | + | |
6855 | + if (!slowlog) { | |
6856 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fopen(%s) failed", child->wp->config->slowlog); | |
6857 | + goto done0; | |
6858 | + } | |
6859 | + | |
6860 | + if (0 > fpm_trace_ready(child->pid)) { | |
6861 | + goto done1; | |
6862 | + } | |
6863 | + | |
6864 | + if (0 > fpm_php_trace_dump(child, slowlog TSRMLS_CC)) { | |
6865 | + fprintf(slowlog, "+++ dump failed\n"); | |
6866 | + } | |
6867 | + | |
6868 | + if (0 > fpm_trace_close(child->pid)) { | |
6869 | + goto done1; | |
6870 | + } | |
6871 | + | |
6872 | +done1: | |
6873 | + fclose(slowlog); | |
6874 | + | |
6875 | +done0: | |
6876 | + fpm_pctl_kill(child->pid, FPM_PCTL_CONT); | |
6877 | + child->tracer = 0; | |
6878 | + | |
6879 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "finished trace of %d", (int) child->pid); | |
6880 | +} | |
6881 | + | |
6882 | +#endif | |
6883 | + | |
6884 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_php_trace.h php-src/sapi/fpm/fpm/fpm_php_trace.h | |
6885 | --- php-src-vanilla/sapi/fpm/fpm/fpm_php_trace.h 1970-01-01 01:00:00.000000000 +0100 | |
6886 | +++ php-src/sapi/fpm/fpm/fpm_php_trace.h 2009-10-18 21:05:39.310440424 +0100 | |
6887 | @@ -0,0 +1,13 @@ | |
6888 | + | |
6889 | + /* $Id$ */ | |
6890 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
6891 | + | |
6892 | +#ifndef FPM_PHP_TRACE_H | |
6893 | +#define FPM_PHP_TRACE_H 1 | |
6894 | + | |
6895 | +struct fpm_child_s; | |
6896 | + | |
6897 | +void fpm_php_trace(struct fpm_child_s *); | |
6898 | + | |
6899 | +#endif | |
6900 | + | |
6901 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_process_ctl.c php-src/sapi/fpm/fpm/fpm_process_ctl.c | |
6902 | --- php-src-vanilla/sapi/fpm/fpm/fpm_process_ctl.c 1970-01-01 01:00:00.000000000 +0100 | |
6903 | +++ php-src/sapi/fpm/fpm/fpm_process_ctl.c 2009-10-18 21:05:39.308376784 +0100 | |
6904 | @@ -0,0 +1,354 @@ | |
6905 | + | |
6906 | + /* $Id$ */ | |
6907 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
6908 | + | |
6909 | +#include "fpm_config.h" | |
6910 | + | |
6911 | +#include <sys/types.h> | |
6912 | +#include <signal.h> | |
6913 | +#include <unistd.h> | |
6914 | +#include <stdlib.h> | |
6915 | + | |
6916 | +#include "fpm.h" | |
6917 | +#include "fpm_clock.h" | |
6918 | +#include "fpm_children.h" | |
6919 | +#include "fpm_signals.h" | |
6920 | +#include "fpm_events.h" | |
6921 | +#include "fpm_process_ctl.h" | |
6922 | +#include "fpm_cleanup.h" | |
6923 | +#include "fpm_request.h" | |
6924 | +#include "fpm_worker_pool.h" | |
6925 | +#include "zlog.h" | |
6926 | + | |
6927 | + | |
6928 | +static int fpm_state = FPM_PCTL_STATE_NORMAL; | |
6929 | +static int fpm_signal_sent = 0; | |
6930 | + | |
6931 | + | |
6932 | +static const char *fpm_state_names[] = { | |
6933 | + [FPM_PCTL_STATE_NORMAL] = "normal", | |
6934 | + [FPM_PCTL_STATE_RELOADING] = "reloading", | |
6935 | + [FPM_PCTL_STATE_TERMINATING] = "terminating", | |
6936 | + [FPM_PCTL_STATE_FINISHING] = "finishing" | |
6937 | +}; | |
6938 | + | |
6939 | +static int saved_argc; | |
6940 | +static char **saved_argv; | |
6941 | + | |
6942 | +static void fpm_pctl_cleanup(int which, void *arg) | |
6943 | +{ | |
6944 | + int i; | |
6945 | + | |
6946 | + if (which != FPM_CLEANUP_PARENT_EXEC) { | |
6947 | + | |
6948 | + for (i = 0; i < saved_argc; i++) { | |
6949 | + free(saved_argv[i]); | |
6950 | + } | |
6951 | + | |
6952 | + free(saved_argv); | |
6953 | + | |
6954 | + } | |
6955 | +} | |
6956 | + | |
6957 | +static struct event pctl_event; | |
6958 | + | |
6959 | +static void fpm_pctl_action(int fd, short which, void *arg) | |
6960 | +{ | |
6961 | + evtimer_del(&pctl_event); | |
6962 | + | |
6963 | + memset(&pctl_event, 0, sizeof(pctl_event)); | |
6964 | + | |
6965 | + fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_TIMEOUT); | |
6966 | +} | |
6967 | + | |
6968 | +static int fpm_pctl_timeout_set(int sec) | |
6969 | +{ | |
6970 | + struct timeval tv = { .tv_sec = sec, .tv_usec = 0 }; | |
6971 | + | |
6972 | + if (evtimer_initialized(&pctl_event)) { | |
6973 | + evtimer_del(&pctl_event); | |
6974 | + } | |
6975 | + | |
6976 | + evtimer_set(&pctl_event, &fpm_pctl_action, 0); | |
6977 | + | |
6978 | + evtimer_add(&pctl_event, &tv); | |
6979 | + | |
6980 | + return 0; | |
6981 | +} | |
6982 | + | |
6983 | +static void fpm_pctl_exit() | |
6984 | +{ | |
6985 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "exiting, bye-bye!"); | |
6986 | + | |
6987 | + fpm_conf_unlink_pid(); | |
6988 | + | |
6989 | + fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT_MAIN); | |
6990 | + | |
6991 | + exit(0); | |
6992 | +} | |
6993 | + | |
6994 | +#define optional_arg(c) (saved_argc > c ? ", \"" : ""), (saved_argc > c ? saved_argv[c] : ""), (saved_argc > c ? "\"" : "") | |
6995 | + | |
6996 | +static void fpm_pctl_exec() | |
6997 | +{ | |
6998 | + | |
6999 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "reloading: execvp(\"%s\", {\"%s\"" | |
7000 | + "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" | |
7001 | + "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" | |
7002 | + "})", | |
7003 | + saved_argv[0], saved_argv[0], | |
7004 | + optional_arg(1), | |
7005 | + optional_arg(2), | |
7006 | + optional_arg(3), | |
7007 | + optional_arg(4), | |
7008 | + optional_arg(5), | |
7009 | + optional_arg(6), | |
7010 | + optional_arg(7), | |
7011 | + optional_arg(8), | |
7012 | + optional_arg(9), | |
7013 | + optional_arg(10) | |
7014 | + ); | |
7015 | + | |
7016 | + fpm_cleanups_run(FPM_CLEANUP_PARENT_EXEC); | |
7017 | + | |
7018 | + execvp(saved_argv[0], saved_argv); | |
7019 | + | |
7020 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "execvp() failed"); | |
7021 | + | |
7022 | + exit(1); | |
7023 | +} | |
7024 | + | |
7025 | +static void fpm_pctl_action_last() | |
7026 | +{ | |
7027 | + switch (fpm_state) { | |
7028 | + | |
7029 | + case FPM_PCTL_STATE_RELOADING : | |
7030 | + | |
7031 | + fpm_pctl_exec(); | |
7032 | + break; | |
7033 | + | |
7034 | + case FPM_PCTL_STATE_FINISHING : | |
7035 | + | |
7036 | + case FPM_PCTL_STATE_TERMINATING : | |
7037 | + | |
7038 | + fpm_pctl_exit(); | |
7039 | + break; | |
7040 | + } | |
7041 | +} | |
7042 | + | |
7043 | +int fpm_pctl_kill(pid_t pid, int how) | |
7044 | +{ | |
7045 | + int s = 0; | |
7046 | + | |
7047 | + switch (how) { | |
7048 | + case FPM_PCTL_TERM : | |
7049 | + s = SIGTERM; | |
7050 | + break; | |
7051 | + case FPM_PCTL_STOP : | |
7052 | + s = SIGSTOP; | |
7053 | + break; | |
7054 | + case FPM_PCTL_CONT : | |
7055 | + s = SIGCONT; | |
7056 | + break; | |
7057 | + default : | |
7058 | + break; | |
7059 | + } | |
7060 | + | |
7061 | + return kill(pid, s); | |
7062 | +} | |
7063 | + | |
7064 | +static void fpm_pctl_kill_all(int signo) | |
7065 | +{ | |
7066 | + struct fpm_worker_pool_s *wp; | |
7067 | + int alive_children = 0; | |
7068 | + | |
7069 | + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { | |
7070 | + struct fpm_child_s *child; | |
7071 | + | |
7072 | + for (child = wp->children; child; child = child->next) { | |
7073 | + | |
7074 | + int res = kill(child->pid, signo); | |
7075 | + | |
7076 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "sending signal %d %s to child %d (pool %s)", signo, | |
7077 | + fpm_signal_names[signo] ? fpm_signal_names[signo] : "", | |
7078 | + (int) child->pid, child->wp->config->name); | |
7079 | + | |
7080 | + if (res == 0) { ++alive_children; } | |
7081 | + } | |
7082 | + } | |
7083 | + | |
7084 | + if (alive_children) { | |
7085 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "%d %s still alive", alive_children, alive_children == 1 ? "child is" : "children are"); | |
7086 | + } | |
7087 | +} | |
7088 | + | |
7089 | +static void fpm_pctl_action_next() | |
7090 | +{ | |
7091 | + int sig, timeout; | |
7092 | + | |
7093 | + if (!fpm_globals.running_children) { fpm_pctl_action_last(); } | |
7094 | + | |
7095 | + if (fpm_signal_sent == 0) { | |
7096 | + if (fpm_state == FPM_PCTL_STATE_TERMINATING) { | |
7097 | + sig = SIGTERM; | |
7098 | + } | |
7099 | + else { | |
7100 | + sig = SIGQUIT; | |
7101 | + } | |
7102 | + timeout = fpm_global_config.process_control_timeout; | |
7103 | + } | |
7104 | + else { | |
7105 | + if (fpm_signal_sent == SIGQUIT) { | |
7106 | + sig = SIGTERM; | |
7107 | + } | |
7108 | + else { | |
7109 | + sig = SIGKILL; | |
7110 | + } | |
7111 | + timeout = 1; | |
7112 | + } | |
7113 | + | |
7114 | + fpm_pctl_kill_all(sig); | |
7115 | + | |
7116 | + fpm_signal_sent = sig; | |
7117 | + | |
7118 | + fpm_pctl_timeout_set(timeout); | |
7119 | +} | |
7120 | + | |
7121 | +void fpm_pctl(int new_state, int action) | |
7122 | +{ | |
7123 | + switch (action) { | |
7124 | + | |
7125 | + case FPM_PCTL_ACTION_SET : | |
7126 | + | |
7127 | + if (fpm_state == new_state) { /* already in progress - just ignore duplicate signal */ | |
7128 | + return; | |
7129 | + } | |
7130 | + | |
7131 | + switch (fpm_state) { /* check which states can be overridden */ | |
7132 | + | |
7133 | + case FPM_PCTL_STATE_NORMAL : | |
7134 | + | |
7135 | + /* 'normal' can be overridden by any other state */ | |
7136 | + break; | |
7137 | + | |
7138 | + case FPM_PCTL_STATE_RELOADING : | |
7139 | + | |
7140 | + /* 'reloading' can be overridden by 'finishing' */ | |
7141 | + if (new_state == FPM_PCTL_STATE_FINISHING) { break; } | |
7142 | + | |
7143 | + case FPM_PCTL_STATE_FINISHING : | |
7144 | + | |
7145 | + /* 'reloading' and 'finishing' can be overridden by 'terminating' */ | |
7146 | + if (new_state == FPM_PCTL_STATE_TERMINATING) { break; } | |
7147 | + | |
7148 | + case FPM_PCTL_STATE_TERMINATING : | |
7149 | + | |
7150 | + /* nothing can override 'terminating' state */ | |
7151 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "not switching to '%s' state, because already in '%s' state", | |
7152 | + fpm_state_names[new_state], fpm_state_names[fpm_state]); | |
7153 | + | |
7154 | + return; | |
7155 | + } | |
7156 | + | |
7157 | + fpm_signal_sent = 0; | |
7158 | + fpm_state = new_state; | |
7159 | + | |
7160 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "switching to '%s' state", fpm_state_names[fpm_state]); | |
7161 | + | |
7162 | + /* fall down */ | |
7163 | + | |
7164 | + case FPM_PCTL_ACTION_TIMEOUT : | |
7165 | + | |
7166 | + fpm_pctl_action_next(); | |
7167 | + | |
7168 | + break; | |
7169 | + | |
7170 | + case FPM_PCTL_ACTION_LAST_CHILD_EXITED : | |
7171 | + | |
7172 | + fpm_pctl_action_last(); | |
7173 | + | |
7174 | + break; | |
7175 | + | |
7176 | + } | |
7177 | +} | |
7178 | + | |
7179 | +int fpm_pctl_can_spawn_children() | |
7180 | +{ | |
7181 | + return fpm_state == FPM_PCTL_STATE_NORMAL; | |
7182 | +} | |
7183 | + | |
7184 | +int fpm_pctl_child_exited() | |
7185 | +{ | |
7186 | + if (fpm_state == FPM_PCTL_STATE_NORMAL) { return 0; } | |
7187 | + | |
7188 | + if (!fpm_globals.running_children) { | |
7189 | + fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_LAST_CHILD_EXITED); | |
7190 | + } | |
7191 | + | |
7192 | + return 0; | |
7193 | +} | |
7194 | + | |
7195 | +int fpm_pctl_init_main() | |
7196 | +{ | |
7197 | + int i; | |
7198 | + | |
7199 | + saved_argc = fpm_globals.argc; | |
7200 | + | |
7201 | + saved_argv = malloc(sizeof(char *) * (saved_argc + 1)); | |
7202 | + | |
7203 | + if (!saved_argv) { | |
7204 | + return -1; | |
7205 | + } | |
7206 | + | |
7207 | + for (i = 0; i < saved_argc; i++) { | |
7208 | + saved_argv[i] = strdup(fpm_globals.argv[i]); | |
7209 | + | |
7210 | + if (!saved_argv[i]) { | |
7211 | + return -1; | |
7212 | + } | |
7213 | + } | |
7214 | + | |
7215 | + saved_argv[i] = 0; | |
7216 | + | |
7217 | + if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_pctl_cleanup, 0)) { | |
7218 | + return -1; | |
7219 | + } | |
7220 | + | |
7221 | + return 0; | |
7222 | +} | |
7223 | + | |
7224 | +static void fpm_pctl_check_request_timeout(struct timeval *now) | |
7225 | +{ | |
7226 | + struct fpm_worker_pool_s *wp; | |
7227 | + | |
7228 | + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { | |
7229 | + int terminate_timeout = wp->config->request_terminate_timeout; | |
7230 | + int slowlog_timeout = wp->config->request_slowlog_timeout; | |
7231 | + struct fpm_child_s *child; | |
7232 | + | |
7233 | + if (terminate_timeout || slowlog_timeout) { | |
7234 | + for (child = wp->children; child; child = child->next) { | |
7235 | + fpm_request_check_timed_out(child, now, terminate_timeout, slowlog_timeout); | |
7236 | + } | |
7237 | + } | |
7238 | + } | |
7239 | + | |
7240 | +} | |
7241 | + | |
7242 | +void fpm_pctl_heartbeat(int fd, short which, void *arg) | |
7243 | +{ | |
7244 | + static struct event heartbeat; | |
7245 | + struct timeval tv = { .tv_sec = 0, .tv_usec = 130000 }; | |
7246 | + struct timeval now; | |
7247 | + | |
7248 | + if (which == EV_TIMEOUT) { | |
7249 | + evtimer_del(&heartbeat); | |
7250 | + fpm_clock_get(&now); | |
7251 | + fpm_pctl_check_request_timeout(&now); | |
7252 | + } | |
7253 | + | |
7254 | + evtimer_set(&heartbeat, &fpm_pctl_heartbeat, 0); | |
7255 | + | |
7256 | + evtimer_add(&heartbeat, &tv); | |
7257 | +} | |
7258 | + | |
7259 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_process_ctl.h php-src/sapi/fpm/fpm/fpm_process_ctl.h | |
7260 | --- php-src-vanilla/sapi/fpm/fpm/fpm_process_ctl.h 1970-01-01 01:00:00.000000000 +0100 | |
7261 | +++ php-src/sapi/fpm/fpm/fpm_process_ctl.h 2009-10-18 21:05:39.310440424 +0100 | |
7262 | @@ -0,0 +1,39 @@ | |
7263 | + | |
7264 | + /* $Id$ */ | |
7265 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
7266 | + | |
7267 | +#ifndef FPM_PROCESS_CTL_H | |
7268 | +#define FPM_PROCESS_CTL_H 1 | |
7269 | + | |
7270 | +struct fpm_child_s; | |
7271 | + | |
7272 | +void fpm_pctl(int new_state, int action); | |
7273 | +int fpm_pctl_can_spawn_children(); | |
7274 | +int fpm_pctl_kill(pid_t pid, int how); | |
7275 | +void fpm_pctl_heartbeat(int fd, short which, void *arg); | |
7276 | +int fpm_pctl_child_exited(); | |
7277 | +int fpm_pctl_init_main(); | |
7278 | + | |
7279 | + | |
7280 | +enum { | |
7281 | + FPM_PCTL_STATE_UNSPECIFIED, | |
7282 | + FPM_PCTL_STATE_NORMAL, | |
7283 | + FPM_PCTL_STATE_RELOADING, | |
7284 | + FPM_PCTL_STATE_TERMINATING, | |
7285 | + FPM_PCTL_STATE_FINISHING | |
7286 | +}; | |
7287 | + | |
7288 | +enum { | |
7289 | + FPM_PCTL_ACTION_SET, | |
7290 | + FPM_PCTL_ACTION_TIMEOUT, | |
7291 | + FPM_PCTL_ACTION_LAST_CHILD_EXITED | |
7292 | +}; | |
7293 | + | |
7294 | +enum { | |
7295 | + FPM_PCTL_TERM, | |
7296 | + FPM_PCTL_STOP, | |
7297 | + FPM_PCTL_CONT | |
7298 | +}; | |
7299 | + | |
7300 | +#endif | |
7301 | + | |
7302 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_request.c php-src/sapi/fpm/fpm/fpm_request.c | |
7303 | --- php-src-vanilla/sapi/fpm/fpm/fpm_request.c 1970-01-01 01:00:00.000000000 +0100 | |
7304 | +++ php-src/sapi/fpm/fpm/fpm_request.c 2009-10-18 21:05:39.310440424 +0100 | |
7305 | @@ -0,0 +1,164 @@ | |
7306 | + | |
7307 | + /* $Id$ */ | |
7308 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
7309 | + | |
7310 | +#include "fpm_config.h" | |
7311 | + | |
7312 | +#include "fpm_php.h" | |
7313 | +#include "fpm_str.h" | |
7314 | +#include "fpm_clock.h" | |
7315 | +#include "fpm_conf.h" | |
7316 | +#include "fpm_trace.h" | |
7317 | +#include "fpm_php_trace.h" | |
7318 | +#include "fpm_process_ctl.h" | |
7319 | +#include "fpm_children.h" | |
7320 | +#include "fpm_shm_slots.h" | |
7321 | +#include "fpm_request.h" | |
7322 | + | |
7323 | +#include "zlog.h" | |
7324 | + | |
7325 | +void fpm_request_accepting() | |
7326 | +{ | |
7327 | + struct fpm_shm_slot_s *slot; | |
7328 | + | |
7329 | + slot = fpm_shm_slots_acquire(0, 0); | |
7330 | + | |
7331 | + slot->request_stage = FPM_REQUEST_ACCEPTING; | |
7332 | + | |
7333 | + fpm_clock_get(&slot->tv); | |
7334 | + memset(slot->request_method, 0, sizeof(slot->request_method)); | |
7335 | + slot->content_length = 0; | |
7336 | + memset(slot->script_filename, 0, sizeof(slot->script_filename)); | |
7337 | + | |
7338 | + fpm_shm_slots_release(slot); | |
7339 | +} | |
7340 | + | |
7341 | +void fpm_request_reading_headers() | |
7342 | +{ | |
7343 | + struct fpm_shm_slot_s *slot; | |
7344 | + | |
7345 | + slot = fpm_shm_slots_acquire(0, 0); | |
7346 | + | |
7347 | + slot->request_stage = FPM_REQUEST_READING_HEADERS; | |
7348 | + | |
7349 | + fpm_clock_get(&slot->tv); | |
7350 | + slot->accepted = slot->tv; | |
7351 | + | |
7352 | + fpm_shm_slots_release(slot); | |
7353 | +} | |
7354 | + | |
7355 | +void fpm_request_info() | |
7356 | +{ | |
7357 | + TSRMLS_FETCH(); | |
7358 | + struct fpm_shm_slot_s *slot; | |
7359 | + char *request_method = fpm_php_request_method(TSRMLS_C); | |
7360 | + char *script_filename = fpm_php_script_filename(TSRMLS_C); | |
7361 | + | |
7362 | + slot = fpm_shm_slots_acquire(0, 0); | |
7363 | + | |
7364 | + slot->request_stage = FPM_REQUEST_INFO; | |
7365 | + | |
7366 | + fpm_clock_get(&slot->tv); | |
7367 | + | |
7368 | + if (request_method) { | |
7369 | + cpystrn(slot->request_method, request_method, sizeof(slot->request_method)); | |
7370 | + } | |
7371 | + | |
7372 | + slot->content_length = fpm_php_content_length(TSRMLS_C); | |
7373 | + | |
7374 | + /* if cgi.fix_pathinfo is set to "1" and script cannot be found (404) | |
7375 | + the sapi_globals.request_info.path_translated is set to NULL */ | |
7376 | + if (script_filename) { | |
7377 | + cpystrn(slot->script_filename, script_filename, sizeof(slot->script_filename)); | |
7378 | + } | |
7379 | + | |
7380 | + fpm_shm_slots_release(slot); | |
7381 | +} | |
7382 | + | |
7383 | +void fpm_request_executing() | |
7384 | +{ | |
7385 | + struct fpm_shm_slot_s *slot; | |
7386 | + | |
7387 | + slot = fpm_shm_slots_acquire(0, 0); | |
7388 | + | |
7389 | + slot->request_stage = FPM_REQUEST_EXECUTING; | |
7390 | + | |
7391 | + fpm_clock_get(&slot->tv); | |
7392 | + | |
7393 | + fpm_shm_slots_release(slot); | |
7394 | +} | |
7395 | + | |
7396 | +void fpm_request_finished() | |
7397 | +{ | |
7398 | + struct fpm_shm_slot_s *slot; | |
7399 | + | |
7400 | + slot = fpm_shm_slots_acquire(0, 0); | |
7401 | + | |
7402 | + slot->request_stage = FPM_REQUEST_FINISHED; | |
7403 | + | |
7404 | + fpm_clock_get(&slot->tv); | |
7405 | + memset(&slot->accepted, 0, sizeof(slot->accepted)); | |
7406 | + | |
7407 | + fpm_shm_slots_release(slot); | |
7408 | +} | |
7409 | + | |
7410 | +void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, int terminate_timeout, int slowlog_timeout) | |
7411 | +{ | |
7412 | + struct fpm_shm_slot_s *slot; | |
7413 | + struct fpm_shm_slot_s slot_c; | |
7414 | + | |
7415 | + slot = fpm_shm_slot(child); | |
7416 | + | |
7417 | + if (!fpm_shm_slots_acquire(slot, 1)) { | |
7418 | + return; | |
7419 | + } | |
7420 | + | |
7421 | + slot_c = *slot; | |
7422 | + | |
7423 | + fpm_shm_slots_release(slot); | |
7424 | + | |
7425 | +#if HAVE_FPM_TRACE | |
7426 | + if (child->slow_logged.tv_sec) { | |
7427 | + if (child->slow_logged.tv_sec != slot_c.accepted.tv_sec || child->slow_logged.tv_usec != slot_c.accepted.tv_usec) { | |
7428 | + child->slow_logged.tv_sec = 0; | |
7429 | + child->slow_logged.tv_usec = 0; | |
7430 | + } | |
7431 | + } | |
7432 | +#endif | |
7433 | + | |
7434 | + if (slot_c.request_stage > FPM_REQUEST_ACCEPTING && slot_c.request_stage < FPM_REQUEST_FINISHED) { | |
7435 | + char purified_script_filename[sizeof(slot_c.script_filename)]; | |
7436 | + struct timeval tv; | |
7437 | + | |
7438 | + timersub(now, &slot_c.accepted, &tv); | |
7439 | + | |
7440 | +#if HAVE_FPM_TRACE | |
7441 | + if (child->slow_logged.tv_sec == 0 && slowlog_timeout && | |
7442 | + slot_c.request_stage == FPM_REQUEST_EXECUTING && tv.tv_sec >= slowlog_timeout) { | |
7443 | + | |
7444 | + str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename)); | |
7445 | + | |
7446 | + child->slow_logged = slot_c.accepted; | |
7447 | + child->tracer = fpm_php_trace; | |
7448 | + | |
7449 | + fpm_trace_signal(child->pid); | |
7450 | + | |
7451 | + zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d, script '%s' (pool %s) executing too slow (%d.%06d sec), logging", | |
7452 | + (int) child->pid, purified_script_filename, child->wp->config->name, (int) tv.tv_sec, (int) tv.tv_usec); | |
7453 | + } | |
7454 | + | |
7455 | + else | |
7456 | +#endif | |
7457 | + if (terminate_timeout && tv.tv_sec >= terminate_timeout) { | |
7458 | + | |
7459 | + str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename)); | |
7460 | + | |
7461 | + fpm_pctl_kill(child->pid, FPM_PCTL_TERM); | |
7462 | + | |
7463 | + zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d, script '%s' (pool %s) execution timed out (%d.%06d sec), terminating", | |
7464 | + (int) child->pid, purified_script_filename, child->wp->config->name, (int) tv.tv_sec, (int) tv.tv_usec); | |
7465 | + } | |
7466 | + } | |
7467 | + | |
7468 | +} | |
7469 | + | |
7470 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_request.h php-src/sapi/fpm/fpm/fpm_request.h | |
7471 | --- php-src-vanilla/sapi/fpm/fpm/fpm_request.h 1970-01-01 01:00:00.000000000 +0100 | |
7472 | +++ php-src/sapi/fpm/fpm/fpm_request.h 2009-10-18 21:05:39.308376784 +0100 | |
7473 | @@ -0,0 +1,27 @@ | |
7474 | + | |
7475 | + /* $Id$ */ | |
7476 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
7477 | + | |
7478 | +#ifndef FPM_REQUEST_H | |
7479 | +#define FPM_REQUEST_H 1 | |
7480 | + | |
7481 | +void fpm_request_accepting(); /* hanging in accept() */ | |
7482 | +void fpm_request_reading_headers(); /* start reading fastcgi request from very first byte */ | |
7483 | +void fpm_request_info(); /* not a stage really but a point in the php code, where all request params have become known to sapi */ | |
7484 | +void fpm_request_executing(); /* the script is executing */ | |
7485 | +void fpm_request_finished(); /* request processed: script response have been sent to web server */ | |
7486 | + | |
7487 | +struct fpm_child_s; | |
7488 | +struct timeval; | |
7489 | + | |
7490 | +void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *tv, int terminate_timeout, int slowlog_timeout); | |
7491 | + | |
7492 | +enum fpm_request_stage_e { | |
7493 | + FPM_REQUEST_ACCEPTING = 1, | |
7494 | + FPM_REQUEST_READING_HEADERS, | |
7495 | + FPM_REQUEST_INFO, | |
7496 | + FPM_REQUEST_EXECUTING, | |
7497 | + FPM_REQUEST_FINISHED | |
7498 | +}; | |
7499 | + | |
7500 | +#endif | |
7501 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_shm.c php-src/sapi/fpm/fpm/fpm_shm.c | |
7502 | --- php-src-vanilla/sapi/fpm/fpm/fpm_shm.c 1970-01-01 01:00:00.000000000 +0100 | |
7503 | +++ php-src/sapi/fpm/fpm/fpm_shm.c 2009-10-18 21:05:39.308376784 +0100 | |
7504 | @@ -0,0 +1,100 @@ | |
7505 | + | |
7506 | + /* $Id$ */ | |
7507 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
7508 | + | |
7509 | +#include "fpm_config.h" | |
7510 | + | |
7511 | +#include <unistd.h> | |
7512 | +#include <sys/mman.h> | |
7513 | +#include <stdlib.h> | |
7514 | + | |
7515 | +#include "fpm_shm.h" | |
7516 | +#include "zlog.h" | |
7517 | + | |
7518 | + | |
7519 | +/* MAP_ANON is depricated, but not in macosx */ | |
7520 | +#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) | |
7521 | +#define MAP_ANONYMOUS MAP_ANON | |
7522 | +#endif | |
7523 | + | |
7524 | + | |
7525 | +struct fpm_shm_s *fpm_shm_alloc(size_t sz) | |
7526 | +{ | |
7527 | + struct fpm_shm_s *shm; | |
7528 | + | |
7529 | + shm = malloc(sizeof(*shm)); | |
7530 | + | |
7531 | + if (!shm) { | |
7532 | + return 0; | |
7533 | + } | |
7534 | + | |
7535 | + shm->mem = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); | |
7536 | + | |
7537 | + if (!shm->mem) { | |
7538 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "mmap(MAP_ANONYMOUS | MAP_SHARED) failed"); | |
7539 | + free(shm); | |
7540 | + return 0; | |
7541 | + } | |
7542 | + | |
7543 | + shm->used = 0; | |
7544 | + shm->sz = sz; | |
7545 | + | |
7546 | + return shm; | |
7547 | +} | |
7548 | + | |
7549 | +static void fpm_shm_free(struct fpm_shm_s *shm, int do_unmap) | |
7550 | +{ | |
7551 | + if (do_unmap) { | |
7552 | + munmap(shm->mem, shm->sz); | |
7553 | + } | |
7554 | + | |
7555 | + free(shm); | |
7556 | +} | |
7557 | + | |
7558 | +void fpm_shm_free_list(struct fpm_shm_s *shm, void *mem) | |
7559 | +{ | |
7560 | + struct fpm_shm_s *next; | |
7561 | + | |
7562 | + for (; shm; shm = next) { | |
7563 | + next = shm->next; | |
7564 | + | |
7565 | + fpm_shm_free(shm, mem != shm->mem); | |
7566 | + } | |
7567 | +} | |
7568 | + | |
7569 | +void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem) | |
7570 | +{ | |
7571 | + size_t pagesize = getpagesize(); | |
7572 | + static const size_t cache_line_size = 16; | |
7573 | + size_t aligned_sz; | |
7574 | + struct fpm_shm_s *shm; | |
7575 | + void *ret; | |
7576 | + | |
7577 | + sz = (sz + cache_line_size - 1) & -cache_line_size; | |
7578 | + | |
7579 | + shm = *head; | |
7580 | + | |
7581 | + if (0 == shm || shm->sz - shm->used < sz) { | |
7582 | + /* allocate one more shm segment */ | |
7583 | + | |
7584 | + aligned_sz = (sz + pagesize - 1) & -pagesize; | |
7585 | + | |
7586 | + shm = fpm_shm_alloc(aligned_sz); | |
7587 | + | |
7588 | + if (!shm) { | |
7589 | + return 0; | |
7590 | + } | |
7591 | + | |
7592 | + shm->next = *head; | |
7593 | + if (shm->next) { shm->next->prev = shm; } | |
7594 | + shm->prev = 0; | |
7595 | + *head = shm; | |
7596 | + } | |
7597 | + | |
7598 | + *mem = shm->mem; | |
7599 | + ret = (char *) shm->mem + shm->used; | |
7600 | + shm->used += sz; | |
7601 | + | |
7602 | + return ret; | |
7603 | +} | |
7604 | + | |
7605 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_shm.h php-src/sapi/fpm/fpm/fpm_shm.h | |
7606 | --- php-src-vanilla/sapi/fpm/fpm/fpm_shm.h 1970-01-01 01:00:00.000000000 +0100 | |
7607 | +++ php-src/sapi/fpm/fpm/fpm_shm.h 2009-10-18 21:05:39.308376784 +0100 | |
7608 | @@ -0,0 +1,22 @@ | |
7609 | + | |
7610 | + /* $Id$ */ | |
7611 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
7612 | + | |
7613 | +#ifndef FPM_SHM_H | |
7614 | +#define FPM_SHM_H 1 | |
7615 | + | |
7616 | +struct fpm_shm_s; | |
7617 | + | |
7618 | +struct fpm_shm_s { | |
7619 | + struct fpm_shm_s *prev, *next; | |
7620 | + void *mem; | |
7621 | + size_t sz; | |
7622 | + size_t used; | |
7623 | +}; | |
7624 | + | |
7625 | +struct fpm_shm_s *fpm_shm_alloc(size_t sz); | |
7626 | +void fpm_shm_free_list(struct fpm_shm_s *, void *); | |
7627 | +void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem); | |
7628 | + | |
7629 | +#endif | |
7630 | + | |
7631 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_shm_slots.c php-src/sapi/fpm/fpm/fpm_shm_slots.c | |
7632 | --- php-src-vanilla/sapi/fpm/fpm/fpm_shm_slots.c 1970-01-01 01:00:00.000000000 +0100 | |
7633 | +++ php-src/sapi/fpm/fpm/fpm_shm_slots.c 2009-10-18 21:05:39.308376784 +0100 | |
7634 | @@ -0,0 +1,127 @@ | |
7635 | + | |
7636 | + /* $Id$ */ | |
7637 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
7638 | + | |
7639 | +#include "fpm_config.h" | |
7640 | + | |
7641 | +#include "fpm_atomic.h" | |
7642 | +#include "fpm_worker_pool.h" | |
7643 | +#include "fpm_children.h" | |
7644 | +#include "fpm_shm.h" | |
7645 | +#include "fpm_shm_slots.h" | |
7646 | +#include "zlog.h" | |
7647 | + | |
7648 | +static void *shm_mem; | |
7649 | +static struct fpm_shm_slot_s *shm_slot; | |
7650 | + | |
7651 | +int fpm_shm_slots_prepare_slot(struct fpm_child_s *child) | |
7652 | +{ | |
7653 | + struct fpm_worker_pool_s *wp = child->wp; | |
7654 | + struct fpm_shm_slot_ptr_s *shm_slot_ptr; | |
7655 | + | |
7656 | + child->shm_slot_i = wp->slots_used.used; | |
7657 | + | |
7658 | + shm_slot_ptr = fpm_array_push(&wp->slots_used); | |
7659 | + | |
7660 | + if (0 == shm_slot_ptr) { | |
7661 | + return -1; | |
7662 | + } | |
7663 | + | |
7664 | + if (0 == wp->slots_free.used) { | |
7665 | + shm_slot_ptr->shm_slot = fpm_shm_alloc_chunk(&wp->shm_list, sizeof(struct fpm_shm_slot_s), &shm_slot_ptr->mem); | |
7666 | + | |
7667 | + if (!shm_slot_ptr->shm_slot) { | |
7668 | + return -1; | |
7669 | + } | |
7670 | + } | |
7671 | + else { | |
7672 | + *shm_slot_ptr = *(struct fpm_shm_slot_ptr_s *) fpm_array_item_last(&wp->slots_free); | |
7673 | + | |
7674 | + --wp->slots_free.used; | |
7675 | + } | |
7676 | + | |
7677 | + memset(shm_slot_ptr->shm_slot, 0, sizeof(struct fpm_shm_slot_s)); | |
7678 | + | |
7679 | + shm_slot_ptr->child = child; | |
7680 | + | |
7681 | + return 0; | |
7682 | +} | |
7683 | + | |
7684 | +void fpm_shm_slots_discard_slot(struct fpm_child_s *child) | |
7685 | +{ | |
7686 | + struct fpm_shm_slot_ptr_s *shm_slot_ptr; | |
7687 | + struct fpm_worker_pool_s *wp = child->wp; | |
7688 | + int n; | |
7689 | + | |
7690 | + shm_slot_ptr = fpm_array_push(&wp->slots_free); | |
7691 | + | |
7692 | + if (shm_slot_ptr) { | |
7693 | + | |
7694 | + struct fpm_shm_slot_ptr_s *shm_slot_ptr_used; | |
7695 | + | |
7696 | + shm_slot_ptr_used = fpm_array_item(&wp->slots_used, child->shm_slot_i); | |
7697 | + | |
7698 | + *shm_slot_ptr = *shm_slot_ptr_used; | |
7699 | + | |
7700 | + shm_slot_ptr->child = 0; | |
7701 | + | |
7702 | + } | |
7703 | + | |
7704 | + n = fpm_array_item_remove(&wp->slots_used, child->shm_slot_i); | |
7705 | + | |
7706 | + if (n > -1) { | |
7707 | + shm_slot_ptr = fpm_array_item(&wp->slots_used, n); | |
7708 | + | |
7709 | + shm_slot_ptr->child->shm_slot_i = n; | |
7710 | + } | |
7711 | +} | |
7712 | + | |
7713 | +void fpm_shm_slots_child_use_slot(struct fpm_child_s *child) | |
7714 | +{ | |
7715 | + struct fpm_shm_slot_ptr_s *shm_slot_ptr; | |
7716 | + struct fpm_worker_pool_s *wp = child->wp; | |
7717 | + | |
7718 | + shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i); | |
7719 | + | |
7720 | + shm_slot = shm_slot_ptr->shm_slot; | |
7721 | + shm_mem = shm_slot_ptr->mem; | |
7722 | +} | |
7723 | + | |
7724 | +void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child) | |
7725 | +{ | |
7726 | + /* nothing to do */ | |
7727 | +} | |
7728 | + | |
7729 | +void *fpm_shm_slots_mem() | |
7730 | +{ | |
7731 | + return shm_mem; | |
7732 | +} | |
7733 | + | |
7734 | +struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child) | |
7735 | +{ | |
7736 | + struct fpm_shm_slot_ptr_s *shm_slot_ptr; | |
7737 | + struct fpm_worker_pool_s *wp = child->wp; | |
7738 | + | |
7739 | + shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i); | |
7740 | + | |
7741 | + return shm_slot_ptr->shm_slot; | |
7742 | +} | |
7743 | + | |
7744 | +struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *s, int nohang) | |
7745 | +{ | |
7746 | + if (s == 0) { | |
7747 | + s = shm_slot; | |
7748 | + } | |
7749 | + | |
7750 | + if (0 > fpm_spinlock(&s->lock, nohang)) { | |
7751 | + return 0; | |
7752 | + } | |
7753 | + | |
7754 | + return s; | |
7755 | +} | |
7756 | + | |
7757 | +void fpm_shm_slots_release(struct fpm_shm_slot_s *s) | |
7758 | +{ | |
7759 | + s->lock = 0; | |
7760 | +} | |
7761 | + | |
7762 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_shm_slots.h php-src/sapi/fpm/fpm/fpm_shm_slots.h | |
7763 | --- php-src-vanilla/sapi/fpm/fpm/fpm_shm_slots.h 1970-01-01 01:00:00.000000000 +0100 | |
7764 | +++ php-src/sapi/fpm/fpm/fpm_shm_slots.h 2009-10-18 21:05:39.308376784 +0100 | |
7765 | @@ -0,0 +1,43 @@ | |
7766 | + | |
7767 | + /* $Id$ */ | |
7768 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
7769 | + | |
7770 | +#ifndef FPM_SHM_SLOTS_H | |
7771 | +#define FPM_SHM_SLOTS_H 1 | |
7772 | + | |
7773 | +#include "fpm_atomic.h" | |
7774 | +#include "fpm_worker_pool.h" | |
7775 | +#include "fpm_request.h" | |
7776 | + | |
7777 | +struct fpm_child_s; | |
7778 | + | |
7779 | +struct fpm_shm_slot_s { | |
7780 | + union { | |
7781 | + atomic_t lock; | |
7782 | + char dummy[16]; | |
7783 | + }; | |
7784 | + enum fpm_request_stage_e request_stage; | |
7785 | + struct timeval accepted; | |
7786 | + struct timeval tv; | |
7787 | + char request_method[16]; | |
7788 | + size_t content_length; /* used with POST only */ | |
7789 | + char script_filename[256]; | |
7790 | +}; | |
7791 | + | |
7792 | +struct fpm_shm_slot_ptr_s { | |
7793 | + void *mem; | |
7794 | + struct fpm_shm_slot_s *shm_slot; | |
7795 | + struct fpm_child_s *child; | |
7796 | +}; | |
7797 | + | |
7798 | +int fpm_shm_slots_prepare_slot(struct fpm_child_s *child); | |
7799 | +void fpm_shm_slots_discard_slot(struct fpm_child_s *child); | |
7800 | +void fpm_shm_slots_child_use_slot(struct fpm_child_s *child); | |
7801 | +void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child); | |
7802 | +void *fpm_shm_slots_mem(); | |
7803 | +struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child); | |
7804 | +struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *, int nohang); | |
7805 | +void fpm_shm_slots_release(struct fpm_shm_slot_s *); | |
7806 | + | |
7807 | +#endif | |
7808 | + | |
7809 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_signals.c php-src/sapi/fpm/fpm/fpm_signals.c | |
7810 | --- php-src-vanilla/sapi/fpm/fpm/fpm_signals.c 1970-01-01 01:00:00.000000000 +0100 | |
7811 | +++ php-src/sapi/fpm/fpm/fpm_signals.c 2009-10-18 21:05:39.308376784 +0100 | |
7812 | @@ -0,0 +1,252 @@ | |
7813 | + | |
7814 | + /* $Id$ */ | |
7815 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
7816 | + | |
7817 | +#include "fpm_config.h" | |
7818 | + | |
7819 | +#include <signal.h> | |
7820 | +#include <stdio.h> | |
7821 | +#include <sys/types.h> | |
7822 | +#include <sys/socket.h> | |
7823 | +#include <stdlib.h> | |
7824 | +#include <string.h> | |
7825 | +#include <fcntl.h> | |
7826 | +#include <unistd.h> | |
7827 | +#include <errno.h> | |
7828 | + | |
7829 | +#include "fpm.h" | |
7830 | +#include "fpm_signals.h" | |
7831 | +#include "fpm_sockets.h" | |
7832 | +#include "fpm_php.h" | |
7833 | +#include "zlog.h" | |
7834 | + | |
7835 | +static int sp[2]; | |
7836 | + | |
7837 | +const char *fpm_signal_names[NSIG + 1] = { | |
7838 | +#ifdef SIGHUP | |
7839 | + [SIGHUP] = "SIGHUP", | |
7840 | +#endif | |
7841 | +#ifdef SIGINT | |
7842 | + [SIGINT] = "SIGINT", | |
7843 | +#endif | |
7844 | +#ifdef SIGQUIT | |
7845 | + [SIGQUIT] = "SIGQUIT", | |
7846 | +#endif | |
7847 | +#ifdef SIGILL | |
7848 | + [SIGILL] = "SIGILL", | |
7849 | +#endif | |
7850 | +#ifdef SIGTRAP | |
7851 | + [SIGTRAP] = "SIGTRAP", | |
7852 | +#endif | |
7853 | +#ifdef SIGABRT | |
7854 | + [SIGABRT] = "SIGABRT", | |
7855 | +#endif | |
7856 | +#ifdef SIGEMT | |
7857 | + [SIGEMT] = "SIGEMT", | |
7858 | +#endif | |
7859 | +#ifdef SIGBUS | |
7860 | + [SIGBUS] = "SIGBUS", | |
7861 | +#endif | |
7862 | +#ifdef SIGFPE | |
7863 | + [SIGFPE] = "SIGFPE", | |
7864 | +#endif | |
7865 | +#ifdef SIGKILL | |
7866 | + [SIGKILL] = "SIGKILL", | |
7867 | +#endif | |
7868 | +#ifdef SIGUSR1 | |
7869 | + [SIGUSR1] = "SIGUSR1", | |
7870 | +#endif | |
7871 | +#ifdef SIGSEGV | |
7872 | + [SIGSEGV] = "SIGSEGV", | |
7873 | +#endif | |
7874 | +#ifdef SIGUSR2 | |
7875 | + [SIGUSR2] = "SIGUSR2", | |
7876 | +#endif | |
7877 | +#ifdef SIGPIPE | |
7878 | + [SIGPIPE] = "SIGPIPE", | |
7879 | +#endif | |
7880 | +#ifdef SIGALRM | |
7881 | + [SIGALRM] = "SIGALRM", | |
7882 | +#endif | |
7883 | +#ifdef SIGTERM | |
7884 | + [SIGTERM] = "SIGTERM", | |
7885 | +#endif | |
7886 | +#ifdef SIGCHLD | |
7887 | + [SIGCHLD] = "SIGCHLD", | |
7888 | +#endif | |
7889 | +#ifdef SIGCONT | |
7890 | + [SIGCONT] = "SIGCONT", | |
7891 | +#endif | |
7892 | +#ifdef SIGSTOP | |
7893 | + [SIGSTOP] = "SIGSTOP", | |
7894 | +#endif | |
7895 | +#ifdef SIGTSTP | |
7896 | + [SIGTSTP] = "SIGTSTP", | |
7897 | +#endif | |
7898 | +#ifdef SIGTTIN | |
7899 | + [SIGTTIN] = "SIGTTIN", | |
7900 | +#endif | |
7901 | +#ifdef SIGTTOU | |
7902 | + [SIGTTOU] = "SIGTTOU", | |
7903 | +#endif | |
7904 | +#ifdef SIGURG | |
7905 | + [SIGURG] = "SIGURG", | |
7906 | +#endif | |
7907 | +#ifdef SIGXCPU | |
7908 | + [SIGXCPU] = "SIGXCPU", | |
7909 | +#endif | |
7910 | +#ifdef SIGXFSZ | |
7911 | + [SIGXFSZ] = "SIGXFSZ", | |
7912 | +#endif | |
7913 | +#ifdef SIGVTALRM | |
7914 | + [SIGVTALRM] = "SIGVTALRM", | |
7915 | +#endif | |
7916 | +#ifdef SIGPROF | |
7917 | + [SIGPROF] = "SIGPROF", | |
7918 | +#endif | |
7919 | +#ifdef SIGWINCH | |
7920 | + [SIGWINCH] = "SIGWINCH", | |
7921 | +#endif | |
7922 | +#ifdef SIGINFO | |
7923 | + [SIGINFO] = "SIGINFO", | |
7924 | +#endif | |
7925 | +#ifdef SIGIO | |
7926 | + [SIGIO] = "SIGIO", | |
7927 | +#endif | |
7928 | +#ifdef SIGPWR | |
7929 | + [SIGPWR] = "SIGPWR", | |
7930 | +#endif | |
7931 | +#ifdef SIGSYS | |
7932 | + [SIGSYS] = "SIGSYS", | |
7933 | +#endif | |
7934 | +#ifdef SIGWAITING | |
7935 | + [SIGWAITING] = "SIGWAITING", | |
7936 | +#endif | |
7937 | +#ifdef SIGLWP | |
7938 | + [SIGLWP] = "SIGLWP", | |
7939 | +#endif | |
7940 | +#ifdef SIGFREEZE | |
7941 | + [SIGFREEZE] = "SIGFREEZE", | |
7942 | +#endif | |
7943 | +#ifdef SIGTHAW | |
7944 | + [SIGTHAW] = "SIGTHAW", | |
7945 | +#endif | |
7946 | +#ifdef SIGCANCEL | |
7947 | + [SIGCANCEL] = "SIGCANCEL", | |
7948 | +#endif | |
7949 | +#ifdef SIGLOST | |
7950 | + [SIGLOST] = "SIGLOST", | |
7951 | +#endif | |
7952 | +}; | |
7953 | + | |
7954 | +static void sig_soft_quit(int signo) | |
7955 | +{ | |
7956 | + int saved_errno = errno; | |
7957 | + | |
7958 | + /* closing fastcgi listening socket will force fcgi_accept() exit immediately */ | |
7959 | + close(0); | |
7960 | + socket(AF_UNIX, SOCK_STREAM, 0); | |
7961 | + | |
7962 | + fpm_php_soft_quit(); | |
7963 | + | |
7964 | + errno = saved_errno; | |
7965 | +} | |
7966 | + | |
7967 | +static void sig_handler(int signo) | |
7968 | +{ | |
7969 | + static const char sig_chars[NSIG + 1] = { | |
7970 | + [SIGTERM] = 'T', | |
7971 | + [SIGINT] = 'I', | |
7972 | + [SIGUSR1] = '1', | |
7973 | + [SIGUSR2] = '2', | |
7974 | + [SIGQUIT] = 'Q', | |
7975 | + [SIGCHLD] = 'C' | |
7976 | + }; | |
7977 | + char s; | |
7978 | + int saved_errno; | |
7979 | + | |
7980 | + if (fpm_globals.parent_pid != getpid()) { | |
7981 | + /* prevent a signal race condition when child process | |
7982 | + have not set up it's own signal handler yet */ | |
7983 | + return; | |
7984 | + } | |
7985 | + | |
7986 | + saved_errno = errno; | |
7987 | + | |
7988 | + s = sig_chars[signo]; | |
7989 | + | |
7990 | + write(sp[1], &s, sizeof(s)); | |
7991 | + | |
7992 | + errno = saved_errno; | |
7993 | +} | |
7994 | + | |
7995 | +int fpm_signals_init_main() | |
7996 | +{ | |
7997 | + struct sigaction act; | |
7998 | + | |
7999 | + if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) { | |
8000 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "socketpair() failed"); | |
8001 | + return -1; | |
8002 | + } | |
8003 | + | |
8004 | + if (0 > fd_set_blocked(sp[0], 0) || 0 > fd_set_blocked(sp[1], 0)) { | |
8005 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fd_set_blocked() failed"); | |
8006 | + return -1; | |
8007 | + } | |
8008 | + | |
8009 | + if (0 > fcntl(sp[0], F_SETFD, FD_CLOEXEC) || 0 > fcntl(sp[1], F_SETFD, FD_CLOEXEC)) { | |
8010 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fcntl(F_SETFD, FD_CLOEXEC) failed"); | |
8011 | + return -1; | |
8012 | + } | |
8013 | + | |
8014 | + memset(&act, 0, sizeof(act)); | |
8015 | + act.sa_handler = sig_handler; | |
8016 | + sigfillset(&act.sa_mask); | |
8017 | + | |
8018 | + if (0 > sigaction(SIGTERM, &act, 0) || | |
8019 | + 0 > sigaction(SIGINT, &act, 0) || | |
8020 | + 0 > sigaction(SIGUSR1, &act, 0) || | |
8021 | + 0 > sigaction(SIGUSR2, &act, 0) || | |
8022 | + 0 > sigaction(SIGCHLD, &act, 0) || | |
8023 | + 0 > sigaction(SIGQUIT, &act, 0)) { | |
8024 | + | |
8025 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed"); | |
8026 | + return -1; | |
8027 | + } | |
8028 | + | |
8029 | + return 0; | |
8030 | +} | |
8031 | + | |
8032 | +int fpm_signals_init_child() | |
8033 | +{ | |
8034 | + struct sigaction act, act_dfl; | |
8035 | + | |
8036 | + memset(&act, 0, sizeof(act)); | |
8037 | + memset(&act_dfl, 0, sizeof(act_dfl)); | |
8038 | + | |
8039 | + act.sa_handler = &sig_soft_quit; | |
8040 | + act.sa_flags |= SA_RESTART; | |
8041 | + | |
8042 | + act_dfl.sa_handler = SIG_DFL; | |
8043 | + | |
8044 | + close(sp[0]); | |
8045 | + close(sp[1]); | |
8046 | + | |
8047 | + if (0 > sigaction(SIGTERM, &act_dfl, 0) || | |
8048 | + 0 > sigaction(SIGINT, &act_dfl, 0) || | |
8049 | + 0 > sigaction(SIGUSR1, &act_dfl, 0) || | |
8050 | + 0 > sigaction(SIGUSR2, &act_dfl, 0) || | |
8051 | + 0 > sigaction(SIGCHLD, &act_dfl, 0) || | |
8052 | + 0 > sigaction(SIGQUIT, &act, 0)) { | |
8053 | + | |
8054 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed"); | |
8055 | + return -1; | |
8056 | + } | |
8057 | + | |
8058 | + return 0; | |
8059 | +} | |
8060 | + | |
8061 | +int fpm_signals_get_fd() | |
8062 | +{ | |
8063 | + return sp[0]; | |
8064 | +} | |
8065 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_signals.h php-src/sapi/fpm/fpm/fpm_signals.h | |
8066 | --- php-src-vanilla/sapi/fpm/fpm/fpm_signals.h 1970-01-01 01:00:00.000000000 +0100 | |
8067 | +++ php-src/sapi/fpm/fpm/fpm_signals.h 2009-10-18 21:05:39.308376784 +0100 | |
8068 | @@ -0,0 +1,16 @@ | |
8069 | + | |
8070 | + /* $Id$ */ | |
8071 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
8072 | + | |
8073 | +#ifndef FPM_SIGNALS_H | |
8074 | +#define FPM_SIGNALS_H 1 | |
8075 | + | |
8076 | +#include <signal.h> | |
8077 | + | |
8078 | +int fpm_signals_init_main(); | |
8079 | +int fpm_signals_init_child(); | |
8080 | +int fpm_signals_get_fd(); | |
8081 | + | |
8082 | +extern const char *fpm_signal_names[NSIG + 1]; | |
8083 | + | |
8084 | +#endif | |
8085 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_sockets.c php-src/sapi/fpm/fpm/fpm_sockets.c | |
8086 | --- php-src-vanilla/sapi/fpm/fpm/fpm_sockets.c 1970-01-01 01:00:00.000000000 +0100 | |
8087 | +++ php-src/sapi/fpm/fpm/fpm_sockets.c 2009-10-18 21:05:39.310440424 +0100 | |
8088 | @@ -0,0 +1,427 @@ | |
8089 | + | |
8090 | + /* $Id$ */ | |
8091 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
8092 | + | |
8093 | +#include "fpm_config.h" | |
8094 | + | |
8095 | +#ifdef HAVE_ALLOCA_H | |
8096 | +#include <alloca.h> | |
8097 | +#endif | |
8098 | +#include <sys/types.h> | |
8099 | +#include <sys/stat.h> /* for chmod(2) */ | |
8100 | +#include <sys/socket.h> | |
8101 | +#include <netinet/in.h> | |
8102 | +#include <arpa/inet.h> | |
8103 | +#include <sys/un.h> | |
8104 | +#include <netdb.h> | |
8105 | +#include <stdio.h> | |
8106 | +#include <stdlib.h> | |
8107 | +#include <string.h> | |
8108 | +#include <errno.h> | |
8109 | +#include <unistd.h> | |
8110 | + | |
8111 | +#include "zlog.h" | |
8112 | +#include "fpm_arrays.h" | |
8113 | +#include "fpm_sockets.h" | |
8114 | +#include "fpm_worker_pool.h" | |
8115 | +#include "fpm_unix.h" | |
8116 | +#include "fpm_str.h" | |
8117 | +#include "fpm_env.h" | |
8118 | +#include "fpm_cleanup.h" | |
8119 | + | |
8120 | +struct listening_socket_s { | |
8121 | + int refcount; | |
8122 | + int sock; | |
8123 | + int type; | |
8124 | + char *key; | |
8125 | +}; | |
8126 | + | |
8127 | +static struct fpm_array_s sockets_list; | |
8128 | + | |
8129 | +static int fpm_sockets_resolve_af_inet(char *node, char *service, struct sockaddr_in *addr) | |
8130 | +{ | |
8131 | + struct addrinfo *res; | |
8132 | + struct addrinfo hints; | |
8133 | + int ret; | |
8134 | + | |
8135 | + memset(&hints, 0, sizeof(hints)); | |
8136 | + | |
8137 | + hints.ai_family = AF_INET; | |
8138 | + | |
8139 | + ret = getaddrinfo(node, service, &hints, &res); | |
8140 | + | |
8141 | + if (ret != 0) { | |
8142 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "can't resolve hostname '%s%s%s': getaddrinfo said: %s%s%s\n", | |
8143 | + node, service ? ":" : "", service ? service : "", | |
8144 | + gai_strerror(ret), ret == EAI_SYSTEM ? ", system error: " : "", ret == EAI_SYSTEM ? strerror(errno) : ""); | |
8145 | + return -1; | |
8146 | + } | |
8147 | + | |
8148 | + *addr = *(struct sockaddr_in *) res->ai_addr; | |
8149 | + | |
8150 | + freeaddrinfo(res); | |
8151 | + | |
8152 | + return 0; | |
8153 | +} | |
8154 | + | |
8155 | +enum { FPM_GET_USE_SOCKET = 1, FPM_STORE_SOCKET = 2, FPM_STORE_USE_SOCKET = 3 }; | |
8156 | + | |
8157 | +static void fpm_sockets_cleanup(int which, void *arg) | |
8158 | +{ | |
8159 | + int i; | |
8160 | + char *env_value = 0; | |
8161 | + int p = 0; | |
8162 | + struct listening_socket_s *ls = sockets_list.data; | |
8163 | + | |
8164 | + for (i = 0; i < sockets_list.used; i++, ls++) { | |
8165 | + | |
8166 | + if (which != FPM_CLEANUP_PARENT_EXEC) { | |
8167 | + | |
8168 | + close(ls->sock); | |
8169 | + | |
8170 | + } | |
8171 | + else { /* on PARENT EXEC we want socket fds to be inherited through environment variable */ | |
8172 | + char fd[32]; | |
8173 | + sprintf(fd, "%d", ls->sock); | |
8174 | + env_value = realloc(env_value, p + (p ? 1 : 0) + strlen(ls->key) + 1 + strlen(fd) + 1); | |
8175 | + p += sprintf(env_value + p, "%s%s=%s", p ? "," : "", ls->key, fd); | |
8176 | + } | |
8177 | + | |
8178 | + if (which == FPM_CLEANUP_PARENT_EXIT_MAIN) { | |
8179 | + | |
8180 | + if (ls->type == FPM_AF_UNIX) { | |
8181 | + unlink(ls->key); | |
8182 | + } | |
8183 | + | |
8184 | + } | |
8185 | + | |
8186 | + free(ls->key); | |
8187 | + } | |
8188 | + | |
8189 | + if (env_value) { | |
8190 | + setenv("FPM_SOCKETS", env_value, 1); | |
8191 | + free(env_value); | |
8192 | + } | |
8193 | + | |
8194 | + fpm_array_free(&sockets_list); | |
8195 | +} | |
8196 | + | |
8197 | +static int fpm_sockets_hash_op(int sock, struct sockaddr *sa, char *key, int type, int op) | |
8198 | +{ | |
8199 | + | |
8200 | + if (key == NULL) { | |
8201 | + | |
8202 | + switch (type) { | |
8203 | + | |
8204 | + case FPM_AF_INET : { | |
8205 | + struct sockaddr_in *sa_in = (struct sockaddr_in *) sa; | |
8206 | + | |
8207 | + key = alloca(sizeof("xxx.xxx.xxx.xxx:ppppp")); | |
8208 | + | |
8209 | + sprintf(key, "%u.%u.%u.%u:%u", IPQUAD(&sa_in->sin_addr), (unsigned int) ntohs(sa_in->sin_port)); | |
8210 | + | |
8211 | + break; | |
8212 | + } | |
8213 | + | |
8214 | + case FPM_AF_UNIX : { | |
8215 | + struct sockaddr_un *sa_un = (struct sockaddr_un *) sa; | |
8216 | + | |
8217 | + key = alloca(strlen(sa_un->sun_path) + 1); | |
8218 | + | |
8219 | + strcpy(key, sa_un->sun_path); | |
8220 | + | |
8221 | + break; | |
8222 | + } | |
8223 | + | |
8224 | + default : | |
8225 | + | |
8226 | + return -1; | |
8227 | + } | |
8228 | + | |
8229 | + } | |
8230 | + | |
8231 | + switch (op) { | |
8232 | + | |
8233 | + case FPM_GET_USE_SOCKET : | |
8234 | + { | |
8235 | + | |
8236 | + int i; | |
8237 | + struct listening_socket_s *ls = sockets_list.data; | |
8238 | + | |
8239 | + for (i = 0; i < sockets_list.used; i++, ls++) { | |
8240 | + | |
8241 | + if (!strcmp(ls->key, key)) { | |
8242 | + ++ls->refcount; | |
8243 | + return ls->sock; | |
8244 | + } | |
8245 | + } | |
8246 | + | |
8247 | + break; | |
8248 | + } | |
8249 | + | |
8250 | + case FPM_STORE_SOCKET : /* inherited socket */ | |
8251 | + case FPM_STORE_USE_SOCKET : /* just created */ | |
8252 | + { | |
8253 | + | |
8254 | + struct listening_socket_s *ls; | |
8255 | + | |
8256 | + ls = fpm_array_push(&sockets_list); | |
8257 | + | |
8258 | + if (!ls) { | |
8259 | + break; | |
8260 | + } | |
8261 | + | |
8262 | + if (op == FPM_STORE_SOCKET) { | |
8263 | + ls->refcount = 0; | |
8264 | + } | |
8265 | + else { | |
8266 | + ls->refcount = 1; | |
8267 | + } | |
8268 | + ls->type = type; | |
8269 | + ls->sock = sock; | |
8270 | + ls->key = strdup(key); | |
8271 | + | |
8272 | + return 0; | |
8273 | + | |
8274 | + } | |
8275 | + } | |
8276 | + | |
8277 | + return -1; | |
8278 | + | |
8279 | +} | |
8280 | + | |
8281 | +static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct sockaddr *sa, int socklen) | |
8282 | +{ | |
8283 | + int backlog = -1; | |
8284 | + int flags = 1; | |
8285 | + int sock; | |
8286 | + mode_t saved_umask; | |
8287 | + | |
8288 | + /* we have custom backlog value */ | |
8289 | + if (wp->config->listen_options) { | |
8290 | + backlog = wp->config->listen_options->backlog; | |
8291 | + } | |
8292 | + | |
8293 | + sock = socket(sa->sa_family, SOCK_STREAM, 0); | |
8294 | + | |
8295 | + if (0 > sock) { | |
8296 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "socket() failed"); | |
8297 | + return -1; | |
8298 | + } | |
8299 | + | |
8300 | + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); | |
8301 | + | |
8302 | + if (wp->listen_address_domain == FPM_AF_UNIX) { | |
8303 | + unlink( ((struct sockaddr_un *) sa)->sun_path); | |
8304 | + } | |
8305 | + | |
8306 | + saved_umask = umask(0777 ^ wp->socket_mode); | |
8307 | + | |
8308 | + if (0 > bind(sock, sa, socklen)) { | |
8309 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "bind() for address '%s' failed", wp->config->listen_address); | |
8310 | + return -1; | |
8311 | + } | |
8312 | + | |
8313 | + if (wp->listen_address_domain == FPM_AF_UNIX) { | |
8314 | + | |
8315 | + char *path = ((struct sockaddr_un *) sa)->sun_path; | |
8316 | + | |
8317 | + if (wp->socket_uid != -1 || wp->socket_gid != -1) { | |
8318 | + | |
8319 | + if (0 > chown(path, wp->socket_uid, wp->socket_gid)) { | |
8320 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chown() for address '%s' failed", wp->config->listen_address); | |
8321 | + return -1; | |
8322 | + } | |
8323 | + | |
8324 | + } | |
8325 | + | |
8326 | + } | |
8327 | + | |
8328 | + umask(saved_umask); | |
8329 | + | |
8330 | + if (0 > listen(sock, backlog)) { | |
8331 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "listen() for address '%s' failed", wp->config->listen_address); | |
8332 | + return -1; | |
8333 | + } | |
8334 | + | |
8335 | + return sock; | |
8336 | +} | |
8337 | + | |
8338 | +static int fpm_sockets_get_listening_socket(struct fpm_worker_pool_s *wp, struct sockaddr *sa, int socklen) | |
8339 | +{ | |
8340 | + int sock; | |
8341 | + | |
8342 | + sock = fpm_sockets_hash_op(0, sa, 0, wp->listen_address_domain, FPM_GET_USE_SOCKET); | |
8343 | + | |
8344 | + if (sock >= 0) { return sock; } | |
8345 | + | |
8346 | + sock = fpm_sockets_new_listening_socket(wp, sa, socklen); | |
8347 | + | |
8348 | + fpm_sockets_hash_op(sock, sa, 0, wp->listen_address_domain, FPM_STORE_USE_SOCKET); | |
8349 | + | |
8350 | + return sock; | |
8351 | +} | |
8352 | + | |
8353 | +enum fpm_address_domain fpm_sockets_domain_from_address(char *address) | |
8354 | +{ | |
8355 | + if (strchr(address, ':')) { return FPM_AF_INET; } | |
8356 | + | |
8357 | + if (strlen(address) == strspn(address, "0123456789")) { return FPM_AF_INET; } | |
8358 | + | |
8359 | + return FPM_AF_UNIX; | |
8360 | +} | |
8361 | + | |
8362 | +static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) | |
8363 | +{ | |
8364 | + struct sockaddr_in sa_in; | |
8365 | + char *dup_address = strdup(wp->config->listen_address); | |
8366 | + char *port_str = strchr(dup_address, ':'); | |
8367 | + char *addr = NULL; | |
8368 | + int port = 0; | |
8369 | + | |
8370 | + if (port_str) { /* this is host:port pair */ | |
8371 | + *port_str++ = '\0'; | |
8372 | + port = atoi(port_str); | |
8373 | + addr = dup_address; | |
8374 | + } | |
8375 | + else if (strlen(dup_address) == strspn(dup_address, "0123456789")) { /* this is port */ | |
8376 | + port = atoi(dup_address); | |
8377 | + port_str = dup_address; | |
8378 | + } | |
8379 | + | |
8380 | + if (port == 0) { | |
8381 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "invalid port value '%s'", port_str); | |
8382 | + return -1; | |
8383 | + } | |
8384 | + | |
8385 | + memset(&sa_in, 0, sizeof(sa_in)); | |
8386 | + | |
8387 | + if (addr) { | |
8388 | + | |
8389 | + sa_in.sin_addr.s_addr = inet_addr(addr); | |
8390 | + | |
8391 | + if (sa_in.sin_addr.s_addr == INADDR_NONE) { /* do resolve */ | |
8392 | + if (0 > fpm_sockets_resolve_af_inet(addr, NULL, &sa_in)) { | |
8393 | + return -1; | |
8394 | + } | |
8395 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "address '%s' resolved as %u.%u.%u.%u", addr, IPQUAD(&sa_in.sin_addr)); | |
8396 | + } | |
8397 | + } | |
8398 | + else { | |
8399 | + | |
8400 | + sa_in.sin_addr.s_addr = htonl(INADDR_ANY); | |
8401 | + | |
8402 | + } | |
8403 | + | |
8404 | + sa_in.sin_family = AF_INET; | |
8405 | + sa_in.sin_port = htons(port); | |
8406 | + | |
8407 | + free(dup_address); | |
8408 | + | |
8409 | + return fpm_sockets_get_listening_socket(wp, (struct sockaddr *) &sa_in, sizeof(struct sockaddr_in)); | |
8410 | +} | |
8411 | + | |
8412 | +static int fpm_socket_af_unix_listening_socket(struct fpm_worker_pool_s *wp) | |
8413 | +{ | |
8414 | + struct sockaddr_un sa_un; | |
8415 | + | |
8416 | + memset(&sa_un, 0, sizeof(sa_un)); | |
8417 | + | |
8418 | + cpystrn(sa_un.sun_path, wp->config->listen_address, sizeof(sa_un.sun_path)); | |
8419 | + sa_un.sun_family = AF_UNIX; | |
8420 | + | |
8421 | + return fpm_sockets_get_listening_socket(wp, (struct sockaddr *) &sa_un, sizeof(struct sockaddr_un)); | |
8422 | +} | |
8423 | + | |
8424 | +int fpm_sockets_init_main() | |
8425 | +{ | |
8426 | + int i; | |
8427 | + struct fpm_worker_pool_s *wp; | |
8428 | + char *inherited = getenv("FPM_SOCKETS"); | |
8429 | + struct listening_socket_s *ls; | |
8430 | + | |
8431 | + if (0 == fpm_array_init(&sockets_list, sizeof(struct listening_socket_s), 10)) { | |
8432 | + return -1; | |
8433 | + } | |
8434 | + | |
8435 | + /* import inherited sockets */ | |
8436 | + while (inherited && *inherited) { | |
8437 | + char *comma = strchr(inherited, ','); | |
8438 | + int type, fd_no; | |
8439 | + char *eq; | |
8440 | + | |
8441 | + if (comma) { *comma = '\0'; } | |
8442 | + | |
8443 | + eq = strchr(inherited, '='); | |
8444 | + | |
8445 | + if (eq) { | |
8446 | + *eq = '\0'; | |
8447 | + | |
8448 | + fd_no = atoi(eq + 1); | |
8449 | + | |
8450 | + type = fpm_sockets_domain_from_address(inherited); | |
8451 | + | |
8452 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "using inherited socket fd=%d, \"%s\"", fd_no, inherited); | |
8453 | + | |
8454 | + fpm_sockets_hash_op(fd_no, 0, inherited, type, FPM_STORE_SOCKET); | |
8455 | + } | |
8456 | + | |
8457 | + if (comma) { inherited = comma + 1; } | |
8458 | + else { inherited = 0; } | |
8459 | + } | |
8460 | + | |
8461 | + /* create all required sockets */ | |
8462 | + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { | |
8463 | + | |
8464 | + if (!wp->is_template) { | |
8465 | + | |
8466 | + switch (wp->listen_address_domain) { | |
8467 | + | |
8468 | + case FPM_AF_INET : | |
8469 | + | |
8470 | + wp->listening_socket = fpm_socket_af_inet_listening_socket(wp); | |
8471 | + break; | |
8472 | + | |
8473 | + case FPM_AF_UNIX : | |
8474 | + | |
8475 | + if (0 > fpm_unix_resolve_socket_premissions(wp)) { | |
8476 | + return -1; | |
8477 | + } | |
8478 | + | |
8479 | + wp->listening_socket = fpm_socket_af_unix_listening_socket(wp); | |
8480 | + break; | |
8481 | + | |
8482 | + } | |
8483 | + | |
8484 | + if (wp->listening_socket == -1) { | |
8485 | + return -1; | |
8486 | + } | |
8487 | + } | |
8488 | + | |
8489 | + } | |
8490 | + | |
8491 | + /* close unused sockets that was inherited */ | |
8492 | + ls = sockets_list.data; | |
8493 | + | |
8494 | + for (i = 0; i < sockets_list.used; ) { | |
8495 | + | |
8496 | + if (ls->refcount == 0) { | |
8497 | + close(ls->sock); | |
8498 | + if (ls->type == FPM_AF_UNIX) { | |
8499 | + unlink(ls->key); | |
8500 | + } | |
8501 | + free(ls->key); | |
8502 | + fpm_array_item_remove(&sockets_list, i); | |
8503 | + } | |
8504 | + else { | |
8505 | + ++i; | |
8506 | + ++ls; | |
8507 | + } | |
8508 | + } | |
8509 | + | |
8510 | + if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_sockets_cleanup, 0)) { | |
8511 | + return -1; | |
8512 | + } | |
8513 | + | |
8514 | + return 0; | |
8515 | +} | |
8516 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_sockets.h php-src/sapi/fpm/fpm/fpm_sockets.h | |
8517 | --- php-src-vanilla/sapi/fpm/fpm/fpm_sockets.h 1970-01-01 01:00:00.000000000 +0100 | |
8518 | +++ php-src/sapi/fpm/fpm/fpm_sockets.h 2009-10-18 21:05:39.310440424 +0100 | |
8519 | @@ -0,0 +1,37 @@ | |
8520 | + | |
8521 | + /* $Id$ */ | |
8522 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
8523 | + | |
8524 | +#ifndef FPM_MISC_H | |
8525 | +#define FPM_MISC_H 1 | |
8526 | + | |
8527 | +#include <unistd.h> | |
8528 | +#include <fcntl.h> | |
8529 | + | |
8530 | +#include "fpm_worker_pool.h" | |
8531 | + | |
8532 | +enum fpm_address_domain fpm_sockets_domain_from_address(char *addr); | |
8533 | +int fpm_sockets_init_main(); | |
8534 | + | |
8535 | + | |
8536 | +static inline int fd_set_blocked(int fd, int blocked) | |
8537 | +{ | |
8538 | + int flags = fcntl(fd, F_GETFL); | |
8539 | + | |
8540 | + if (flags < 0) { return -1; } | |
8541 | + | |
8542 | + if (blocked) | |
8543 | + { flags &= ~O_NONBLOCK; } | |
8544 | + else | |
8545 | + { flags |= O_NONBLOCK; } | |
8546 | + | |
8547 | + return fcntl(fd, F_SETFL, flags); | |
8548 | +} | |
8549 | + | |
8550 | +#define IPQUAD(sin_addr) \ | |
8551 | + (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[0], \ | |
8552 | + (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[1], \ | |
8553 | + (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[2], \ | |
8554 | + (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[3] | |
8555 | + | |
8556 | +#endif | |
8557 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_stdio.c php-src/sapi/fpm/fpm/fpm_stdio.c | |
8558 | --- php-src-vanilla/sapi/fpm/fpm/fpm_stdio.c 1970-01-01 01:00:00.000000000 +0100 | |
8559 | +++ php-src/sapi/fpm/fpm/fpm_stdio.c 2009-10-18 21:05:39.310440424 +0100 | |
8560 | @@ -0,0 +1,286 @@ | |
8561 | + | |
8562 | + /* $Id$ */ | |
8563 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
8564 | + | |
8565 | +#include "fpm_config.h" | |
8566 | + | |
8567 | +#include <sys/types.h> | |
8568 | +#include <sys/stat.h> | |
8569 | +#include <string.h> | |
8570 | +#include <fcntl.h> | |
8571 | +#include <unistd.h> | |
8572 | +#include <errno.h> | |
8573 | + | |
8574 | +#include "fpm.h" | |
8575 | +#include "fpm_children.h" | |
8576 | +#include "fpm_events.h" | |
8577 | +#include "fpm_sockets.h" | |
8578 | +#include "fpm_stdio.h" | |
8579 | +#include "zlog.h" | |
8580 | + | |
8581 | +static int fd_stdout[2]; | |
8582 | +static int fd_stderr[2]; | |
8583 | + | |
8584 | +int fpm_stdio_init_main() | |
8585 | +{ | |
8586 | + int fd = open("/dev/null", O_RDWR); | |
8587 | + | |
8588 | + if (0 > fd) { | |
8589 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(\"/dev/null\") failed"); | |
8590 | + return -1; | |
8591 | + } | |
8592 | + | |
8593 | + if (0 > dup2(fd, STDIN_FILENO) || 0 > dup2(fd, STDOUT_FILENO)) { | |
8594 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "dup2() failed"); | |
8595 | + return -1; | |
8596 | + } | |
8597 | + | |
8598 | + close(fd); | |
8599 | + | |
8600 | + return 0; | |
8601 | +} | |
8602 | + | |
8603 | +int fpm_stdio_init_final() | |
8604 | +{ | |
8605 | + if (fpm_global_config.daemonize) { | |
8606 | + | |
8607 | + if (fpm_globals.error_log_fd != STDERR_FILENO) { | |
8608 | + /* there might be messages to stderr from libevent, we need to log them all */ | |
8609 | + if (0 > dup2(fpm_globals.error_log_fd, STDERR_FILENO)) { | |
8610 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "dup2() failed"); | |
8611 | + return -1; | |
8612 | + } | |
8613 | + } | |
8614 | + | |
8615 | + zlog_set_level(fpm_globals.log_level); | |
8616 | + | |
8617 | + zlog_set_fd(fpm_globals.error_log_fd); | |
8618 | + } | |
8619 | + | |
8620 | + return 0; | |
8621 | +} | |
8622 | + | |
8623 | +int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) | |
8624 | +{ | |
8625 | + close(fpm_globals.error_log_fd); | |
8626 | + fpm_globals.error_log_fd = -1; | |
8627 | + zlog_set_fd(-1); | |
8628 | + | |
8629 | + if (wp->listening_socket != STDIN_FILENO) { | |
8630 | + if (0 > dup2(wp->listening_socket, STDIN_FILENO)) { | |
8631 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "dup2() failed"); | |
8632 | + return -1; | |
8633 | + } | |
8634 | + } | |
8635 | + | |
8636 | + return 0; | |
8637 | +} | |
8638 | + | |
8639 | +static void fpm_stdio_child_said(int fd, short which, void *arg) | |
8640 | +{ | |
8641 | + static const int max_buf_size = 1024; | |
8642 | + char buf[max_buf_size]; | |
8643 | + struct fpm_child_s *child = arg; | |
8644 | + int is_stdout = fd == child->fd_stdout; | |
8645 | + struct event *ev = is_stdout ? &child->ev_stdout : &child->ev_stderr; | |
8646 | + int fifo_in = 1, fifo_out = 1; | |
8647 | + int is_last_message = 0; | |
8648 | + int in_buf = 0; | |
8649 | + int res; | |
8650 | + | |
8651 | +#if 0 | |
8652 | + zlog(ZLOG_STUFF, ZLOG_DEBUG, "child %d said %s", (int) child->pid, is_stdout ? "stdout" : "stderr"); | |
8653 | +#endif | |
8654 | + | |
8655 | + while (fifo_in || fifo_out) { | |
8656 | + | |
8657 | + if (fifo_in) { | |
8658 | + | |
8659 | + res = read(fd, buf + in_buf, max_buf_size - 1 - in_buf); | |
8660 | + | |
8661 | + if (res <= 0) { /* no data */ | |
8662 | + fifo_in = 0; | |
8663 | + | |
8664 | + if (res < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) { | |
8665 | + /* just no more data ready */ | |
8666 | + } | |
8667 | + else { /* error or pipe is closed */ | |
8668 | + | |
8669 | + if (res < 0) { /* error */ | |
8670 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed"); | |
8671 | + } | |
8672 | + | |
8673 | + fpm_event_del(ev); | |
8674 | + is_last_message = 1; | |
8675 | + | |
8676 | + if (is_stdout) { | |
8677 | + close(child->fd_stdout); | |
8678 | + child->fd_stdout = -1; | |
8679 | + } | |
8680 | + else { | |
8681 | + close(child->fd_stderr); | |
8682 | + child->fd_stderr = -1; | |
8683 | + } | |
8684 | + | |
8685 | +#if 0 | |
8686 | + if (in_buf == 0 && !fpm_globals.is_child) { | |
8687 | + zlog(ZLOG_STUFF, ZLOG_DEBUG, "child %d (pool %s) %s pipe is closed", (int) child->pid, | |
8688 | + child->wp->config->name, is_stdout ? "stdout" : "stderr"); | |
8689 | + } | |
8690 | +#endif | |
8691 | + } | |
8692 | + } | |
8693 | + else { | |
8694 | + in_buf += res; | |
8695 | + } | |
8696 | + } | |
8697 | + | |
8698 | + if (fifo_out) { | |
8699 | + if (in_buf == 0) { | |
8700 | + fifo_out = 0; | |
8701 | + } | |
8702 | + else { | |
8703 | + char *nl; | |
8704 | + int should_print = 0; | |
8705 | + buf[in_buf] = '\0'; | |
8706 | + | |
8707 | + /* FIXME: there might be binary data */ | |
8708 | + | |
8709 | + /* we should print if no more space in the buffer */ | |
8710 | + if (in_buf == max_buf_size - 1) { | |
8711 | + should_print = 1; | |
8712 | + } | |
8713 | + | |
8714 | + /* we should print if no more data to come */ | |
8715 | + if (!fifo_in) { | |
8716 | + should_print = 1; | |
8717 | + } | |
8718 | + | |
8719 | + nl = strchr(buf, '\n'); | |
8720 | + | |
8721 | + if (nl || should_print) { | |
8722 | + | |
8723 | + if (nl) { | |
8724 | + *nl = '\0'; | |
8725 | + } | |
8726 | + | |
8727 | + zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d (pool %s) said into %s: \"%s\"%s", (int) child->pid, | |
8728 | + child->wp->config->name, is_stdout ? "stdout" : "stderr", buf, is_last_message ? ", pipe is closed" : ""); | |
8729 | + | |
8730 | + if (nl) { | |
8731 | + int out_buf = 1 + nl - buf; | |
8732 | + memmove(buf, buf + out_buf, in_buf - out_buf); | |
8733 | + in_buf -= out_buf; | |
8734 | + } | |
8735 | + else { | |
8736 | + in_buf = 0; | |
8737 | + } | |
8738 | + } | |
8739 | + } | |
8740 | + } | |
8741 | + } | |
8742 | + | |
8743 | +} | |
8744 | + | |
8745 | +int fpm_stdio_prepare_pipes(struct fpm_child_s *child) | |
8746 | +{ | |
8747 | + if (0 == child->wp->config->catch_workers_output) { /* not required */ | |
8748 | + return 0; | |
8749 | + } | |
8750 | + | |
8751 | + if (0 > pipe(fd_stdout)) { | |
8752 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pipe() failed"); | |
8753 | + return -1; | |
8754 | + } | |
8755 | + | |
8756 | + if (0 > pipe(fd_stderr)) { | |
8757 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pipe() failed"); | |
8758 | + close(fd_stdout[0]); close(fd_stdout[1]); | |
8759 | + return -1; | |
8760 | + } | |
8761 | + | |
8762 | + if (0 > fd_set_blocked(fd_stdout[0], 0) || 0 > fd_set_blocked(fd_stderr[0], 0)) { | |
8763 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fd_set_blocked() failed"); | |
8764 | + close(fd_stdout[0]); close(fd_stdout[1]); | |
8765 | + close(fd_stderr[0]); close(fd_stderr[1]); | |
8766 | + return -1; | |
8767 | + } | |
8768 | + | |
8769 | + return 0; | |
8770 | +} | |
8771 | + | |
8772 | +int fpm_stdio_parent_use_pipes(struct fpm_child_s *child) | |
8773 | +{ | |
8774 | + if (0 == child->wp->config->catch_workers_output) { /* not required */ | |
8775 | + return 0; | |
8776 | + } | |
8777 | + | |
8778 | + close(fd_stdout[1]); | |
8779 | + close(fd_stderr[1]); | |
8780 | + | |
8781 | + child->fd_stdout = fd_stdout[0]; | |
8782 | + child->fd_stderr = fd_stderr[0]; | |
8783 | + | |
8784 | + fpm_event_add(child->fd_stdout, &child->ev_stdout, fpm_stdio_child_said, child); | |
8785 | + fpm_event_add(child->fd_stderr, &child->ev_stderr, fpm_stdio_child_said, child); | |
8786 | + | |
8787 | + return 0; | |
8788 | +} | |
8789 | + | |
8790 | +int fpm_stdio_discard_pipes(struct fpm_child_s *child) | |
8791 | +{ | |
8792 | + if (0 == child->wp->config->catch_workers_output) { /* not required */ | |
8793 | + return 0; | |
8794 | + } | |
8795 | + | |
8796 | + close(fd_stdout[1]); | |
8797 | + close(fd_stderr[1]); | |
8798 | + | |
8799 | + close(fd_stdout[0]); | |
8800 | + close(fd_stderr[0]); | |
8801 | + | |
8802 | + return 0; | |
8803 | +} | |
8804 | + | |
8805 | +void fpm_stdio_child_use_pipes(struct fpm_child_s *child) | |
8806 | +{ | |
8807 | + if (child->wp->config->catch_workers_output) { | |
8808 | + dup2(fd_stdout[1], STDOUT_FILENO); | |
8809 | + dup2(fd_stderr[1], STDERR_FILENO); | |
8810 | + close(fd_stdout[0]); close(fd_stdout[1]); | |
8811 | + close(fd_stderr[0]); close(fd_stderr[1]); | |
8812 | + } | |
8813 | + else { | |
8814 | + /* stdout of parent is always /dev/null */ | |
8815 | + dup2(STDOUT_FILENO, STDERR_FILENO); | |
8816 | + } | |
8817 | +} | |
8818 | + | |
8819 | +int fpm_stdio_open_error_log(int reopen) | |
8820 | +{ | |
8821 | + int fd; | |
8822 | + | |
8823 | + fd = open(fpm_global_config.error_log, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR); | |
8824 | + | |
8825 | + if (0 > fd) { | |
8826 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(\"%s\") failed", fpm_global_config.error_log); | |
8827 | + return -1; | |
8828 | + } | |
8829 | + | |
8830 | + if (reopen) { | |
8831 | + if (fpm_global_config.daemonize) { | |
8832 | + dup2(fd, STDERR_FILENO); | |
8833 | + } | |
8834 | + | |
8835 | + dup2(fd, fpm_globals.error_log_fd); | |
8836 | + close(fd); | |
8837 | + fd = fpm_globals.error_log_fd; /* for FD_CLOSEXEC to work */ | |
8838 | + } | |
8839 | + else { | |
8840 | + fpm_globals.error_log_fd = fd; | |
8841 | + } | |
8842 | + | |
8843 | + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); | |
8844 | + | |
8845 | + return 0; | |
8846 | +} | |
8847 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_stdio.h php-src/sapi/fpm/fpm/fpm_stdio.h | |
8848 | --- php-src-vanilla/sapi/fpm/fpm/fpm_stdio.h 1970-01-01 01:00:00.000000000 +0100 | |
8849 | +++ php-src/sapi/fpm/fpm/fpm_stdio.h 2009-10-18 21:05:39.310440424 +0100 | |
8850 | @@ -0,0 +1,20 @@ | |
8851 | + | |
8852 | + /* $Id$ */ | |
8853 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
8854 | + | |
8855 | +#ifndef FPM_STDIO_H | |
8856 | +#define FPM_STDIO_H 1 | |
8857 | + | |
8858 | +#include "fpm_worker_pool.h" | |
8859 | + | |
8860 | +int fpm_stdio_init_main(); | |
8861 | +int fpm_stdio_init_final(); | |
8862 | +int fpm_stdio_init_child(struct fpm_worker_pool_s *wp); | |
8863 | +int fpm_stdio_prepare_pipes(struct fpm_child_s *child); | |
8864 | +void fpm_stdio_child_use_pipes(struct fpm_child_s *child); | |
8865 | +int fpm_stdio_parent_use_pipes(struct fpm_child_s *child); | |
8866 | +int fpm_stdio_discard_pipes(struct fpm_child_s *child); | |
8867 | +int fpm_stdio_open_error_log(int reopen); | |
8868 | + | |
8869 | +#endif | |
8870 | + | |
8871 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_str.h php-src/sapi/fpm/fpm/fpm_str.h | |
8872 | --- php-src-vanilla/sapi/fpm/fpm/fpm_str.h 1970-01-01 01:00:00.000000000 +0100 | |
8873 | +++ php-src/sapi/fpm/fpm/fpm_str.h 2009-10-18 21:05:39.308376784 +0100 | |
8874 | @@ -0,0 +1,49 @@ | |
8875 | + | |
8876 | + /* $Id$ */ | |
8877 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
8878 | + | |
8879 | +#ifndef FPM_STR_H | |
8880 | +#define FPM_STR_H 1 | |
8881 | + | |
8882 | +static inline char *cpystrn(char *dst, const char *src, size_t dst_size) | |
8883 | +{ | |
8884 | + char *d, *end; | |
8885 | + | |
8886 | + if (!dst_size) { return dst; } | |
8887 | + | |
8888 | + d = dst; | |
8889 | + end = dst + dst_size - 1; | |
8890 | + | |
8891 | + for (; d < end; ++d, ++src) { | |
8892 | + if (!(*d = *src)) { | |
8893 | + return d; | |
8894 | + } | |
8895 | + } | |
8896 | + | |
8897 | + *d = '\0'; | |
8898 | + | |
8899 | + return d; | |
8900 | +} | |
8901 | + | |
8902 | +static inline char *str_purify_filename(char *dst, char *src, size_t size) | |
8903 | +{ | |
8904 | + char *d, *end; | |
8905 | + | |
8906 | + d = dst; | |
8907 | + end = dst + size - 1; | |
8908 | + | |
8909 | + for (; d < end && *src; ++d, ++src) { | |
8910 | + if (* (unsigned char *) src < ' ' || * (unsigned char *) src > '\x7f') { | |
8911 | + *d = '.'; | |
8912 | + } | |
8913 | + else { | |
8914 | + *d = *src; | |
8915 | + } | |
8916 | + } | |
8917 | + | |
8918 | + *d = '\0'; | |
8919 | + | |
8920 | + return d; | |
8921 | +} | |
8922 | + | |
8923 | +#endif | |
8924 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_trace.c php-src/sapi/fpm/fpm/fpm_trace.c | |
8925 | --- php-src-vanilla/sapi/fpm/fpm/fpm_trace.c 1970-01-01 01:00:00.000000000 +0100 | |
8926 | +++ php-src/sapi/fpm/fpm/fpm_trace.c 2009-10-18 21:05:39.310440424 +0100 | |
8927 | @@ -0,0 +1,46 @@ | |
8928 | + | |
8929 | + /* $Id$ */ | |
8930 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
8931 | + | |
8932 | +#include "fpm_config.h" | |
8933 | + | |
8934 | +#include <sys/types.h> | |
8935 | + | |
8936 | +#include "fpm_trace.h" | |
8937 | + | |
8938 | +int fpm_trace_get_strz(char *buf, size_t sz, long addr) | |
8939 | +{ | |
8940 | + int i; | |
8941 | + long l; | |
8942 | + char *lc = (char *) &l; | |
8943 | + | |
8944 | + if (0 > fpm_trace_get_long(addr, &l)) { | |
8945 | + return -1; | |
8946 | + } | |
8947 | + | |
8948 | + i = l % SIZEOF_LONG; | |
8949 | + | |
8950 | + l -= i; | |
8951 | + | |
8952 | + for (addr = l; ; addr += SIZEOF_LONG) { | |
8953 | + | |
8954 | + if (0 > fpm_trace_get_long(addr, &l)) { | |
8955 | + return -1; | |
8956 | + } | |
8957 | + | |
8958 | + for ( ; i < SIZEOF_LONG; i++) { | |
8959 | + --sz; | |
8960 | + | |
8961 | + if (sz && lc[i]) { | |
8962 | + *buf++ = lc[i]; | |
8963 | + continue; | |
8964 | + } | |
8965 | + | |
8966 | + *buf = '\0'; | |
8967 | + return 0; | |
8968 | + } | |
8969 | + | |
8970 | + i = 0; | |
8971 | + } | |
8972 | +} | |
8973 | + | |
8974 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_trace.h php-src/sapi/fpm/fpm/fpm_trace.h | |
8975 | --- php-src-vanilla/sapi/fpm/fpm/fpm_trace.h 1970-01-01 01:00:00.000000000 +0100 | |
8976 | +++ php-src/sapi/fpm/fpm/fpm_trace.h 2009-10-18 21:05:39.302497288 +0100 | |
8977 | @@ -0,0 +1,17 @@ | |
8978 | + | |
8979 | + /* $Id$ */ | |
8980 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
8981 | + | |
8982 | +#ifndef FPM_TRACE_H | |
8983 | +#define FPM_TRACE_H 1 | |
8984 | + | |
8985 | +#include <unistd.h> | |
8986 | + | |
8987 | +int fpm_trace_signal(pid_t pid); | |
8988 | +int fpm_trace_ready(pid_t pid); | |
8989 | +int fpm_trace_close(pid_t pid); | |
8990 | +int fpm_trace_get_long(long addr, long *data); | |
8991 | +int fpm_trace_get_strz(char *buf, size_t sz, long addr); | |
8992 | + | |
8993 | +#endif | |
8994 | + | |
8995 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_trace_mach.c php-src/sapi/fpm/fpm/fpm_trace_mach.c | |
8996 | --- php-src-vanilla/sapi/fpm/fpm/fpm_trace_mach.c 1970-01-01 01:00:00.000000000 +0100 | |
8997 | +++ php-src/sapi/fpm/fpm/fpm_trace_mach.c 2009-10-18 21:05:39.308376784 +0100 | |
8998 | @@ -0,0 +1,102 @@ | |
8999 | + | |
9000 | + /* $Id$ */ | |
9001 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
9002 | + | |
9003 | +#include "fpm_config.h" | |
9004 | + | |
9005 | +#include <mach/mach.h> | |
9006 | +#include <mach/mach_vm.h> | |
9007 | + | |
9008 | +#include <unistd.h> | |
9009 | + | |
9010 | +#include "fpm_trace.h" | |
9011 | +#include "fpm_process_ctl.h" | |
9012 | +#include "fpm_unix.h" | |
9013 | +#include "zlog.h" | |
9014 | + | |
9015 | + | |
9016 | +static mach_port_name_t target; | |
9017 | +static vm_offset_t target_page_base; | |
9018 | +static vm_offset_t local_page; | |
9019 | +static mach_msg_type_number_t local_size; | |
9020 | + | |
9021 | +static void fpm_mach_vm_deallocate() | |
9022 | +{ | |
9023 | + if (local_page) { | |
9024 | + mach_vm_deallocate(mach_task_self(), local_page, local_size); | |
9025 | + target_page_base = 0; | |
9026 | + local_page = 0; | |
9027 | + local_size = 0; | |
9028 | + } | |
9029 | +} | |
9030 | + | |
9031 | +static int fpm_mach_vm_read_page(vm_offset_t page) | |
9032 | +{ | |
9033 | + kern_return_t kr; | |
9034 | + | |
9035 | + kr = mach_vm_read(target, page, fpm_pagesize, &local_page, &local_size); | |
9036 | + | |
9037 | + if (kr != KERN_SUCCESS) { | |
9038 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "mach_vm_read() failed: %s (%d)", mach_error_string(kr), kr); | |
9039 | + return -1; | |
9040 | + } | |
9041 | + | |
9042 | + return 0; | |
9043 | +} | |
9044 | + | |
9045 | +int fpm_trace_signal(pid_t pid) | |
9046 | +{ | |
9047 | + if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) { | |
9048 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "kill(SIGSTOP) failed"); | |
9049 | + return -1; | |
9050 | + } | |
9051 | + | |
9052 | + return 0; | |
9053 | +} | |
9054 | + | |
9055 | +int fpm_trace_ready(pid_t pid) | |
9056 | +{ | |
9057 | + kern_return_t kr; | |
9058 | + | |
9059 | + kr = task_for_pid(mach_task_self(), pid, &target); | |
9060 | + | |
9061 | + if (kr != KERN_SUCCESS) { | |
9062 | + char *msg = ""; | |
9063 | + | |
9064 | + if (kr == KERN_FAILURE) { | |
9065 | + msg = " It seems that master process does not have enough privileges to trace processes."; | |
9066 | + } | |
9067 | + | |
9068 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "task_for_pid() failed: %s (%d)%s", mach_error_string(kr), kr, msg); | |
9069 | + return -1; | |
9070 | + } | |
9071 | + | |
9072 | + return 0; | |
9073 | +} | |
9074 | + | |
9075 | +int fpm_trace_close(pid_t pid) | |
9076 | +{ | |
9077 | + fpm_mach_vm_deallocate(); | |
9078 | + | |
9079 | + target = 0; | |
9080 | + | |
9081 | + return 0; | |
9082 | +} | |
9083 | + | |
9084 | +int fpm_trace_get_long(long addr, long *data) | |
9085 | +{ | |
9086 | + size_t offset = ((uintptr_t) (addr) % fpm_pagesize); | |
9087 | + vm_offset_t base = (uintptr_t) (addr) - offset; | |
9088 | + | |
9089 | + if (base != target_page_base) { | |
9090 | + fpm_mach_vm_deallocate(); | |
9091 | + if (0 > fpm_mach_vm_read_page(base)) { | |
9092 | + return -1; | |
9093 | + } | |
9094 | + } | |
9095 | + | |
9096 | + *data = * (long *) (local_page + offset); | |
9097 | + | |
9098 | + return 0; | |
9099 | +} | |
9100 | + | |
9101 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_trace_pread.c php-src/sapi/fpm/fpm/fpm_trace_pread.c | |
9102 | --- php-src-vanilla/sapi/fpm/fpm/fpm_trace_pread.c 1970-01-01 01:00:00.000000000 +0100 | |
9103 | +++ php-src/sapi/fpm/fpm/fpm_trace_pread.c 2009-10-18 21:05:39.310440424 +0100 | |
9104 | @@ -0,0 +1,72 @@ | |
9105 | + | |
9106 | + /* $Id$ */ | |
9107 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
9108 | + | |
9109 | +#define _GNU_SOURCE | |
9110 | +#define _FILE_OFFSET_BITS 64 | |
9111 | + | |
9112 | +#include "fpm_config.h" | |
9113 | + | |
9114 | +#include <unistd.h> | |
9115 | + | |
9116 | +#include <fcntl.h> | |
9117 | +#include <stdio.h> | |
9118 | +#if HAVE_INTTYPES_H | |
9119 | +#include <inttypes.h> | |
9120 | +#else | |
9121 | +#include <stdint.h> | |
9122 | +#endif | |
9123 | + | |
9124 | + | |
9125 | +#include "fpm_trace.h" | |
9126 | +#include "fpm_process_ctl.h" | |
9127 | +#include "zlog.h" | |
9128 | + | |
9129 | + | |
9130 | +static int mem_file = -1; | |
9131 | + | |
9132 | +int fpm_trace_signal(pid_t pid) | |
9133 | +{ | |
9134 | + if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) { | |
9135 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "kill(SIGSTOP) failed"); | |
9136 | + return -1; | |
9137 | + } | |
9138 | + | |
9139 | + return 0; | |
9140 | +} | |
9141 | + | |
9142 | +int fpm_trace_ready(pid_t pid) | |
9143 | +{ | |
9144 | + char buf[128]; | |
9145 | + | |
9146 | + sprintf(buf, "/proc/%d/" PROC_MEM_FILE, (int) pid); | |
9147 | + | |
9148 | + mem_file = open(buf, O_RDONLY); | |
9149 | + | |
9150 | + if (0 > mem_file) { | |
9151 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(%s) failed", buf); | |
9152 | + return -1; | |
9153 | + } | |
9154 | + | |
9155 | + return 0; | |
9156 | +} | |
9157 | + | |
9158 | +int fpm_trace_close(pid_t pid) | |
9159 | +{ | |
9160 | + close(mem_file); | |
9161 | + | |
9162 | + mem_file = -1; | |
9163 | + | |
9164 | + return 0; | |
9165 | +} | |
9166 | + | |
9167 | +int fpm_trace_get_long(long addr, long *data) | |
9168 | +{ | |
9169 | + if (sizeof(*data) != pread(mem_file, (void *) data, sizeof(*data), (uintptr_t) addr)) { | |
9170 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pread() failed"); | |
9171 | + return -1; | |
9172 | + } | |
9173 | + | |
9174 | + return 0; | |
9175 | +} | |
9176 | + | |
9177 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_trace_ptrace.c php-src/sapi/fpm/fpm/fpm_trace_ptrace.c | |
9178 | --- php-src-vanilla/sapi/fpm/fpm/fpm_trace_ptrace.c 1970-01-01 01:00:00.000000000 +0100 | |
9179 | +++ php-src/sapi/fpm/fpm/fpm_trace_ptrace.c 2009-10-18 21:05:39.302497288 +0100 | |
9180 | @@ -0,0 +1,85 @@ | |
9181 | + | |
9182 | + /* $Id$ */ | |
9183 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
9184 | + | |
9185 | +#include "fpm_config.h" | |
9186 | + | |
9187 | +#include <sys/wait.h> | |
9188 | +#include <sys/ptrace.h> | |
9189 | +#include <unistd.h> | |
9190 | +#include <errno.h> | |
9191 | + | |
9192 | +#if defined(PT_ATTACH) && !defined(PTRACE_ATTACH) | |
9193 | +#define PTRACE_ATTACH PT_ATTACH | |
9194 | +#endif | |
9195 | + | |
9196 | +#if defined(PT_DETACH) && !defined(PTRACE_DETACH) | |
9197 | +#define PTRACE_DETACH PT_DETACH | |
9198 | +#endif | |
9199 | + | |
9200 | +#if defined(PT_READ_D) && !defined(PTRACE_PEEKDATA) | |
9201 | +#define PTRACE_PEEKDATA PT_READ_D | |
9202 | +#endif | |
9203 | + | |
9204 | +#include "fpm_trace.h" | |
9205 | +#include "zlog.h" | |
9206 | + | |
9207 | +static pid_t traced_pid; | |
9208 | + | |
9209 | +int fpm_trace_signal(pid_t pid) | |
9210 | +{ | |
9211 | + if (0 > ptrace(PTRACE_ATTACH, pid, 0, 0)) { | |
9212 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(ATTACH) failed"); | |
9213 | + return -1; | |
9214 | + } | |
9215 | + | |
9216 | + return 0; | |
9217 | +} | |
9218 | + | |
9219 | +int fpm_trace_ready(pid_t pid) | |
9220 | +{ | |
9221 | + traced_pid = pid; | |
9222 | + | |
9223 | + return 0; | |
9224 | +} | |
9225 | + | |
9226 | +int fpm_trace_close(pid_t pid) | |
9227 | +{ | |
9228 | + if (0 > ptrace(PTRACE_DETACH, pid, (void *) 1, 0)) { | |
9229 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(DETACH) failed"); | |
9230 | + return -1; | |
9231 | + } | |
9232 | + | |
9233 | + traced_pid = 0; | |
9234 | + | |
9235 | + return 0; | |
9236 | +} | |
9237 | + | |
9238 | +int fpm_trace_get_long(long addr, long *data) | |
9239 | +{ | |
9240 | +#ifdef PT_IO | |
9241 | + struct ptrace_io_desc ptio = { | |
9242 | + .piod_op = PIOD_READ_D, | |
9243 | + .piod_offs = (void *) addr, | |
9244 | + .piod_addr = (void *) data, | |
9245 | + .piod_len = sizeof(long) | |
9246 | + }; | |
9247 | + | |
9248 | + if (0 > ptrace(PT_IO, traced_pid, (void *) &ptio, 0)) { | |
9249 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(PT_IO) failed"); | |
9250 | + return -1; | |
9251 | + } | |
9252 | +#else | |
9253 | + errno = 0; | |
9254 | + | |
9255 | + *data = ptrace(PTRACE_PEEKDATA, traced_pid, (void *) addr, 0); | |
9256 | + | |
9257 | + if (errno) { | |
9258 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(PEEKDATA) failed"); | |
9259 | + return -1; | |
9260 | + } | |
9261 | +#endif | |
9262 | + | |
9263 | + return 0; | |
9264 | +} | |
9265 | + | |
9266 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_unix.c php-src/sapi/fpm/fpm/fpm_unix.c | |
9267 | --- php-src-vanilla/sapi/fpm/fpm/fpm_unix.c 1970-01-01 01:00:00.000000000 +0100 | |
9268 | +++ php-src/sapi/fpm/fpm/fpm_unix.c 2009-10-18 21:05:39.310440424 +0100 | |
9269 | @@ -0,0 +1,289 @@ | |
9270 | + | |
9271 | + /* $Id$ */ | |
9272 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
9273 | + | |
9274 | +#include "fpm_config.h" | |
9275 | + | |
9276 | +#include <string.h> | |
9277 | +#include <sys/time.h> | |
9278 | +#include <sys/resource.h> | |
9279 | +#include <stdlib.h> | |
9280 | +#include <unistd.h> | |
9281 | +#include <sys/types.h> | |
9282 | +#include <pwd.h> | |
9283 | +#include <grp.h> | |
9284 | + | |
9285 | +#ifdef HAVE_PRCTL | |
9286 | +#include <sys/prctl.h> | |
9287 | +#endif | |
9288 | + | |
9289 | +#include "fpm.h" | |
9290 | +#include "fpm_conf.h" | |
9291 | +#include "fpm_cleanup.h" | |
9292 | +#include "fpm_clock.h" | |
9293 | +#include "fpm_stdio.h" | |
9294 | +#include "fpm_unix.h" | |
9295 | +#include "zlog.h" | |
9296 | + | |
9297 | +size_t fpm_pagesize; | |
9298 | + | |
9299 | +int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp) | |
9300 | +{ | |
9301 | + struct fpm_listen_options_s *lo = wp->config->listen_options; | |
9302 | + | |
9303 | + /* uninitialized */ | |
9304 | + wp->socket_uid = -1; | |
9305 | + wp->socket_gid = -1; | |
9306 | + wp->socket_mode = 0666; | |
9307 | + | |
9308 | + if (!lo) { return 0; } | |
9309 | + | |
9310 | + if (lo->owner && *lo->owner) { | |
9311 | + struct passwd *pwd; | |
9312 | + | |
9313 | + pwd = getpwnam(lo->owner); | |
9314 | + | |
9315 | + if (!pwd) { | |
9316 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "cannot get uid for user '%s', pool '%s'", lo->owner, wp->config->name); | |
9317 | + return -1; | |
9318 | + } | |
9319 | + | |
9320 | + wp->socket_uid = pwd->pw_uid; | |
9321 | + wp->socket_gid = pwd->pw_gid; | |
9322 | + } | |
9323 | + | |
9324 | + if (lo->group && *lo->group) { | |
9325 | + struct group *grp; | |
9326 | + | |
9327 | + grp = getgrnam(lo->group); | |
9328 | + | |
9329 | + if (!grp) { | |
9330 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "cannot get gid for group '%s', pool '%s'", lo->group, wp->config->name); | |
9331 | + return -1; | |
9332 | + } | |
9333 | + | |
9334 | + wp->socket_gid = grp->gr_gid; | |
9335 | + } | |
9336 | + | |
9337 | + if (lo->mode && *lo->mode) { | |
9338 | + wp->socket_mode = strtoul(lo->mode, 0, 8); | |
9339 | + } | |
9340 | + | |
9341 | + return 0; | |
9342 | +} | |
9343 | + | |
9344 | +static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) | |
9345 | +{ | |
9346 | + int is_root = !geteuid(); | |
9347 | + | |
9348 | + if (is_root) { | |
9349 | + if (wp->config->user && *wp->config->user) { | |
9350 | + | |
9351 | + if (strlen(wp->config->user) == strspn(wp->config->user, "0123456789")) { | |
9352 | + wp->set_uid = strtoul(wp->config->user, 0, 10); | |
9353 | + } | |
9354 | + else { | |
9355 | + struct passwd *pwd; | |
9356 | + | |
9357 | + pwd = getpwnam(wp->config->user); | |
9358 | + | |
9359 | + if (!pwd) { | |
9360 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "cannot get uid for user '%s', pool '%s'", wp->config->user, wp->config->name); | |
9361 | + return -1; | |
9362 | + } | |
9363 | + | |
9364 | + wp->set_uid = pwd->pw_uid; | |
9365 | + wp->set_gid = pwd->pw_gid; | |
9366 | + | |
9367 | + wp->user = strdup(pwd->pw_name); | |
9368 | + wp->home = strdup(pwd->pw_dir); | |
9369 | + } | |
9370 | + } | |
9371 | + | |
9372 | + if (wp->config->group && *wp->config->group) { | |
9373 | + | |
9374 | + if (strlen(wp->config->group) == strspn(wp->config->group, "0123456789")) { | |
9375 | + wp->set_gid = strtoul(wp->config->group, 0, 10); | |
9376 | + } | |
9377 | + else { | |
9378 | + struct group *grp; | |
9379 | + | |
9380 | + grp = getgrnam(wp->config->group); | |
9381 | + | |
9382 | + if (!grp) { | |
9383 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "cannot get gid for group '%s', pool '%s'", wp->config->group, wp->config->name); | |
9384 | + return -1; | |
9385 | + } | |
9386 | + | |
9387 | + wp->set_gid = grp->gr_gid; | |
9388 | + } | |
9389 | + } | |
9390 | + | |
9391 | +#ifndef I_REALLY_WANT_ROOT_PHP | |
9392 | + if (wp->set_uid == 0 || wp->set_gid == 0) { | |
9393 | + zlog(ZLOG_STUFF, ZLOG_ERROR, "please specify user and group other than root, pool '%s'", wp->config->name); | |
9394 | + return -1; | |
9395 | + } | |
9396 | +#endif | |
9397 | + } | |
9398 | + else { /* not root */ | |
9399 | + if (wp->config->user && *wp->config->user) { | |
9400 | + zlog(ZLOG_STUFF, ZLOG_WARNING, "'user' directive is ignored, pool '%s'", wp->config->name); | |
9401 | + } | |
9402 | + if (wp->config->group && *wp->config->group) { | |
9403 | + zlog(ZLOG_STUFF, ZLOG_WARNING, "'group' directive is ignored, pool '%s'", wp->config->name); | |
9404 | + } | |
9405 | + if (wp->config->chroot && *wp->config->chroot) { | |
9406 | + zlog(ZLOG_STUFF, ZLOG_WARNING, "'chroot' directive is ignored, pool '%s'", wp->config->name); | |
9407 | + } | |
9408 | + | |
9409 | + { /* set up HOME and USER anyway */ | |
9410 | + struct passwd *pwd; | |
9411 | + | |
9412 | + pwd = getpwuid(getuid()); | |
9413 | + | |
9414 | + if (pwd) { | |
9415 | + wp->user = strdup(pwd->pw_name); | |
9416 | + wp->home = strdup(pwd->pw_dir); | |
9417 | + } | |
9418 | + } | |
9419 | + } | |
9420 | + | |
9421 | + return 0; | |
9422 | +} | |
9423 | + | |
9424 | +int fpm_unix_init_child(struct fpm_worker_pool_s *wp) | |
9425 | +{ | |
9426 | + int is_root = !geteuid(); | |
9427 | + int made_chroot = 0; | |
9428 | + | |
9429 | + if (wp->config->rlimit_files) { | |
9430 | + struct rlimit r; | |
9431 | + | |
9432 | + getrlimit(RLIMIT_NOFILE, &r); | |
9433 | + | |
9434 | + r.rlim_cur = (rlim_t) wp->config->rlimit_files; | |
9435 | + | |
9436 | + if (0 > setrlimit(RLIMIT_NOFILE, &r)) { | |
9437 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setrlimit(RLIMIT_NOFILE) failed"); | |
9438 | + } | |
9439 | + } | |
9440 | + | |
9441 | + if (wp->config->rlimit_core) { | |
9442 | + struct rlimit r; | |
9443 | + | |
9444 | + getrlimit(RLIMIT_CORE, &r); | |
9445 | + | |
9446 | + r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core; | |
9447 | + | |
9448 | + if (0 > setrlimit(RLIMIT_CORE, &r)) { | |
9449 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setrlimit(RLIMIT_CORE) failed"); | |
9450 | + } | |
9451 | + } | |
9452 | + | |
9453 | + if (is_root && wp->config->chroot && *wp->config->chroot) { | |
9454 | + if (0 > chroot(wp->config->chroot)) { | |
9455 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chroot(%s) failed", wp->config->chroot); | |
9456 | + return -1; | |
9457 | + } | |
9458 | + made_chroot = 1; | |
9459 | + } | |
9460 | + | |
9461 | + if (wp->config->chdir && *wp->config->chdir) { | |
9462 | + if (0 > chdir(wp->config->chdir)) { | |
9463 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chdir(%s) failed", wp->config->chdir); | |
9464 | + return -1; | |
9465 | + } | |
9466 | + } | |
9467 | + else if (made_chroot) { | |
9468 | + chdir("/"); | |
9469 | + } | |
9470 | + | |
9471 | + if (is_root) { | |
9472 | + if (wp->set_gid) { | |
9473 | + if (0 > setgid(wp->set_gid)) { | |
9474 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setgid(%d) failed", wp->set_gid); | |
9475 | + return -1; | |
9476 | + } | |
9477 | + } | |
9478 | + if (wp->set_uid) { | |
9479 | + if (0 > initgroups(wp->config->user, wp->set_gid)) { | |
9480 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "initgroups(%s, %d) failed", wp->config->user, wp->set_gid); | |
9481 | + return -1; | |
9482 | + } | |
9483 | + if (0 > setuid(wp->set_uid)) { | |
9484 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setuid(%d) failed", wp->set_uid); | |
9485 | + return -1; | |
9486 | + } | |
9487 | + } | |
9488 | + } | |
9489 | + | |
9490 | +#ifdef HAVE_PRCTL | |
9491 | + if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) { | |
9492 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "prctl(PR_SET_DUMPABLE) failed"); | |
9493 | + } | |
9494 | +#endif | |
9495 | + | |
9496 | + if (0 > fpm_clock_init()) { | |
9497 | + return -1; | |
9498 | + } | |
9499 | + | |
9500 | + return 0; | |
9501 | +} | |
9502 | + | |
9503 | +int fpm_unix_init_main() | |
9504 | +{ | |
9505 | + struct fpm_worker_pool_s *wp; | |
9506 | + | |
9507 | + fpm_pagesize = getpagesize(); | |
9508 | + | |
9509 | + if (fpm_global_config.daemonize) { | |
9510 | + | |
9511 | + switch (fork()) { | |
9512 | + | |
9513 | + case -1 : | |
9514 | + | |
9515 | + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fork() failed"); | |
9516 | + return -1; | |
9517 | + | |
9518 | + case 0 : | |
9519 | + | |
9520 | + break; | |
9521 | + | |
9522 | + default : | |
9523 | + | |
9524 | + fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT); | |
9525 | + exit(0); | |
9526 | + | |
9527 | + } | |
9528 | + | |
9529 | + } | |
9530 | + | |
9531 | + setsid(); | |
9532 | + | |
9533 | + if (0 > fpm_clock_init()) { | |
9534 | + return -1; | |
9535 | + } | |
9536 | + | |
9537 | + fpm_globals.parent_pid = getpid(); | |
9538 | + | |
9539 | + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { | |
9540 | + | |
9541 | + if (0 > fpm_unix_conf_wp(wp)) { | |
9542 | + return -1; | |
9543 | + } | |
9544 | + | |
9545 | + } | |
9546 | + | |
9547 | + fpm_stdio_init_final(); | |
9548 | + | |
9549 | + { | |
9550 | + struct rlimit r; | |
9551 | + getrlimit(RLIMIT_NOFILE, &r); | |
9552 | + | |
9553 | + zlog(ZLOG_STUFF, ZLOG_NOTICE, "getrlimit(nofile): max:%lld, cur:%lld", | |
9554 | + (long long) r.rlim_max, (long long) r.rlim_cur); | |
9555 | + } | |
9556 | + | |
9557 | + return 0; | |
9558 | +} | |
9559 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_unix.h php-src/sapi/fpm/fpm/fpm_unix.h | |
9560 | --- php-src-vanilla/sapi/fpm/fpm/fpm_unix.h 1970-01-01 01:00:00.000000000 +0100 | |
9561 | +++ php-src/sapi/fpm/fpm/fpm_unix.h 2009-10-18 21:05:39.308376784 +0100 | |
9562 | @@ -0,0 +1,17 @@ | |
9563 | + | |
9564 | + /* $Id$ */ | |
9565 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
9566 | + | |
9567 | +#ifndef FPM_UNIX_H | |
9568 | +#define FPM_UNIX_H 1 | |
9569 | + | |
9570 | +#include "fpm_worker_pool.h" | |
9571 | + | |
9572 | +int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp); | |
9573 | +int fpm_unix_init_child(struct fpm_worker_pool_s *wp); | |
9574 | +int fpm_unix_init_main(); | |
9575 | + | |
9576 | +extern size_t fpm_pagesize; | |
9577 | + | |
9578 | +#endif | |
9579 | + | |
9580 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_worker_pool.c php-src/sapi/fpm/fpm/fpm_worker_pool.c | |
9581 | --- php-src-vanilla/sapi/fpm/fpm/fpm_worker_pool.c 1970-01-01 01:00:00.000000000 +0100 | |
9582 | +++ php-src/sapi/fpm/fpm/fpm_worker_pool.c 2009-10-18 21:05:39.308376784 +0100 | |
9583 | @@ -0,0 +1,69 @@ | |
9584 | + | |
9585 | + /* $Id$ */ | |
9586 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
9587 | + | |
9588 | +#include "fpm_config.h" | |
9589 | + | |
9590 | +#include <string.h> | |
9591 | +#include <stdlib.h> | |
9592 | +#include <unistd.h> | |
9593 | + | |
9594 | +#include "fpm_worker_pool.h" | |
9595 | +#include "fpm_cleanup.h" | |
9596 | +#include "fpm_children.h" | |
9597 | +#include "fpm_shm.h" | |
9598 | +#include "fpm_shm_slots.h" | |
9599 | +#include "fpm_conf.h" | |
9600 | + | |
9601 | +struct fpm_worker_pool_s *fpm_worker_all_pools; | |
9602 | + | |
9603 | +static void fpm_worker_pool_cleanup(int which, void *arg) | |
9604 | +{ | |
9605 | + struct fpm_worker_pool_s *wp, *wp_next; | |
9606 | + | |
9607 | + for (wp = fpm_worker_all_pools; wp; wp = wp_next) { | |
9608 | + wp_next = wp->next; | |
9609 | + fpm_worker_pool_config_free(wp->config); | |
9610 | + fpm_children_free(wp->children); | |
9611 | + fpm_array_free(&wp->slots_used); | |
9612 | + fpm_array_free(&wp->slots_free); | |
9613 | + fpm_shm_free_list(wp->shm_list, which == FPM_CLEANUP_CHILD ? fpm_shm_slots_mem() : 0); | |
9614 | + free(wp->config); | |
9615 | + free(wp->user); | |
9616 | + free(wp->home); | |
9617 | + free(wp); | |
9618 | + } | |
9619 | + | |
9620 | + fpm_worker_all_pools = 0; | |
9621 | +} | |
9622 | + | |
9623 | +struct fpm_worker_pool_s *fpm_worker_pool_alloc() | |
9624 | +{ | |
9625 | + struct fpm_worker_pool_s *ret; | |
9626 | + | |
9627 | + ret = malloc(sizeof(struct fpm_worker_pool_s)); | |
9628 | + | |
9629 | + if (!ret) { | |
9630 | + return 0; | |
9631 | + } | |
9632 | + | |
9633 | + memset(ret, 0, sizeof(struct fpm_worker_pool_s)); | |
9634 | + | |
9635 | + if (!fpm_worker_all_pools) { | |
9636 | + fpm_worker_all_pools = ret; | |
9637 | + } | |
9638 | + | |
9639 | + fpm_array_init(&ret->slots_used, sizeof(struct fpm_shm_slot_ptr_s), 50); | |
9640 | + fpm_array_init(&ret->slots_free, sizeof(struct fpm_shm_slot_ptr_s), 50); | |
9641 | + | |
9642 | + return ret; | |
9643 | +} | |
9644 | + | |
9645 | +int fpm_worker_pool_init_main() | |
9646 | +{ | |
9647 | + if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_worker_pool_cleanup, 0)) { | |
9648 | + return -1; | |
9649 | + } | |
9650 | + | |
9651 | + return 0; | |
9652 | +} | |
9653 | diff -Naur php-src-vanilla/sapi/fpm/fpm/fpm_worker_pool.h php-src/sapi/fpm/fpm/fpm_worker_pool.h | |
9654 | --- php-src-vanilla/sapi/fpm/fpm/fpm_worker_pool.h 1970-01-01 01:00:00.000000000 +0100 | |
9655 | +++ php-src/sapi/fpm/fpm/fpm_worker_pool.h 2009-10-18 21:05:39.310440424 +0100 | |
9656 | @@ -0,0 +1,46 @@ | |
9657 | + | |
9658 | + /* $Id$ */ | |
9659 | + /* (c) 2007,2008 Andrei Nigmatulin */ | |
9660 | + | |
9661 | +#ifndef FPM_WORKER_POOL_H | |
9662 | +#define FPM_WORKER_POOL_H 1 | |
9663 | + | |
9664 | +#include "fpm_conf.h" | |
9665 | +#include "fpm_arrays.h" | |
9666 | + | |
9667 | +struct fpm_worker_pool_s; | |
9668 | +struct fpm_child_s; | |
9669 | +struct fpm_child_stat_s; | |
9670 | +struct fpm_shm_s; | |
9671 | + | |
9672 | +enum fpm_address_domain { | |
9673 | + FPM_AF_UNIX = 1, | |
9674 | + FPM_AF_INET = 2 | |
9675 | +}; | |
9676 | + | |
9677 | +struct fpm_worker_pool_s { | |
9678 | + struct fpm_worker_pool_s *next; | |
9679 | + struct fpm_worker_pool_config_s *config; | |
9680 | + char *user, *home; /* for setting env USER and HOME */ | |
9681 | + enum fpm_address_domain listen_address_domain; | |
9682 | + int listening_socket; | |
9683 | + int set_uid, set_gid; /* config uid and gid */ | |
9684 | + unsigned is_template:1; /* just config template, no processes will be created */ | |
9685 | + int socket_uid, socket_gid, socket_mode; | |
9686 | + | |
9687 | + struct fpm_shm_s *shm_list; | |
9688 | + struct fpm_array_s slots_used; | |
9689 | + struct fpm_array_s slots_free; | |
9690 | + | |
9691 | + /* runtime */ | |
9692 | + struct fpm_child_s *children; | |
9693 | + int running_children; | |
9694 | +}; | |
9695 | + | |
9696 | +struct fpm_worker_pool_s *fpm_worker_pool_alloc(); | |
9697 | +int fpm_worker_pool_init_main(); | |
9698 | + | |
9699 | +extern struct fpm_worker_pool_s *fpm_worker_all_pools; | |
9700 | + | |
9701 | +#endif | |
9702 | + | |
9703 | diff -Naur php-src-vanilla/sapi/fpm/fpm/xml_config.c php-src/sapi/fpm/fpm/xml_config.c | |
9704 | --- php-src-vanilla/sapi/fpm/fpm/xml_config.c 1970-01-01 01:00:00.000000000 +0100 | |
9705 | +++ php-src/sapi/fpm/fpm/xml_config.c 2009-10-18 21:05:39.310440424 +0100 | |
9706 | @@ -0,0 +1,278 @@ | |
9707 | + | |
9708 | + /* $Id$ */ | |
9709 | + /* (c) 2004-2007 Andrei Nigmatulin */ | |
9710 | + | |
9711 | +#include "fpm_config.h" | |
9712 | + | |
9713 | +#ifdef HAVE_ALLOCA_H | |
9714 | +#include <alloca.h> | |
9715 | +#endif | |
9716 | +#include <string.h> | |
9717 | +#include <stdio.h> | |
9718 | +#include <stddef.h> | |
9719 | +#include <stdlib.h> | |
9720 | + | |
9721 | +#include <libxml/parser.h> | |
9722 | +#include <libxml/tree.h> | |
9723 | + | |
9724 | +#include "xml_config.h" | |
9725 | + | |
9726 | +static struct xml_conf_section **xml_conf_sections = 0; | |
9727 | +static int xml_conf_sections_allocated = 0; | |
9728 | +static int xml_conf_sections_used = 0; | |
9729 | + | |
9730 | +char *xml_conf_set_slot_boolean(void **conf, char *name, void *vv, intptr_t offset) | |
9731 | +{ | |
9732 | + char *value = vv; | |
9733 | + long value_y = !strcasecmp(value, "yes") || !strcmp(value, "1") || !strcasecmp(value, "on"); | |
9734 | + long value_n = !strcasecmp(value, "no") || !strcmp(value, "0") || !strcasecmp(value, "off"); | |
9735 | + | |
9736 | + if (!value_y && !value_n) { | |
9737 | + return "xml_conf_set_slot(): invalid boolean value"; | |
9738 | + } | |
9739 | + | |
9740 | +#ifdef XML_CONF_DEBUG | |
9741 | + fprintf(stderr, "setting boolean '%s' => %s\n", name, value_y ? "TRUE" : "FALSE"); | |
9742 | +#endif | |
9743 | + | |
9744 | + * (int *) ((char *) *conf + offset) = value_y ? 1 : 0; | |
9745 | + | |
9746 | + return NULL; | |
9747 | +} | |
9748 | + | |
9749 | +char *xml_conf_set_slot_string(void **conf, char *name, void *vv, intptr_t offset) | |
9750 | +{ | |
9751 | + char *value = vv; | |
9752 | + char *v = strdup(value); | |
9753 | + | |
9754 | + if (!v) { return "xml_conf_set_slot_string(): strdup() failed"; } | |
9755 | + | |
9756 | +#ifdef XML_CONF_DEBUG | |
9757 | + fprintf(stderr, "setting string '%s' => '%s'\n", name, v); | |
9758 | +#endif | |
9759 | + | |
9760 | + * (char **) ((char *) *conf + offset) = v; | |
9761 | + | |
9762 | + return NULL; | |
9763 | +} | |
9764 | + | |
9765 | +char *xml_conf_set_slot_integer(void **conf, char *name, void *vv, intptr_t offset) | |
9766 | +{ | |
9767 | + char *value = vv; | |
9768 | + int v = atoi(value); | |
9769 | + | |
9770 | + * (int *) ((char *) *conf + offset) = v; | |
9771 | + | |
9772 | +#ifdef XML_CONF_DEBUG | |
9773 | + fprintf(stderr, "setting integer '%s' => %d\n", name, v); | |
9774 | +#endif | |
9775 | + | |
9776 | + return NULL; | |
9777 | +} | |
9778 | + | |
9779 | +char *xml_conf_set_slot_time(void **conf, char *name, void *vv, intptr_t offset) | |
9780 | +{ | |
9781 | + char *value = vv; | |
9782 | + int len = strlen(value); | |
9783 | + char suffix; | |
9784 | + int seconds; | |
9785 | + | |
9786 | + if (!len) { return "xml_conf_set_slot_timeval(): invalid timeval value"; } | |
9787 | + | |
9788 | + suffix = value[len-1]; | |
9789 | + | |
9790 | + value[len-1] = '\0'; | |
9791 | + | |
9792 | + switch (suffix) { | |
9793 | + case 's' : | |
9794 | + seconds = atoi(value); | |
9795 | + break; | |
9796 | + case 'm' : | |
9797 | + seconds = 60 * atoi(value); | |
9798 | + break; | |
9799 | + case 'h' : | |
9800 | + seconds = 60 * 60 * atoi(value); | |
9801 | + break; | |
9802 | + case 'd' : | |
9803 | + seconds = 24 * 60 * 60 * atoi(value); | |
9804 | + break; | |
9805 | + default : | |
9806 | + return "xml_conf_set_slot_timeval(): unknown suffix used in timeval value"; | |
9807 | + } | |
9808 | + | |
9809 | + * (int *) ((char *) *conf + offset) = seconds; | |
9810 | + | |
9811 | +#ifdef XML_CONF_DEBUG | |
9812 | + fprintf(stderr, "setting time '%s' => %d:%02d:%02d:%02d\n", name, expand_dhms(seconds)); | |
9813 | +#endif | |
9814 | + | |
9815 | + return NULL; | |
9816 | +} | |
9817 | + | |
9818 | +char *xml_conf_parse_section(void **conf, struct xml_conf_section *section, void *xml_node) | |
9819 | +{ | |
9820 | + xmlNode *element = xml_node; | |
9821 | + char *ret = 0; | |
9822 | + | |
9823 | +#ifdef XML_CONF_DEBUG | |
9824 | + fprintf(stderr, "processing a section %s\n", section->path); | |
9825 | +#endif | |
9826 | + | |
9827 | + for ( ; element; element = element->next) { | |
9828 | + if (element->type == XML_ELEMENT_NODE && !strcmp((const char *) element->name, "value") && element->children) { | |
9829 | + xmlChar *name = xmlGetProp(element, (unsigned char *) "name"); | |
9830 | + | |
9831 | + if (name) { | |
9832 | + int i; | |
9833 | + | |
9834 | +#ifdef XML_CONF_DEBUG | |
9835 | + fprintf(stderr, "found a value: %s\n", name); | |
9836 | +#endif | |
9837 | + for (i = 0; section->parsers[i].parser; i++) { | |
9838 | + if (!section->parsers[i].name || !strcmp(section->parsers[i].name, (char *) name)) { | |
9839 | + break; | |
9840 | + } | |
9841 | + } | |
9842 | + | |
9843 | + if (section->parsers[i].parser) { | |
9844 | + if (section->parsers[i].type == XML_CONF_SCALAR) { | |
9845 | + if (element->children->type == XML_TEXT_NODE) { | |
9846 | + ret = section->parsers[i].parser(conf, (char *) name, element->children->content, section->parsers[i].offset); | |
9847 | + } | |
9848 | + else { | |
9849 | + ret = "XML_TEXT_NODE is expected, something different is given"; | |
9850 | + } | |
9851 | + } | |
9852 | + else { | |
9853 | + ret = section->parsers[i].parser(conf, (char *) name, element->children, section->parsers[i].offset); | |
9854 | + } | |
9855 | + | |
9856 | + xmlFree(name); | |
9857 | + if (ret) { return ret; } | |
9858 | + else { continue; } | |
9859 | + } | |
9860 | + | |
9861 | + fprintf(stderr, "Warning, unknown setting '%s' in section '%s'\n", (char *) name, section->path); | |
9862 | + | |
9863 | + xmlFree(name); | |
9864 | + } | |
9865 | + } | |
9866 | + } | |
9867 | + | |
9868 | + return NULL; | |
9869 | +} | |
9870 | + | |
9871 | +static char *xml_conf_parse_file(xmlNode *element) | |
9872 | +{ | |
9873 | + char *ret = 0; | |
9874 | + | |
9875 | + for ( ; element; element = element->next) { | |
9876 | + | |
9877 | + if (element->parent && element->type == XML_ELEMENT_NODE && !strcmp((const char *) element->name, "section")) { | |
9878 | + xmlChar *name = xmlGetProp(element, (unsigned char *) "name"); | |
9879 | + | |
9880 | + if (name) { | |
9881 | + char *parent_name = (char *) xmlGetNodePath(element->parent); | |
9882 | + char *full_name; | |
9883 | + int i; | |
9884 | + struct xml_conf_section *section = NULL; | |
9885 | + | |
9886 | +#ifdef XML_CONF_DEBUG | |
9887 | + fprintf(stderr, "got a section: %s/%s\n", parent_name, name); | |
9888 | +#endif | |
9889 | + full_name = alloca(strlen(parent_name) + strlen((char *) name) + 1 + 1); | |
9890 | + | |
9891 | + sprintf(full_name, "%s/%s", parent_name, (char *) name); | |
9892 | + | |
9893 | + xmlFree(parent_name); | |
9894 | + xmlFree(name); | |
9895 | + | |
9896 | + for (i = 0; i < xml_conf_sections_used; i++) { | |
9897 | + if (!strcmp(xml_conf_sections[i]->path, full_name)) { | |
9898 | + section = xml_conf_sections[i]; | |
9899 | + } | |
9900 | + } | |
9901 | + | |
9902 | + if (section) { /* found a registered section */ | |
9903 | + void *conf = section->conf(); | |
9904 | + ret = xml_conf_parse_section(&conf, section, element->children); | |
9905 | + if (ret) { break; } | |
9906 | + } | |
9907 | + | |
9908 | + } | |
9909 | + } | |
9910 | + | |
9911 | + if (element->children) { | |
9912 | + ret = xml_conf_parse_file(element->children); | |
9913 | + if (ret) { break; } | |
9914 | + } | |
9915 | + } | |
9916 | + | |
9917 | + return ret; | |
9918 | +} | |
9919 | + | |
9920 | +char *xml_conf_load_file(char *file) | |
9921 | +{ | |
9922 | + char *ret = 0; | |
9923 | + xmlDoc *doc; | |
9924 | + | |
9925 | + LIBXML_TEST_VERSION | |
9926 | + | |
9927 | + doc = xmlParseFile(file); | |
9928 | + | |
9929 | + if (doc) { | |
9930 | + ret = xml_conf_parse_file(doc->children); | |
9931 | + xmlFreeDoc(doc); | |
9932 | + } | |
9933 | + else { | |
9934 | + ret = "failed to parse conf file"; | |
9935 | + } | |
9936 | + | |
9937 | + xmlCleanupParser(); | |
9938 | + return ret; | |
9939 | +} | |
9940 | + | |
9941 | +int xml_conf_init() | |
9942 | +{ | |
9943 | + return 0; | |
9944 | +} | |
9945 | + | |
9946 | +void xml_conf_clean() | |
9947 | +{ | |
9948 | + if (xml_conf_sections) { | |
9949 | + free(xml_conf_sections); | |
9950 | + } | |
9951 | +} | |
9952 | + | |
9953 | +int xml_conf_section_register(struct xml_conf_section *section) | |
9954 | +{ | |
9955 | + if (xml_conf_sections_allocated == xml_conf_sections_used) { | |
9956 | + int new_size = xml_conf_sections_used + 10; | |
9957 | + void *new_ptr = realloc(xml_conf_sections, sizeof(struct xml_conf_section *) * new_size); | |
9958 | + | |
9959 | + if (new_ptr) { | |
9960 | + xml_conf_sections = new_ptr; | |
9961 | + xml_conf_sections_allocated = new_size; | |
9962 | + } | |
9963 | + else { | |
9964 | + fprintf(stderr, "xml_conf_section_register(): out of memory\n"); | |
9965 | + return -1; | |
9966 | + } | |
9967 | + } | |
9968 | + | |
9969 | + xml_conf_sections[xml_conf_sections_used++] = section; | |
9970 | + | |
9971 | + return 0; | |
9972 | +} | |
9973 | + | |
9974 | +int xml_conf_sections_register(struct xml_conf_section *sections[]) | |
9975 | +{ | |
9976 | + for ( ; sections && *sections; sections++) { | |
9977 | + if (0 > xml_conf_section_register(*sections)) { | |
9978 | + return -1; | |
9979 | + } | |
9980 | + } | |
9981 | + | |
9982 | + return 0; | |
9983 | +} | |
9984 | + | |
9985 | diff -Naur php-src-vanilla/sapi/fpm/fpm/xml_config.h php-src/sapi/fpm/fpm/xml_config.h | |
9986 | --- php-src-vanilla/sapi/fpm/fpm/xml_config.h 1970-01-01 01:00:00.000000000 +0100 | |
9987 | +++ php-src/sapi/fpm/fpm/xml_config.h 2009-10-18 21:05:39.310440424 +0100 | |
9988 | @@ -0,0 +1,48 @@ | |
9989 | + | |
9990 | + /* $Id$ */ | |
9991 | + /* (c) 2004-2007 Andrei Nigmatulin */ | |
9992 | + | |
9993 | +#ifndef XML_CONFIG_H | |
9994 | +#define XML_CONFIG_H 1 | |
9995 | + | |
9996 | +#if HAVE_INTTYPES_H | |
9997 | +#include <inttypes.h> | |
9998 | +#else | |
9999 | +#include <stdint.h> | |
10000 | +#endif | |
10001 | + | |
10002 | + | |
10003 | +struct xml_value_parser; | |
10004 | + | |
10005 | +struct xml_value_parser { | |
10006 | + int type; | |
10007 | + char *name; | |
10008 | + char *(*parser)(void **, char *, void *, intptr_t offset); | |
10009 | + intptr_t offset; | |
10010 | +}; | |
10011 | + | |
10012 | +struct xml_conf_section { | |
10013 | + void *(*conf)(); | |
10014 | + char *path; | |
10015 | + struct xml_value_parser *parsers; | |
10016 | +}; | |
10017 | + | |
10018 | +char *xml_conf_set_slot_boolean(void **conf, char *name, void *value, intptr_t offset); | |
10019 | +char *xml_conf_set_slot_string(void **conf, char *name, void *value, intptr_t offset); | |
10020 | +char *xml_conf_set_slot_integer(void **conf, char *name, void *value, intptr_t offset); | |
10021 | +char *xml_conf_set_slot_time(void **conf, char *name, void *value, intptr_t offset); | |
10022 | + | |
10023 | +int xml_conf_init(); | |
10024 | +void xml_conf_clean(); | |
10025 | +char *xml_conf_load_file(char *file); | |
10026 | +char *xml_conf_parse_section(void **conf, struct xml_conf_section *section, void *ve); | |
10027 | +int xml_conf_section_register(struct xml_conf_section *section); | |
10028 | +int xml_conf_sections_register(struct xml_conf_section *sections[]); | |
10029 | + | |
10030 | +#define expand_hms(value) (value) / 3600, ((value) % 3600) / 60, (value) % 60 | |
10031 | + | |
10032 | +#define expand_dhms(value) (value) / 86400, ((value) % 86400) / 3600, ((value) % 3600) / 60, (value) % 60 | |
10033 | + | |
10034 | +enum { XML_CONF_SCALAR = 1, XML_CONF_SUBSECTION = 2 }; | |
10035 | + | |
10036 | +#endif | |
10037 | diff -Naur php-src-vanilla/sapi/fpm/fpm/zlog.c php-src/sapi/fpm/fpm/zlog.c | |
10038 | --- php-src-vanilla/sapi/fpm/fpm/zlog.c 1970-01-01 01:00:00.000000000 +0100 | |
10039 | +++ php-src/sapi/fpm/fpm/zlog.c 2009-10-18 21:05:39.310440424 +0100 | |
10040 | @@ -0,0 +1,113 @@ | |
10041 | + | |
10042 | + /* $Id$ */ | |
10043 | + /* (c) 2004-2007 Andrei Nigmatulin */ | |
10044 | + | |
10045 | +#include "fpm_config.h" | |
10046 | + | |
10047 | +#include <stdio.h> | |
10048 | +#include <unistd.h> | |
10049 | +#include <time.h> | |
10050 | +#include <string.h> | |
10051 | +#include <stdarg.h> | |
10052 | +#include <sys/time.h> | |
10053 | +#include <errno.h> | |
10054 | + | |
10055 | +#include "zlog.h" | |
10056 | + | |
10057 | +#define MAX_LINE_LENGTH 1024 | |
10058 | + | |
10059 | +static int zlog_fd = -1; | |
10060 | +static int zlog_level = ZLOG_NOTICE; | |
10061 | + | |
10062 | +static const char *level_names[] = { | |
10063 | + [ZLOG_DEBUG] = "DEBUG", | |
10064 | + [ZLOG_NOTICE] = "NOTICE", | |
10065 | + [ZLOG_WARNING] = "WARNING", | |
10066 | + [ZLOG_ERROR] = "ERROR", | |
10067 | + [ZLOG_ALERT] = "ALERT", | |
10068 | +}; | |
10069 | + | |
10070 | +size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len) | |
10071 | +{ | |
10072 | + struct tm t; | |
10073 | + size_t len; | |
10074 | + | |
10075 | + len = strftime(timebuf, timebuf_len, "%b %d %H:%M:%S", localtime_r((const time_t *) &tv->tv_sec, &t)); | |
10076 | + len += snprintf(timebuf + len, timebuf_len - len, ".%06d", (int) tv->tv_usec); | |
10077 | + | |
10078 | + return len; | |
10079 | +} | |
10080 | + | |
10081 | +int zlog_set_fd(int new_fd) | |
10082 | +{ | |
10083 | + int old_fd = zlog_fd; | |
10084 | + zlog_fd = new_fd; | |
10085 | + | |
10086 | + return old_fd; | |
10087 | +} | |
10088 | + | |
10089 | +int zlog_set_level(int new_value) | |
10090 | +{ | |
10091 | + int old_value = zlog_level; | |
10092 | + | |
10093 | + zlog_level = new_value; | |
10094 | + | |
10095 | + return old_value; | |
10096 | +} | |
10097 | + | |
10098 | +void zlog(const char *function, int line, int flags, const char *fmt, ...) | |
10099 | +{ | |
10100 | + struct timeval tv; | |
10101 | + char buf[MAX_LINE_LENGTH]; | |
10102 | + const size_t buf_size = MAX_LINE_LENGTH; | |
10103 | + va_list args; | |
10104 | + size_t len; | |
10105 | + int truncated = 0; | |
10106 | + int saved_errno; | |
10107 | + | |
10108 | + if ((flags & ZLOG_LEVEL_MASK) < zlog_level) { | |
10109 | + return; | |
10110 | + } | |
10111 | + | |
10112 | + saved_errno = errno; | |
10113 | + | |
10114 | + gettimeofday(&tv, 0); | |
10115 | + | |
10116 | + len = zlog_print_time(&tv, buf, buf_size); | |
10117 | + | |
10118 | + len += snprintf(buf + len, buf_size - len, " [%s] %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line); | |
10119 | + | |
10120 | + if (len > buf_size - 1) { | |
10121 | + truncated = 1; | |
10122 | + } | |
10123 | + | |
10124 | + if (!truncated) { | |
10125 | + va_start(args, fmt); | |
10126 | + | |
10127 | + len += vsnprintf(buf + len, buf_size - len, fmt, args); | |
10128 | + | |
10129 | + va_end(args); | |
10130 | + | |
10131 | + if (len >= buf_size) { | |
10132 | + truncated = 1; | |
10133 | + } | |
10134 | + } | |
10135 | + | |
10136 | + if (!truncated) { | |
10137 | + if (flags & ZLOG_HAVE_ERRNO) { | |
10138 | + len += snprintf(buf + len, buf_size - len, ": %s (%d)", strerror(saved_errno), saved_errno); | |
10139 | + if (len >= buf_size) { | |
10140 | + truncated = 1; | |
10141 | + } | |
10142 | + } | |
10143 | + } | |
10144 | + | |
10145 | + if (truncated) { | |
10146 | + memcpy(buf + buf_size - sizeof("..."), "...", sizeof("...") - 1); | |
10147 | + len = buf_size - 1; | |
10148 | + } | |
10149 | + | |
10150 | + buf[len++] = '\n'; | |
10151 | + | |
10152 | + write(zlog_fd > -1 ? zlog_fd : STDERR_FILENO, buf, len); | |
10153 | +} | |
10154 | diff -Naur php-src-vanilla/sapi/fpm/fpm/zlog.h php-src/sapi/fpm/fpm/zlog.h | |
10155 | --- php-src-vanilla/sapi/fpm/fpm/zlog.h 1970-01-01 01:00:00.000000000 +0100 | |
10156 | +++ php-src/sapi/fpm/fpm/zlog.h 2009-10-18 21:05:39.308376784 +0100 | |
10157 | @@ -0,0 +1,34 @@ | |
10158 | + | |
10159 | + /* $Id$ */ | |
10160 | + /* (c) 2004-2007 Andrei Nigmatulin */ | |
10161 | + | |
10162 | +#ifndef ZLOG_H | |
10163 | +#define ZLOG_H 1 | |
10164 | + | |
10165 | +#define ZLOG_STUFF __func__, __LINE__ | |
10166 | + | |
10167 | +struct timeval; | |
10168 | + | |
10169 | +int zlog_set_fd(int new_fd); | |
10170 | +int zlog_set_level(int new_value); | |
10171 | + | |
10172 | +size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len); | |
10173 | + | |
10174 | +void zlog(const char *function, int line, int flags, const char *fmt, ...) | |
10175 | + __attribute__ ((format(printf,4,5))); | |
10176 | + | |
10177 | +enum { | |
10178 | + ZLOG_DEBUG = 1, | |
10179 | + ZLOG_NOTICE = 2, | |
10180 | + ZLOG_WARNING = 3, | |
10181 | + ZLOG_ERROR = 4, | |
10182 | + ZLOG_ALERT = 5, | |
10183 | +}; | |
10184 | + | |
10185 | +#define ZLOG_LEVEL_MASK 7 | |
10186 | + | |
10187 | +#define ZLOG_HAVE_ERRNO 0x100 | |
10188 | + | |
10189 | +#define ZLOG_SYSERROR (ZLOG_ERROR | ZLOG_HAVE_ERRNO) | |
10190 | + | |
10191 | +#endif | |
10192 | diff -Naur php-src-vanilla/sapi/fpm/LICENSE php-src/sapi/fpm/LICENSE | |
10193 | --- php-src-vanilla/sapi/fpm/LICENSE 1970-01-01 01:00:00.000000000 +0100 | |
10194 | +++ php-src/sapi/fpm/LICENSE 2009-10-18 21:05:39.302497288 +0100 | |
10195 | @@ -0,0 +1,23 @@ | |
10196 | +Copyright (c) 2007-2009, Andrei Nigmatulin | |
10197 | +All rights reserved. | |
10198 | + | |
10199 | +Redistribution and use in source and binary forms, with or without | |
10200 | +modification, are permitted provided that the following conditions | |
10201 | +are met: | |
10202 | +1. Redistributions of source code must retain the above copyright | |
10203 | + notice, this list of conditions and the following disclaimer. | |
10204 | +2. Redistributions in binary form must reproduce the above copyright | |
10205 | + notice, this list of conditions and the following disclaimer in the | |
10206 | + documentation and/or other materials provided with the distribution. | |
10207 | + | |
10208 | +THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
10209 | +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
10210 | +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
10211 | +ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE | |
10212 | +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
10213 | +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
10214 | +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
10215 | +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
10216 | +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
10217 | +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
10218 | +SUCH DAMAGE. | |
10219 | diff -Naur php-src-vanilla/sapi/fpm/man/php-fpm.1.in php-src/sapi/fpm/man/php-fpm.1.in | |
10220 | --- php-src-vanilla/sapi/fpm/man/php-fpm.1.in 1970-01-01 01:00:00.000000000 +0100 | |
10221 | +++ php-src/sapi/fpm/man/php-fpm.1.in 2009-10-18 21:05:39.310440424 +0100 | |
10222 | @@ -0,0 +1,186 @@ | |
10223 | +.TH PHP-FPM 1 "2009" "The PHP Group" "Scripting Language" | |
10224 | +.SH NAME | |
10225 | +.TP 15 | |
10226 | +@php_fpm_bin@ \- PHP FastCGI Process Manager 'PHP-FPM' | |
10227 | +.SH SYNOPSIS | |
10228 | +.B @php_fpm_bin@ | |
10229 | +[options] | |
10230 | +.LP | |
10231 | +.SH DESCRIPTION | |
10232 | +\fBPHP\fP is a widely\-used general\-purpose scripting language that is especially suited for | |
10233 | +Web development and can be embedded into HTML. This is a variant of PHP that will run in the background as a daemon, listening for CGI requests. Output is logged to @php_fpm_log_path@. | |
10234 | +.LP | |
10235 | +Most options are set in the xml configuration file @php_fpm_conf_path@. Unless configured otherwise, @php_fpm_bin@ will respond to CGI requests listening on http localhost port 9000 by default. Therefore @php_fpm_bin@ expects your webserver to forward all requests for '.php' files to port 9000 and you should edit your webserver configuration file appropriately. | |
10236 | +.SH OPTIONS | |
10237 | +.TP 15 | |
10238 | +.B \-C | |
10239 | +Do not chdir to the script's directory | |
10240 | +.TP | |
10241 | +.PD 0 | |
10242 | +.B \-\-php\-ini \fIpath\fP|\fIfile\fP | |
10243 | +.TP | |
10244 | +.PD 1 | |
10245 | +.B \-c \fIpath\fP|\fIfile\fP | |
10246 | +Look for | |
10247 | +.B php.ini | |
10248 | +file in the directory | |
10249 | +.IR path | |
10250 | +or use the specified | |
10251 | +.IR file | |
10252 | +.TP | |
10253 | +.PD 0 | |
10254 | +.B \-\-no\-php\-ini | |
10255 | +.TP | |
10256 | +.PD 1 | |
10257 | +.B \-n | |
10258 | +No | |
10259 | +.B php.ini | |
10260 | +file will be used | |
10261 | +.TP | |
10262 | +.PD 0 | |
10263 | +.B \-\-define \fIfoo\fP[=\fIbar\fP] | |
10264 | +.TP | |
10265 | +.PD 1 | |
10266 | +.B \-d \fIfoo\fP[=\fIbar\fP] | |
10267 | +Define INI entry | |
10268 | +.IR foo | |
10269 | +with value | |
10270 | +.IR bar | |
10271 | +.TP | |
10272 | +.B \-e | |
10273 | +Generate extended information for debugger/profiler | |
10274 | +.TP | |
10275 | +.PD 0 | |
10276 | +.B \-\-help | |
10277 | +.TP | |
10278 | +.PD 1 | |
10279 | +.B \-h | |
10280 | +This help | |
10281 | +.TP | |
10282 | +.PD 0 | |
10283 | +.B \-\-info | |
10284 | +.TP | |
10285 | +.PD 1 | |
10286 | +.B \-i | |
10287 | +PHP information and configuration | |
10288 | +.TP | |
10289 | +.PD 0 | |
10290 | +.B \-\-modules | |
10291 | +.TP | |
10292 | +.PD 1 | |
10293 | +.B \-m | |
10294 | +Show compiled in modules | |
10295 | +.TP | |
10296 | +.PD 0 | |
10297 | +.B \-\-version | |
10298 | +.TP | |
10299 | +.PD 1 | |
10300 | +.B \-v | |
10301 | +Version number | |
10302 | +.TP | |
10303 | +.PD 0 | |
10304 | +.B \-\-fpm\-config \fIfile\fP | |
10305 | +.TP | |
10306 | +.PD 1 | |
10307 | +.B \-\-y | |
10308 | +Specify alternative path to FastCGI process manager configuration file (the default is @php_fpm_conf_path@) | |
10309 | +.TP | |
10310 | +.PD 0 | |
10311 | +.B \-\-zend\-extension \fIfile\fP | |
10312 | +.TP | |
10313 | +.PD 1 | |
10314 | +.B \-z \fIfile\fP | |
10315 | +Load Zend extension | |
10316 | +.IR file | |
10317 | +.SH FILES | |
10318 | +.TP 15 | |
10319 | +.B @php_fpm_bin@.conf | |
10320 | +The configuration file for the @php_fpm_bin@ daemon. | |
10321 | +.TP | |
10322 | +.B php.ini | |
10323 | +The standard php configuration file. | |
10324 | +.SH EXAMPLES | |
10325 | +You should use the init script provided to start and stop the @php_fpm_bin@ daemon. This situation applies for any unix systems which use init.d for their main process manager. | |
10326 | +.P | |
10327 | +.PD 1 | |
10328 | +.RS | |
10329 | +sudo /etc/init.d/@php_fpm_bin@ start | |
10330 | +.RE | |
10331 | +.TP | |
10332 | +If your installation has no appropriate init script, launch @php_fpm_bin_path@ with no arguments. It will launch as a daemon (background process) by default. The file @php_fpm_pid_path@ determines whether @php_fpm_bin@ is already up and running. Once started, @php_fpm_bin@ then responds to several POSIX signals: | |
10333 | +.P | |
10334 | +.PD 0 | |
10335 | +.RS | |
10336 | +.B SIGINT,SIGTERM \fPimmediate termination | |
10337 | +.TP | |
10338 | +.B SIGQUIT \fPgraceful stop | |
10339 | +.TP | |
10340 | +.B SIGUSR1 \fPre-open log file | |
10341 | +.TP | |
10342 | +.B SIGUSR2 \fPgraceful reload of all workers + reload of fpm conf/binary | |
10343 | +.RE | |
10344 | +.PD 1 | |
10345 | +.P | |
10346 | +.SH TIPS | |
10347 | +The PHP-FPM CGI daemon will work well with most popular webservers, including Apache2 and light-httpd. For best efficiency and performance improvements its also worthwhile to consider the engine-x webserver ('nginx'), and php opcode-cacher ('php5-xcache'). | |
10348 | +.PD 1 | |
10349 | +.P | |
10350 | +.SH SEE ALSO | |
10351 | +The PHP-FPM website: | |
10352 | +.PD 0 | |
10353 | +.P | |
10354 | +.B http://php-fpm.org | |
10355 | +.PD 1 | |
10356 | +.P | |
10357 | +For a more or less complete description of PHP look here: | |
10358 | +.PD 0 | |
10359 | +.P | |
10360 | +.B http://www.php.net/manual/ | |
10361 | +.PD 1 | |
10362 | +.P | |
10363 | +A nice introduction to PHP by Stig Bakken can be found here: | |
10364 | +.PD 0 | |
10365 | +.P | |
10366 | +.B http://www.zend.com/zend/art/intro.php | |
10367 | +.PD 1 | |
10368 | +.SH BUGS | |
10369 | +You can view the list of known bugs or report any new bug you | |
10370 | +found at: | |
10371 | +.PD 0 | |
10372 | +.P | |
10373 | +.B http://bugs.php.net | |
10374 | +.PD 1 | |
10375 | +.SH AUTHORS | |
10376 | +PHP-FPM Sapi was written by Andrei Nigmatulin. The mailing-lists are highload-php-en (English) and highload-php-ru (Russion). | |
10377 | +.P | |
10378 | +The PHP Group: Thies C. Arntzen, Stig Bakken, Andi Gutmans, Rasmus Lerdorf, Sam Ruby, Sascha Schumann, Zeev Suraski, Jim Winstead, Andrei Zmievski. | |
10379 | +.P | |
10380 | +A List of active developers can be found here: | |
10381 | +.PD 0 | |
10382 | +.P | |
10383 | +.B http://www.php.net/credits.php | |
10384 | +.PD 1 | |
10385 | +.P | |
10386 | +And last but not least PHP was developed with the help of a huge amount of | |
10387 | +contributors all around the world. | |
10388 | +.SH VERSION INFORMATION | |
10389 | +This manpage describes \fBphp\fP, version @PHP_VERSION@, \fBfpm\fP, version @fpm_version@. | |
10390 | +.SH COPYRIGHT | |
10391 | +Copyright \(co 1997\-2009 The PHP Group | |
10392 | +.PD 0 | |
10393 | +.P | |
10394 | +Copyright (c) 2007-2009, Andrei Nigmatulin | |
10395 | +.PD 1 | |
10396 | +.LP | |
10397 | +This source file is subject to version 3.01 of the PHP license, | |
10398 | +that is bundled with this package in the file LICENSE, and is | |
10399 | +available through the world-wide-web at the following url: | |
10400 | +.PD 0 | |
10401 | +.P | |
10402 | +.B http://www.php.net/license/3_01.txt | |
10403 | +.PD 1 | |
10404 | +.P | |
10405 | +If you did not receive a copy of the PHP license and are unable to | |
10406 | +obtain it through the world-wide-web, please send a note to | |
10407 | +.B license@php.net | |
10408 | +so we can mail you a copy immediately. | |
10409 | diff -Naur php-src-vanilla/sapi/fpm/readme-ru.markdown php-src/sapi/fpm/readme-ru.markdown | |
10410 | --- php-src-vanilla/sapi/fpm/readme-ru.markdown 1970-01-01 01:00:00.000000000 +0100 | |
10411 | +++ php-src/sapi/fpm/readme-ru.markdown 2009-10-18 21:05:39.310440424 +0100 | |
10412 | @@ -0,0 +1,127 @@ | |
10413 | +# PHP FastCGI Менеджер процессов (PHP-FPM) | |
10414 | + | |
10415 | +PHP-FPM это Fast-CGI фронтэнд для php и расширение php-cgi. Проект находится на [Launchpad](https://launchpad.net/php-fpm) | |
10416 | + | |
10417 | +## Быстрый старт: | |
10418 | + | |
10419 | +Выберите один из 2 путей сборки fpm: Или `встроенный`, или `отдельный`. Если вы не разработчик или не системный администратор, то мы рекомендуем `встроенный` вариант компиляции. Для дополнительной информации смотрите файл `readme.markdown`. | |
10420 | + | |
10421 | +## Зависимости | |
10422 | +Если вы до этого не устанавливали php, то вам придётся установить пакет `libxml2-dev`. FPM также необходим `libevent-dev`. Debian / ubuntu: | |
10423 | + | |
10424 | + sudo aptitude install -y libxml2-dev libevent-dev | |
10425 | + | |
10426 | +Рекомендуется использовать libevent 1.4.12-stable или позднее, но необходим, как минимум, libevent 1.4.3-stable. Если нет подходящей версии, скайте и скомпилируйте с [сайта Libevent](http://www.monkey.org/~provos/libevent/). | |
10427 | + | |
10428 | + export LE_VER=1.4.12-stable | |
10429 | + wget "http://www.monkey.org/~provos/libevent-$LE_VER.tar.gz" | |
10430 | + tar -zxvf "libevent-$LE_VER.tar.gz" | |
10431 | + cd "libevent-$LE_VER" | |
10432 | + ./configure && make | |
10433 | + DESTDIR=$PWD make install | |
10434 | + export LIBEVENT_SEARCH_PATH="$PWD/usr/local" | |
10435 | + | |
10436 | +## Встроенная сборка | |
10437 | + | |
10438 | +Скачайте fpm и сгенерируйте патч | |
10439 | + | |
10440 | + export PHP_VER=5.3.0 | |
10441 | + wget "http://launchpad.net/php-fpm/master/0.6/+download/php-fpm-0.6-$PHP_VER.tar.gz" | |
10442 | + tar -zxvf "php-fpm-0.6-$PHP_VER.tar.gz" | |
10443 | + "php-fpm-0.6-$PHP_VER/generate-fpm-patch" | |
10444 | + | |
10445 | +Скачайте и распакуйте исходный код PHP | |
10446 | + | |
10447 | + wget "http://ru2.php.net/get/php-$PHP_VER.tar.gz/from/ru2.php.net/mirror" | |
10448 | + tar xvfz "php-$PHP_VER.tar.gz" | |
10449 | + cd "php-$PHP_VER" | |
10450 | + | |
10451 | +Примените патч и компилируйте | |
10452 | + | |
10453 | + patch -p1 < ../fpm.patch | |
10454 | + ./buildconf --force | |
10455 | + mkdir fpm-build && cd fpm-build | |
10456 | + ../configure --with-fpm \ | |
10457 | + --with-libevent="$LIBEVENT_SEARCH_PATH" && make | |
10458 | + | |
10459 | +## Отдельная сборка | |
10460 | + | |
10461 | +Скачайте и распакуйте исходный код PHP | |
10462 | + | |
10463 | + export PHP_VER=5.3.0 | |
10464 | + wget "http://ru2.php.net/get/php-$PHP_VER.tar.gz/from/ru2.php.net/mirror" | |
10465 | + tar xvfz "php-$PHP_VER.tar.gz" | |
10466 | + cd "php-$PHP_VER" | |
10467 | + mkdir php-build && cd php-build | |
10468 | + ../configure && make | |
10469 | + | |
10470 | +Теперь можете скачать, конфигурировать и компилировать FPM фронтэнд | |
10471 | + | |
10472 | + wget "http://launchpad.net/php-fpm/master/0.6/+download/php-fpm-0.6-$PHP_VER.tar.gz" | |
10473 | + tar -zxvf "php-fpm-0.6-$PHP_VER.tar.gz" | |
10474 | + cd "php-fpm-0.6-$PHP_VER" | |
10475 | + mkdir fpm-build && cd fpm-build | |
10476 | + ../configure --srcdir=../ \ | |
10477 | + --with-php-src="../../php-$PHP_VER" \ | |
10478 | + --with-php-build="../../php-$PHP_VER/php-build" \ | |
10479 | + --with-libevent="$LIBEVENT_SEARCH_PATH" && make | |
10480 | + | |
10481 | +## Флаги конфигурирования | |
10482 | + | |
10483 | + --with-libevent[=PATH] Путь до libevent, для fpm SAPI [/usr/local] | |
10484 | + --with-fpm-bin[=PATH] Путь для откомпилированного php-fpm [/usr/local/bin/php-fpm] | |
10485 | + --with-fpm-port[=PORT] TCP порт для cgi запросов [9000] | |
10486 | + --with[out]-fpm-conf[=PATH] Путь до файла конфигурации php-fpm [/etc/php-fpm.conf] | |
10487 | + --with[out]-fpm-init[=PATH] Путь до init-файла php-fpm [/etc/init.d/php-fpm] | |
10488 | + --with-fpm-log[=PATH] Путь до лог-файла php-fpm [/var/log/php-fpm.log] | |
10489 | + --with-fpm-pid[=PATH] Путь до pid-файла php-fpm [/var/run/php-fpm.pid] | |
10490 | + --with-fpm-user[=USER] Пользователь, под которым запускать php-fpm [nobody] | |
10491 | + --with-fpm-group[=GRP] Группа, под которой запускать php-fpm. Для системных | |
10492 | + пользователей задайте имя пользователя [nobody] | |
10493 | + | |
10494 | +## Установка | |
10495 | + | |
10496 | +Если вы делали `встроенную` сборку, то вы получите полный php, включая исполнитель коммандной строки `php-cli` и библиотеку PEAR. `Отдельная` или `независимая` сборка установит только демон `php-fpm` и минимум файлов, необходимых для его запуска. | |
10497 | + | |
10498 | + # Посмотреть, какие файлы будут установлены | |
10499 | + make install --dry-run | |
10500 | + | |
10501 | + # Установить в '/' | |
10502 | + sudo make install | |
10503 | + | |
10504 | + # Установить в '/opt' | |
10505 | + sudo INSTALL_ROOT=/opt make install | |
10506 | + | |
10507 | +Notes: | |
10508 | + | |
10509 | +* (Upgrade) When overwriting existing FPM installation files: A previous configuration file `php-fpm.conf` will be moved to `php-fpm.conf.old`. Then a newer (default) configuration file will be installed in it's place. If you have any custom XML settings which you wish to keep, its recommended to copy these back over manually. | |
10510 | + | |
10511 | +* (BSD) the default init.d path is `/usr/local/etc/rc.d/php-fpm` or disable: `--without-fpm-init` | |
10512 | + | |
10513 | +* (Nginx) An example nginx configuration file is generated. The file `nginx-site-conf.sample` may be installed into your nginx configuration directory, if exists: `/etc/nginx/`, `/usr/local/etc/nginx/`, or `/usr/local/nginx/conf` | |
10514 | + | |
10515 | +## Больше о процессе сборки PHP-FPM | |
10516 | + | |
10517 | +Процесс сборки можно описать так: | |
10518 | + | |
10519 | + 1) Компилируются исходники php в объектные файлы | |
10520 | + 2) Компилируются исходники fpm в объектные файлы | |
10521 | + 3) Линковка php и fpm объектных файлов | |
10522 | + 4) Результат: исполняемый php5, в основе которого php и fast-CGI от fpm как фронтэнд | |
10523 | + | |
10524 | +Fpm подмешивается в php при линковке (link-level). Андрей разделил исходный код fpm, сделав SAPI чем-то менее чуствительным к изменениям в остальном коде php. Код cgi-main.c из PHP-FPM - конктроллер запросов - вырезан из оригинального fcgi-sapi. Мы отправляем билд 0.6 в PHP Group. Мы будем отслеживать развитие PHP и периодически синхронизировать изменения с проектами встроенной / отдельной сборки. | |
10525 | + | |
10526 | +## Buildconf | |
10527 | + | |
10528 | +Для сборки fpm отдельно, конфигурирование (`./configure`) требует некоторой версии набора инструментов autoconf. Buildconf запустит `./generate-autotools` и попробует установить эти инструменты самостоятельно. Если `./buildconf` не работает, смотрите лог ошибок. | |
10529 | + | |
10530 | + | |
10531 | +## Обсуждение | |
10532 | + | |
10533 | +Есть 2 группы для обсуждения php-fpm, | |
10534 | + | |
10535 | +- [highload-php-ru](http://groups.google.com/group/highload-php-en) (english) | |
10536 | + | |
10537 | +- [highload-php-ru](http://groups.google.com/group/highload-php-ru) (русская) | |
10538 | + | |
10539 | +Translated by Anatoly Pashin |