]> git.pld-linux.org Git - packages/php.git/blame - php-fpm.patch
- shared libevent
[packages/php.git] / php-fpm.patch
CommitLineData
c6a6bfc9 1diff -Nru php-5.2.6.vanilla/configure php-5.2.6.fpm/configure
e327cc0e
ER
2diff -Nru php-5.2.6.vanilla/configure.in php-5.2.6.fpm/configure.in
3--- php-5.2.6.vanilla/configure.in 2008-04-30 22:27:55.000000000 +0400
4+++ php-5.2.6.fpm/configure.in 2008-05-01 20:42:05.000000000 +0400
5@@ -267,6 +267,12 @@
6 PTHREADS_FLAGS
fd1be940
ER
7 fi
8
e327cc0e
ER
9+if test "$PHP_FASTCGI" = "yes" -a "$PHP_FPM" = "yes"; then
10+ PHP_CONFIGURE_PART(Running FastCGI Process Manager checks)
8c0dac15
ER
11+ sinclude(sapi/cgi/fpm/acinclude.m4)
12+ sinclude(sapi/cgi/fpm/config.m4)
fd1be940
ER
13+fi
14+
e327cc0e 15 divert(3)
fd1be940 16
e327cc0e
ER
17 dnl ## In diversion 3 we check for compile-time options to the PHP
18@@ -476,6 +482,7 @@
19 alphasort \
20 asctime_r \
21 chroot \
22+clearenv \
23 ctime_r \
24 cuserid \
25 crypt \
26@@ -1197,6 +1204,8 @@
27 PHP_SUBST_OLD(EXTRA_LDFLAGS)
28 PHP_SUBST_OLD(EXTRA_LDFLAGS_PROGRAM)
29 PHP_SUBST_OLD(EXTRA_LIBS)
30+PHP_SUBST_OLD(SAPI_EXTRA_LIBS)
31+PHP_SUBST_OLD(SAPI_EXTRA_DEPS)
32 PHP_SUBST_OLD(ZEND_EXTRA_LIBS)
33 PHP_SUBST_OLD(INCLUDES)
34 PHP_SUBST_OLD(EXTRA_INCLUDES)
35@@ -1285,7 +1294,7 @@
36 install_targets="$PHP_INSTALL_CLI_TARGET $install_targets"
37 ;;
38 *)
39- install_targets="install-sapi $PHP_INSTALL_CLI_TARGET $install_targets"
40+ install_targets="install-sapi $install_fpm $PHP_INSTALL_CLI_TARGET $install_targets"
41 ;;
42 esac
fd1be940 43
e327cc0e
ER
44diff -Nru php-5.2.6.vanilla/libevent/aclocal.m4 php-5.2.6.fpm/libevent/aclocal.m4
45diff -Nru php-5.2.6.vanilla/libevent/autogen.sh php-5.2.6.fpm/libevent/autogen.sh
46diff -Nru php-5.2.6.vanilla/libevent/ChangeLog php-5.2.6.fpm/libevent/ChangeLog
47diff -Nru php-5.2.6.vanilla/libevent/compat/sys/queue.h php-5.2.6.fpm/libevent/compat/sys/queue.h
48diff -Nru php-5.2.6.vanilla/libevent/compat/sys/_time.h php-5.2.6.fpm/libevent/compat/sys/_time.h
49diff -Nru php-5.2.6.vanilla/libevent/config.guess php-5.2.6.fpm/libevent/config.guess
50diff -Nru php-5.2.6.vanilla/libevent/config.h.in php-5.2.6.fpm/libevent/config.h.in
51diff -Nru php-5.2.6.vanilla/libevent/config.sub php-5.2.6.fpm/libevent/config.sub
52diff -Nru php-5.2.6.vanilla/libevent/configure php-5.2.6.fpm/libevent/configure
53diff -Nru php-5.2.6.vanilla/libevent/configure.in php-5.2.6.fpm/libevent/configure.in
54diff -Nru php-5.2.6.vanilla/libevent/depcomp php-5.2.6.fpm/libevent/depcomp
55diff -Nru php-5.2.6.vanilla/libevent/devpoll.c php-5.2.6.fpm/libevent/devpoll.c
56diff -Nru php-5.2.6.vanilla/libevent/epoll.c php-5.2.6.fpm/libevent/epoll.c
57diff -Nru php-5.2.6.vanilla/libevent/epoll_sub.c php-5.2.6.fpm/libevent/epoll_sub.c
58diff -Nru php-5.2.6.vanilla/libevent/event.3 php-5.2.6.fpm/libevent/event.3
59diff -Nru php-5.2.6.vanilla/libevent/event.c php-5.2.6.fpm/libevent/event.c
60diff -Nru php-5.2.6.vanilla/libevent/event-config.h php-5.2.6.fpm/libevent/event-config.h
61diff -Nru php-5.2.6.vanilla/libevent/event-fpm.h php-5.2.6.fpm/libevent/event-fpm.h
62diff -Nru php-5.2.6.vanilla/libevent/event.h php-5.2.6.fpm/libevent/event.h
63diff -Nru php-5.2.6.vanilla/libevent/event-internal.h php-5.2.6.fpm/libevent/event-internal.h
64diff -Nru php-5.2.6.vanilla/libevent/evport.c php-5.2.6.fpm/libevent/evport.c
65diff -Nru php-5.2.6.vanilla/libevent/evsignal.h php-5.2.6.fpm/libevent/evsignal.h
66diff -Nru php-5.2.6.vanilla/libevent/evutil.c php-5.2.6.fpm/libevent/evutil.c
67diff -Nru php-5.2.6.vanilla/libevent/evutil.h php-5.2.6.fpm/libevent/evutil.h
68diff -Nru php-5.2.6.vanilla/libevent/install-sh php-5.2.6.fpm/libevent/install-sh
69diff -Nru php-5.2.6.vanilla/libevent/kqueue.c php-5.2.6.fpm/libevent/kqueue.c
70diff -Nru php-5.2.6.vanilla/libevent/log.c php-5.2.6.fpm/libevent/log.c
71diff -Nru php-5.2.6.vanilla/libevent/log.h php-5.2.6.fpm/libevent/log.h
72diff -Nru php-5.2.6.vanilla/libevent/Makefile.am php-5.2.6.fpm/libevent/Makefile.am
73diff -Nru php-5.2.6.vanilla/libevent/Makefile.in php-5.2.6.fpm/libevent/Makefile.in
c6a6bfc9 74diff -Nru php-5.2.6.vanilla/libevent/min_heap.h php-5.2.6.fpm/libevent/min_heap.h
c6a6bfc9 75diff -Nru php-5.2.6.vanilla/libevent/missing php-5.2.6.fpm/libevent/missing
c6a6bfc9 76diff -Nru php-5.2.6.vanilla/libevent/mkinstalldirs php-5.2.6.fpm/libevent/mkinstalldirs
c6a6bfc9 77diff -Nru php-5.2.6.vanilla/libevent/poll.c php-5.2.6.fpm/libevent/poll.c
c6a6bfc9 78diff -Nru php-5.2.6.vanilla/libevent/README php-5.2.6.fpm/libevent/README
c6a6bfc9 79diff -Nru php-5.2.6.vanilla/libevent/select.c php-5.2.6.fpm/libevent/select.c
c6a6bfc9 80diff -Nru php-5.2.6.vanilla/libevent/signal.c php-5.2.6.fpm/libevent/signal.c
c6a6bfc9
ER
81diff -Nru php-5.2.6.vanilla/main/php_config.h.in php-5.2.6.fpm/main/php_config.h.in
82--- php-5.2.6.vanilla/main/php_config.h.in 2008-04-30 22:37:39.000000000 +0400
83+++ php-5.2.6.fpm/main/php_config.h.in 2008-09-21 17:37:45.000000000 +0400
fd1be940
ER
84@@ -170,6 +170,9 @@
85 /* Define if you have the chroot function. */
86 #undef HAVE_CHROOT
87
88+/* Define if you have the clearenv function. */
89+#undef HAVE_CLEARENV
90+
91 /* Define if you have the crypt function. */
92 #undef HAVE_CRYPT
93
94@@ -929,6 +932,9 @@
95 /* */
96 #undef PHP_FASTCGI
97
98+/* Is experimental fastcgi process manager code activated */
99+#undef PHP_FASTCGI_PM
100+
101 /* */
102 #undef FORCE_CGI_REDIRECT
103
c6a6bfc9 104@@ -938,6 +944,27 @@
fd1be940
ER
105 /* */
106 #undef ENABLE_PATHINFO_CHECK
107
108+/* do we have libxml? */
109+#undef HAVE_LIBXML
c6a6bfc9
ER
110+
111+/* do we have prctl? */
112+#undef HAVE_PRCTL
113+
114+/* do we have clock_gettime? */
115+#undef HAVE_CLOCK_GETTIME
116+
117+/* do we have clock_get_time? */
118+#undef HAVE_CLOCK_GET_TIME
119+
120+/* do we have ptrace? */
121+#undef HAVE_PTRACE
122+
123+/* do we have mach_vm_read? */
124+#undef HAVE_MACH_VM_READ
125+
126+/* /proc/pid/mem interface */
127+#undef PROC_MEM_FILE
fd1be940
ER
128+
129 /* Define if system uses EBCDIC */
130 #undef CHARSET_EBCDIC
131
8c0dac15
ER
132diff -Nru php-5.2.6.vanilla/sapi/cgi/cgi_main.c php-5.2.6.fpm/sapi/cgi/cgi_main.c
133--- php-5.2.6.vanilla/sapi/cgi/cgi_main.c 2008-04-09 13:16:40.000000000 +0400
134+++ php-5.2.6.fpm/sapi/cgi/cgi_main.c 2008-07-22 01:50:58.000000000 +0400
fd1be940
ER
135@@ -55,6 +55,9 @@
136 #if HAVE_SYS_WAIT_H
137 #include <sys/wait.h>
138 #endif
139+#if HAVE_FCNTL_H
140+#include <fcntl.h>
141+#endif
142 #include "zend.h"
143 #include "zend_extensions.h"
144 #include "php_ini.h"
c6a6bfc9 145@@ -83,6 +86,11 @@
fd1be940
ER
146 #if PHP_FASTCGI
147 #include "fastcgi.h"
148
149+#if PHP_FASTCGI_PM
150+#include "fpm/fpm.h"
c6a6bfc9 151+#include "fpm/fpm_request.h"
fd1be940
ER
152+#endif
153+
154 #ifndef PHP_WIN32
155 /* XXX this will need to change later when threaded fastcgi is
156 implemented. shane */
c6a6bfc9 157@@ -109,8 +117,12 @@
fd1be940
ER
158 static pid_t pgroup;
159 #endif
160
161+static int request_body_fd;
162+
163 #endif
164
165+static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC);
166+
167 #define PHP_MODE_STANDARD 1
168 #define PHP_MODE_HIGHLIGHT 2
169 #define PHP_MODE_INDENT 3
c6a6bfc9 170@@ -140,6 +152,10 @@
fd1be940
ER
171 {'w', 0, "strip"},
172 {'?', 0, "usage"},/* help alias (both '?' and 'usage') */
173 {'v', 0, "version"},
174+#if PHP_FASTCGI_PM
175+ {'x', 0, "fpm"},
176+ {'y', 1, "fpm-config"},
177+#endif
178 {'z', 1, "zend-extension"},
c6a6bfc9
ER
179 #if PHP_FASTCGI
180 {'T', 1, "timing"},
181@@ -164,6 +180,7 @@
fd1be940
ER
182 zend_bool impersonate;
183 # endif
fd1be940 184 #endif
c6a6bfc9 185+ char *error_header;
fd1be940
ER
186 } php_cgi_globals_struct;
187
c6a6bfc9
ER
188 #ifdef ZTS
189@@ -444,7 +461,28 @@
fd1be940
ER
190 #if PHP_FASTCGI
191 if (fcgi_is_fastcgi()) {
192 fcgi_request *request = (fcgi_request*) SG(server_context);
193- tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
194+
195+ if (request_body_fd == -1) {
c6a6bfc9
ER
196+ char *request_body_filename = sapi_cgibin_getenv((char *) "REQUEST_BODY_FILE",
197+ sizeof("REQUEST_BODY_FILE")-1 TSRMLS_CC);
198+
fd1be940
ER
199+ if (request_body_filename && *request_body_filename) {
200+ request_body_fd = open(request_body_filename, O_RDONLY);
c6a6bfc9
ER
201+
202+ if (0 > request_body_fd) {
203+ php_error(E_WARNING, "REQUEST_BODY_FILE: open('%s') failed: %s (%d)",
204+ request_body_filename, strerror(errno), errno);
205+ return 0;
206+ }
fd1be940
ER
207+ }
208+ }
209+
210+ /* If REQUEST_BODY_FILE variable not available - read post body from fastcgi stream */
fd1be940
ER
211+ if (request_body_fd < 0) {
212+ tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
213+ } else {
214+ tmp_read_bytes = read(request_body_fd, buffer + read_bytes, count_bytes - read_bytes);
215+ }
216 } else {
217 tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes);
218 }
c6a6bfc9 219@@ -756,7 +794,12 @@
fd1be940
ER
220 " -s Display colour syntax highlighted source.\n"
221 " -v Version number\n"
222 " -w Display source with stripped comments and whitespace.\n"
c6a6bfc9 223- " -z <file> Load Zend extension <file>.\n"
fd1be940
ER
224+#if PHP_FASTCGI_PM
225+ " -x, --fpm Run in FastCGI process manager mode.\n"
226+ " -y, --fpm-config <file>\n"
227+ " Specify alternative path to FastCGI process manager config file.\n"
228+#endif
c6a6bfc9
ER
229+ " -z <file> Load Zend extension <file>.\n"
230 #if PHP_FASTCGI
231 " -T <count> Measure execution time of script repeated <count> times.\n"
232 #endif
233@@ -1173,6 +1216,7 @@
fd1be940
ER
234 # ifdef PHP_WIN32
235 STD_PHP_INI_ENTRY("fastcgi.impersonate", "0", PHP_INI_SYSTEM, OnUpdateBool, impersonate, php_cgi_globals_struct, php_cgi_globals)
236 # endif
237+ STD_PHP_INI_ENTRY("fastcgi.error_header", NULL, PHP_INI_SYSTEM, OnUpdateString, error_header, php_cgi_globals_struct, php_cgi_globals)
238 #endif
239 PHP_INI_END()
240
c6a6bfc9 241@@ -1195,6 +1239,7 @@
fd1be940
ER
242 # ifdef PHP_WIN32
243 php_cgi_globals->impersonate = 0;
244 # endif
245+ php_cgi_globals->error_header = NULL;
246 #endif
247 }
248 /* }}} */
c6a6bfc9
ER
249@@ -1227,9 +1272,47 @@
250 static PHP_MINFO_FUNCTION(cgi)
251 {
252 DISPLAY_INI_ENTRIES();
253+
254+#if PHP_FASTCGI_PM
255+
256+#include "fpm/fpm_autoconf.h"
257+
258+ php_info_print_table_start();
259+ php_info_print_table_row(2, "php-fpm", fpm ? "active" : "inactive");
260+ php_info_print_table_row(2, "php-fpm version", PHP_FPM_VERSION);
261+ php_info_print_table_end();
262+#endif
263+
fd1be940
ER
264 }
265 /* }}} */
266
267+#if PHP_FASTCGI
268+PHP_FUNCTION(fastcgi_finish_request)
269+{
270+ fcgi_request *request = (fcgi_request*) SG(server_context);
271+
272+ if (fcgi_is_fastcgi() && request->fd >= 0) {
273+
274+ php_end_ob_buffers(1 TSRMLS_CC);
275+ php_header(TSRMLS_C);
276+
277+ fcgi_flush(request, 1);
278+ fcgi_close(request, 0, 0);
279+ RETURN_TRUE;
280+ }
281+
282+ RETURN_FALSE;
283+
284+}
285+#endif
286+
287+function_entry cgi_fcgi_sapi_functions[] = {
288+#if PHP_FASTCGI
289+ PHP_FE(fastcgi_finish_request, NULL)
290+#endif
291+ {NULL, NULL, NULL}
292+};
293+
294 static zend_module_entry cgi_module_entry = {
295 STANDARD_MODULE_HEADER,
296 #if PHP_FASTCGI
c6a6bfc9 297@@ -1237,7 +1320,7 @@
fd1be940
ER
298 #else
299 "cgi",
300 #endif
301- NULL,
302+ cgi_fcgi_sapi_functions,
303 PHP_MINIT(cgi),
304 PHP_MSHUTDOWN(cgi),
305 NULL,
c6a6bfc9 306@@ -1277,6 +1360,7 @@
fd1be940
ER
307 char *bindpath = NULL;
308 int fcgi_fd = 0;
309 fcgi_request request;
fd1be940 310+ char *fpm_config = NULL;
c6a6bfc9
ER
311 int repeats = 1;
312 int benchmark = 0;
313 #if HAVE_GETTIMEOFDAY
314@@ -1397,6 +1481,14 @@
fd1be940
ER
315 case 's': /* generate highlighted HTML from source */
316 behavior = PHP_MODE_HIGHLIGHT;
317 break;
318+#if PHP_FASTCGI_PM
319+ case 'y':
320+ fpm_config = php_optarg;
321+ break;
322+ case 'x':
323+ fpm = 1;
324+ break;
325+#endif
326
327 }
328
c6a6bfc9 329@@ -1459,6 +1551,19 @@
fd1be940
ER
330 #endif /* FORCE_CGI_REDIRECT */
331
332 #if PHP_FASTCGI
333+#if PHP_FASTCGI_PM
334+ if (fpm) {
335+ if (0 > fpm_init(argc, argv, fpm_config)) {
336+ return FAILURE;
337+ }
338+
339+ fcgi_fd = fpm_run(&max_requests);
340+
341+ fcgi_set_is_fastcgi(fastcgi = 1);
342+ }
343+ else
344+#endif
345+
346 if (bindpath) {
347 fcgi_fd = fcgi_listen(bindpath, 128);
348 if (fcgi_fd < 0) {
c6a6bfc9 349@@ -1473,7 +1578,7 @@
fd1be940
ER
350
351 if (fastcgi) {
352 /* How many times to run PHP scripts before dying */
353- if (getenv("PHP_FCGI_MAX_REQUESTS")) {
354+ if (!fpm && getenv("PHP_FCGI_MAX_REQUESTS")) {
355 max_requests = atoi(getenv("PHP_FCGI_MAX_REQUESTS"));
356 if (max_requests < 0) {
357 fprintf(stderr, "PHP_FCGI_MAX_REQUESTS is not valid\n");
c6a6bfc9 358@@ -1490,7 +1595,7 @@
fd1be940
ER
359
360 #ifndef PHP_WIN32
361 /* Pre-fork, if required */
362- if (getenv("PHP_FCGI_CHILDREN")) {
363+ if (!fpm && getenv("PHP_FCGI_CHILDREN")) {
364 children = atoi(getenv("PHP_FCGI_CHILDREN"));
365 if (children < 0) {
366 fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
c6a6bfc9 367@@ -1616,6 +1721,8 @@
fd1be940
ER
368 #endif
369
370 #if PHP_FASTCGI
371+ request_body_fd = -1;
372+
373 SG(server_context) = (void *) &request;
374 #else
375 SG(server_context) = (void *) 1; /* avoid server_context==NULL checks */
c6a6bfc9
ER
376@@ -1623,6 +1730,10 @@
377 init_request_info(TSRMLS_C);
378 CG(interactive) = 0;
379
380+#if PHP_FASTCGI_PM
381+ if (fpm) fpm_request_info();
382+#endif
383+
384 if (!cgi
385 #if PHP_FASTCGI
386 && !fastcgi
387@@ -1914,6 +2025,10 @@
388 }
389 }
390
391+#if PHP_FASTCGI_PM
392+ if (fpm) fpm_request_executing();
393+#endif
394+
395 switch (behavior) {
396 case PHP_MODE_STANDARD:
397 php_execute_script(&file_handle TSRMLS_CC);
398@@ -1966,6 +2081,10 @@
fd1be940
ER
399
400 #if PHP_FASTCGI
401 fastcgi_request_done:
402+
403+ if (request_body_fd != -1) close(request_body_fd);
404+
405+ request_body_fd = -2;
406 #endif
407 {
408 char *path_translated;
c6a6bfc9 409@@ -1979,6 +2098,16 @@
fd1be940
ER
410 SG(request_info).path_translated = path_translated;
411 }
412
413+ if (EG(exit_status) == 255) {
414+ if (CGIG(error_header) && *CGIG(error_header)) {
415+ sapi_header_line ctr = {0};
416+
417+ ctr.line = CGIG(error_header);
418+ ctr.line_len = strlen(CGIG(error_header));
419+ sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
420+ }
421+ }
422+
423 php_request_shutdown((void *) 0);
424 if (exit_status == 0) {
425 exit_status = EG(exit_status);
c6a6bfc9
ER
426@@ -2016,15 +2145,20 @@
427 if (bindpath) {
428 free(bindpath);
429 }
430- if (max_requests != 1) {
431- /* no need to return exit_status of the last request */
432- exit_status = 0;
433- }
434 break;
fd1be940 435 }
c6a6bfc9
ER
436 /* end of fastcgi loop */
437 }
438 fcgi_shutdown();
fd1be940 439+
c6a6bfc9
ER
440+ if (fcgi_in_shutdown() || /* graceful shutdown by a signal */
441+ (max_requests && (requests == max_requests)) /* we were told to process max_requests and we are done */
442+ ) {
443+ exit_status = 0;
444+ }
445+ else {
446+ exit_status = 255;
447+ }
448 #endif
449
450 if (cgi_sapi_module.php_ini_path_override) {
8c0dac15
ER
451diff -Nru php-5.2.6.vanilla/sapi/cgi/config9.m4 php-5.2.6.fpm/sapi/cgi/config9.m4
452--- php-5.2.6.vanilla/sapi/cgi/config9.m4 2007-07-12 03:20:36.000000000 +0400
453+++ php-5.2.6.fpm/sapi/cgi/config9.m4 2008-07-20 20:46:41.000000000 +0400
fd1be940
ER
454@@ -22,6 +22,10 @@
455 [ --disable-path-info-check CGI: If this is disabled, paths such as
456 /info.php/test?a=b will fail to work], yes, no)
457
458+PHP_ARG_ENABLE(fpm,,
459+[ --enable-fpm FastCGI: If this is enabled, the fastcgi support
460+ will include experimental process manager code], no, no)
461+
462 dnl
463 dnl CGI setup
464 dnl
465@@ -54,6 +58,20 @@
466 AC_DEFINE_UNQUOTED(PHP_FASTCGI, $PHP_ENABLE_FASTCGI, [ ])
467 AC_MSG_RESULT($PHP_FASTCGI)
468
469+ dnl --enable-fpm
470+ if test "$PHP_FASTCGI" = "yes"; then
c6a6bfc9 471+ AC_MSG_CHECKING(whether to enable FastCGI Process Manager)
fd1be940
ER
472+ if test "$PHP_FPM" = "yes"; then
473+ PHP_FASTCGI_PM=1
474+ else
475+ PHP_FASTCGI_PM=0
476+ fi
477+ AC_MSG_RESULT($PHP_FPM)
478+ else
479+ PHP_FASTCGI_PM=0
480+ fi
481+ AC_DEFINE_UNQUOTED(PHP_FASTCGI_PM, $PHP_FASTCGI_PM, [Is experimental fastcgi process manager code activated])
482+
483 dnl --enable-force-cgi-redirect
484 AC_MSG_CHECKING(whether to force Apache CGI redirect)
485 if test "$PHP_FORCE_CGI_REDIRECT" = "yes"; then
75ddaf45
ER
486@@ -108,13 +108,13 @@
487
488 case $host_alias in
489 *aix*)
490- BUILD_CGI="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) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
491+ BUILD_CGI="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_CGI_PATH)"
fd1be940
ER
492 ;;
493 *darwin*)
75ddaf45
ER
494- BUILD_CGI="\$(CC) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_SAPI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
495+ BUILD_CGI="\$(CC) \$(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_CGI_PATH)"
fd1be940
ER
496 ;;
497 *)
75ddaf45
ER
498- BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) libphp_common.la \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
499+ BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) libphp_common.la \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
fd1be940
ER
500 ;;
501 esac
502
8c0dac15
ER
503diff -Nru php-5.2.6.vanilla/sapi/cgi/fastcgi.c php-5.2.6.fpm/sapi/cgi/fastcgi.c
504--- php-5.2.6.vanilla/sapi/cgi/fastcgi.c 2008-04-03 14:24:44.000000000 +0400
505+++ php-5.2.6.fpm/sapi/cgi/fastcgi.c 2008-05-15 23:37:01.000000000 +0400
c6a6bfc9
ER
506@@ -27,6 +27,11 @@
507 #include <stdarg.h>
508 #include <errno.h>
509
510+#if PHP_FASTCGI_PM
511+#include "fpm/fpm.h"
512+#include "fpm/fpm_request.h"
513+#endif
514+
515 #ifdef _WIN32
516
517 #include <windows.h>
518@@ -240,6 +245,8 @@
fd1be940
ER
519 } else {
520 return is_fastcgi = 0;
521 }
522+
523+ fcgi_set_allowed_clients(getenv("FCGI_WEB_SERVER_ADDRS"));
524 #endif
525 }
526 return is_fastcgi;
c6a6bfc9 527@@ -255,9 +262,24 @@
fd1be940
ER
528 }
529 }
530
531+void fcgi_set_is_fastcgi(int new_value)
532+{
533+ is_fastcgi = new_value;
534+}
c6a6bfc9
ER
535+
536+void fcgi_set_in_shutdown(int new_value)
537+{
538+ in_shutdown = new_value;
539+}
fd1be940
ER
540+
541 void fcgi_shutdown(void)
542 {
543 is_fastcgi = 0;
544+
545+ if (allowed_clients) {
546+ free(allowed_clients);
547+ allowed_clients = 0;
548+ }
549 }
550
551 #ifdef _WIN32
c6a6bfc9 552@@ -330,6 +352,41 @@
fd1be940
ER
553 }
554 #endif
555
556+void fcgi_set_allowed_clients(char *ip)
557+{
558+ char *cur, *end;
559+ int n;
560+
561+ if (ip) {
562+ ip = strdup(ip);
563+ cur = ip;
564+ n = 0;
565+ while (*cur) {
566+ if (*cur == ',') n++;
567+ cur++;
568+ }
569+ if (allowed_clients) free(allowed_clients);
570+ allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
571+ n = 0;
572+ cur = ip;
573+ while (cur) {
574+ end = strchr(cur, ',');
575+ if (end) {
576+ *end = 0;
577+ end++;
578+ }
579+ allowed_clients[n] = inet_addr(cur);
580+ if (allowed_clients[n] == INADDR_NONE) {
581+ fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur);
582+ }
583+ n++;
584+ cur = end;
585+ }
586+ allowed_clients[n] = INADDR_NONE;
587+ free(ip);
588+ }
589+}
590+
591 static int is_port_number(const char *bindpath)
592 {
593 while (*bindpath) {
c6a6bfc9 594@@ -458,38 +515,6 @@
fd1be940
ER
595
596 if (!tcp) {
597 chmod(path, 0777);
598- } else {
599- char *ip = getenv("FCGI_WEB_SERVER_ADDRS");
600- char *cur, *end;
601- int n;
602-
603- if (ip) {
604- ip = strdup(ip);
605- cur = ip;
606- n = 0;
607- while (*cur) {
608- if (*cur == ',') n++;
609- cur++;
610- }
611- allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
612- n = 0;
613- cur = ip;
614- while (cur) {
615- end = strchr(cur, ',');
616- if (end) {
617- *end = 0;
618- end++;
619- }
620- allowed_clients[n] = inet_addr(cur);
621- if (allowed_clients[n] == INADDR_NONE) {
622- fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur);
623- }
624- n++;
625- cur = end;
626- }
627- allowed_clients[n] = INADDR_NONE;
628- free(ip);
629- }
630 }
631
632 if (!is_initialized) {
c6a6bfc9 633@@ -829,7 +854,7 @@
fd1be940
ER
634 return n;
635 }
636
637-static inline void fcgi_close(fcgi_request *req, int force, int destroy)
638+void fcgi_close(fcgi_request *req, int force, int destroy)
639 {
640 if (destroy) {
641 zend_hash_destroy(&req->env);
c6a6bfc9
ER
642@@ -869,6 +894,10 @@
643 close(req->fd);
644 #endif
645 req->fd = -1;
646+
647+#if PHP_FASTCGI_PM
648+ if (fpm) fpm_request_finished();
649+#endif
650 }
651 }
652
653@@ -916,6 +945,10 @@
654 sa_t sa;
655 socklen_t len = sizeof(sa);
656
657+#if PHP_FASTCGI_PM
658+ if (fpm) fpm_request_accepting();
659+#endif
660+
661 FCGI_LOCK(req->listen_socket);
662 req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
663 FCGI_UNLOCK(req->listen_socket);
664@@ -951,6 +984,11 @@
665 break;
666 #else
667 if (req->fd >= 0) {
668+
669+#if PHP_FASTCGI_PM
670+ if (fpm) fpm_request_reading_headers();
671+#endif
672+
673 #if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
674 struct pollfd fds;
675 int ret;
8c0dac15
ER
676diff -Nru php-5.2.6.vanilla/sapi/cgi/fastcgi.h php-5.2.6.fpm/sapi/cgi/fastcgi.h
677--- php-5.2.6.vanilla/sapi/cgi/fastcgi.h 2007-12-31 10:20:16.000000000 +0300
678+++ php-5.2.6.fpm/sapi/cgi/fastcgi.h 2008-05-01 20:42:06.000000000 +0400
c6a6bfc9 679@@ -114,6 +114,9 @@
fd1be940
ER
680 int fcgi_init(void);
681 void fcgi_shutdown(void);
682 int fcgi_is_fastcgi(void);
683+void fcgi_set_is_fastcgi(int);
c6a6bfc9 684+void fcgi_set_in_shutdown(int);
fd1be940
ER
685+void fcgi_set_allowed_clients(char *);
686 int fcgi_in_shutdown(void);
687 int fcgi_listen(const char *path, int backlog);
688 void fcgi_init_request(fcgi_request *req, int listen_socket);
c6a6bfc9 689@@ -128,6 +131,8 @@
fd1be940
ER
690 int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len);
691 int fcgi_flush(fcgi_request *req, int close);
692
693+void fcgi_close(fcgi_request *req, int force, int destroy);
694+
695 #ifdef PHP_WIN32
696 void fcgi_impersonate(void);
697 #endif
8c0dac15
ER
698diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/acinclude.m4 php-5.2.6.fpm/sapi/cgi/fpm/acinclude.m4
699--- php-5.2.6.vanilla/sapi/cgi/fpm/acinclude.m4 1970-01-01 03:00:00.000000000 +0300
700+++ php-5.2.6.fpm/sapi/cgi/fpm/acinclude.m4 2008-07-21 06:39:38.000000000 +0400
c6a6bfc9 701@@ -0,0 +1,383 @@
fd1be940
ER
702+
703+AC_DEFUN([AC_FPM_CHECK_FUNC],
704+[
705+ SAVED_CFLAGS="$CFLAGS"
706+ CFLAGS="$CFLAGS $2"
707+ SAVED_LIBS="$LIBS"
708+ LIBS="$LIBS $3"
709+
710+ AC_CHECK_FUNC([$1],[$4],[$5])
711+
712+ CFLAGS="$SAVED_CFLAGS"
713+ LIBS="$SAVED_LIBS"
714+])
715+
716+AC_DEFUN([AC_FPM_LIBEVENT],
717+[
718+ AC_ARG_WITH([libevent],
719+ [ --with-libevent=DIR FPM: libevent install directory])
720+
721+ LIBEVENT_CFLAGS=""
722+ LIBEVENT_LIBS="-levent"
723+ LIBEVENT_INCLUDE_PATH=""
724+
725+ if test "$with_libevent" != "no" -a -n "$with_libevent"; then
726+ LIBEVENT_CFLAGS="-I$with_libevent/include"
727+ LIBEVENT_LIBS="-L$with_libevent/lib $LIBEVENT_LIBS"
728+ LIBEVENT_INCLUDE_PATH="$with_libevent/include"
729+ fi
730+
731+ AC_MSG_CHECKING([for event.h])
732+
733+ found=no
734+
735+ for dir in "$LIBEVENT_INCLUDE_PATH" /usr/include ; do
c6a6bfc9 736+ if test -r "$dir/event.h" ; then
fd1be940
ER
737+ found=yes
738+ break
739+ fi
740+ done
741+
742+ AC_MSG_RESULT([$found])
743+
744+ AC_FPM_CHECK_FUNC([event_set], [$LIBEVENT_CFLAGS], [$LIBEVENT_LIBS], ,
745+ [AC_MSG_ERROR([Failed to link with libevent. Perhaps --with-libevent=DIR option could help.])])
746+
747+ AC_FPM_CHECK_FUNC([event_base_free], [$LIBEVENT_CFLAGS], [$LIBEVENT_LIBS], ,
748+ [AC_MSG_ERROR([You have too old version. libevent version >= 1.2 is required.])])
749+
750+])
751+
752+AC_DEFUN([AC_FPM_LIBXML],
753+[
754+ AC_MSG_RESULT([checking for XML configuration])
755+
756+ AC_ARG_WITH(xml-config,
757+ [ --with-xml-config=PATH FPM: use xml-config in PATH to find libxml],
758+ [XMLCONFIG="$withval"],
759+ [AC_PATH_PROGS(XMLCONFIG, [xml2-config xml-config], "")]
760+ )
761+
762+ if test "x$XMLCONFIG" = "x"; then
763+ AC_MSG_ERROR([XML configuration could not be found])
764+ else
765+ AC_MSG_CHECKING([for libxml library])
766+
767+ if test ! -x "$XMLCONFIG"; then
768+ AC_MSG_ERROR([$XMLCONFIG cannot be executed])
769+ fi
770+
771+ LIBXML_LIBS="`$XMLCONFIG --libs`"
772+ LIBXML_CFLAGS="`$XMLCONFIG --cflags`"
773+ LIBXML_VERSION="`$XMLCONFIG --version`"
774+
775+ AC_MSG_RESULT([yes, $LIBXML_VERSION])
776+
777+ AC_FPM_CHECK_FUNC([xmlParseFile], [$LIBXML_CFLAGS], [$LIBXML_LIBS], ,
778+ [AC_MSG_ERROR([Failed to link with libxml])])
779+
780+ AC_DEFINE(HAVE_LIBXML, 1, [do we have libxml?])
781+ fi
782+])
783+
784+AC_DEFUN([AC_FPM_JUDY],
785+[
786+ AC_ARG_WITH([Judy],
787+ [ --with-Judy=DIR FPM: Judy install directory])
788+
789+ JUDY_CFLAGS=""
790+ JUDY_LIBS="-lJudy"
791+ JUDY_INCLUDE_PATH=""
792+
793+ if test "$with_Judy" != "no" -a -n "$with_Judy"; then
794+ JUDY_INCLUDE_PATH="$with_Judy/include"
795+ JUDY_CFLAGS="-I$with_Judy/include $JUDY_CFLAGS"
796+ JUDY_LIBS="-L$with_Judy/lib $JUDY_LIBS"
797+ fi
798+
799+ AC_MSG_CHECKING([for Judy.h])
800+
801+ found=no
802+
803+ for dir in "$JUDY_INCLUDE_PATH" /usr/include ; do
c6a6bfc9 804+ if test -r "$dir/Judy.h" ; then
fd1be940
ER
805+ found=yes
806+ break
807+ fi
808+ done
809+
810+ AC_MSG_RESULT([$found])
811+
812+ AC_FPM_CHECK_FUNC([JudyLCount], [$JUDY_CFLAGS], [$JUDY_LIBS], ,
813+ [AC_MSG_ERROR([Failed to link with Judy])])
814+
815+])
816+
c6a6bfc9
ER
817+AC_DEFUN([AC_FPM_CLOCK],
818+[
819+ have_clock_gettime=no
820+
821+ AC_MSG_CHECKING([for clock_gettime])
822+
823+ AC_TRY_COMPILE([ #include <time.h> ], [struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);], [
824+ have_clock_gettime=yes
825+ AC_MSG_RESULT([yes])
826+ ], [
827+ AC_MSG_RESULT([no])
828+ ])
829+
830+ if test "$have_clock_gettime" = "no"; then
831+ AC_MSG_CHECKING([for clock_gettime in -lrt])
832+
833+ SAVED_LIBS="$LIBS"
834+ LIBS="$LIBS -lrt"
835+
836+ AC_TRY_COMPILE([ #include <time.h> ], [struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);], [
837+ have_clock_gettime=yes
838+ AC_MSG_RESULT([yes])
839+ ], [
840+ LIBS="$SAVED_LIBS"
841+ AC_MSG_RESULT([no])
842+ ])
843+ fi
844+
845+ if test "$have_clock_gettime" = "yes"; then
846+ AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [do we have clock_gettime?])
847+ fi
848+
849+ have_clock_get_time=no
850+
851+ if test "$have_clock_gettime" = "no"; then
852+ AC_MSG_CHECKING([for clock_get_time])
853+
854+ AC_TRY_RUN([ #include <mach/mach.h>
855+ #include <mach/clock.h>
856+ #include <mach/mach_error.h>
857+
858+ int main()
859+ {
860+ kern_return_t ret; clock_serv_t aClock; mach_timespec_t aTime;
861+ ret = host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &aClock);
862+
863+ if (ret != KERN_SUCCESS) {
864+ return 1;
865+ }
866+
867+ ret = clock_get_time(aClock, &aTime);
868+ if (ret != KERN_SUCCESS) {
869+ return 2;
870+ }
871+
872+ return 0;
873+ }
874+ ], [
875+ have_clock_get_time=yes
876+ AC_MSG_RESULT([yes])
877+ ], [
878+ AC_MSG_RESULT([no])
879+ ])
880+ fi
881+
882+ if test "$have_clock_get_time" = "yes"; then
883+ AC_DEFINE([HAVE_CLOCK_GET_TIME], 1, [do we have clock_get_time?])
884+ fi
885+])
886+
887+AC_DEFUN([AC_FPM_TRACE],
888+[
889+ have_ptrace=no
890+ have_broken_ptrace=no
891+
892+ AC_MSG_CHECKING([for ptrace])
893+
894+ AC_TRY_COMPILE([
895+ #include <sys/types.h>
896+ #include <sys/ptrace.h> ], [ptrace(0, 0, (void *) 0, 0);], [
897+ have_ptrace=yes
898+ AC_MSG_RESULT([yes])
899+ ], [
900+ AC_MSG_RESULT([no])
901+ ])
902+
903+ if test "$have_ptrace" = "yes"; then
904+ AC_MSG_CHECKING([whether ptrace works])
905+
906+ AC_TRY_RUN([
907+ #include <unistd.h>
908+ #include <signal.h>
909+ #include <sys/wait.h>
910+ #include <sys/types.h>
911+ #include <sys/ptrace.h>
912+ #include <errno.h>
913+
914+ #if !defined(PTRACE_ATTACH) && defined(PT_ATTACH)
915+ #define PTRACE_ATTACH PT_ATTACH
916+ #endif
917+
918+ #if !defined(PTRACE_DETACH) && defined(PT_DETACH)
919+ #define PTRACE_DETACH PT_DETACH
920+ #endif
921+
922+ #if !defined(PTRACE_PEEKDATA) && defined(PT_READ_D)
923+ #define PTRACE_PEEKDATA PT_READ_D
924+ #endif
925+
926+ int main()
927+ {
928+ long v1 = (unsigned int) -1; /* copy will fail if sizeof(long) == 8 and we've got "int ptrace()" */
929+ long v2;
930+ pid_t child;
931+ int status;
932+
933+ if ( (child = fork()) ) { /* parent */
934+ int ret = 0;
935+
936+ if (0 > ptrace(PTRACE_ATTACH, child, 0, 0)) {
937+ return 1;
938+ }
939+
940+ waitpid(child, &status, 0);
941+
942+ #ifdef PT_IO
943+ struct ptrace_io_desc ptio = {
944+ .piod_op = PIOD_READ_D,
945+ .piod_offs = &v1,
946+ .piod_addr = &v2,
947+ .piod_len = sizeof(v1)
948+ };
949+
950+ if (0 > ptrace(PT_IO, child, (void *) &ptio, 0)) {
951+ ret = 1;
952+ }
953+ #else
954+ errno = 0;
955+
956+ v2 = ptrace(PTRACE_PEEKDATA, child, (void *) &v1, 0);
957+
958+ if (errno) {
959+ ret = 1;
960+ }
961+ #endif
962+ ptrace(PTRACE_DETACH, child, (void *) 1, 0);
963+
964+ kill(child, SIGKILL);
965+
966+ return ret ? ret : (v1 != v2);
967+ }
968+ else { /* child */
969+ sleep(10);
970+ return 0;
971+ }
972+ }
973+ ], [
974+ AC_MSG_RESULT([yes])
975+ ], [
976+ have_ptrace=no
977+ have_broken_ptrace=yes
978+ AC_MSG_RESULT([no])
979+ ])
980+ fi
981+
982+ if test "$have_ptrace" = "yes"; then
983+ AC_DEFINE([HAVE_PTRACE], 1, [do we have ptrace?])
984+ fi
985+
986+ have_mach_vm_read=no
987+
988+ if test "$have_broken_ptrace" = "yes"; then
989+ AC_MSG_CHECKING([for mach_vm_read])
990+
991+ AC_TRY_COMPILE([ #include <mach/mach.h>
992+ #include <mach/mach_vm.h>
993+ ], [
994+ 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);
995+ ], [
996+ have_mach_vm_read=yes
997+ AC_MSG_RESULT([yes])
998+ ], [
999+ AC_MSG_RESULT([no])
1000+ ])
1001+ fi
1002+
1003+ if test "$have_mach_vm_read" = "yes"; then
1004+ AC_DEFINE([HAVE_MACH_VM_READ], 1, [do we have mach_vm_read?])
1005+ fi
1006+
1007+ proc_mem_file=""
1008+
1009+ if test -r /proc/$$/mem ; then
1010+ proc_mem_file="mem"
1011+ else
1012+ if test -r /proc/$$/as ; then
1013+ proc_mem_file="as"
1014+ fi
1015+ fi
1016+
1017+ if test -n "$proc_mem_file" ; then
1018+ AC_MSG_CHECKING([for proc mem file])
1019+
1020+ AC_TRY_RUN([
1021+ #define _GNU_SOURCE
1022+ #define _FILE_OFFSET_BITS 64
1023+ #include <stdint.h>
1024+ #include <unistd.h>
1025+ #include <sys/types.h>
1026+ #include <sys/stat.h>
1027+ #include <fcntl.h>
1028+ #include <stdio.h>
1029+ int main()
1030+ {
1031+ long v1 = (unsigned int) -1, v2 = 0;
1032+ char buf[128];
1033+ int fd;
1034+ sprintf(buf, "/proc/%d/$proc_mem_file", getpid());
1035+ fd = open(buf, O_RDONLY);
1036+ if (0 > fd) {
1037+ return 1;
1038+ }
1039+ if (sizeof(long) != pread(fd, &v2, sizeof(long), (uintptr_t) &v1)) {
1040+ close(fd);
1041+ return 1;
1042+ }
1043+ close(fd);
1044+ return v1 != v2;
1045+ }
1046+ ], [
1047+ AC_MSG_RESULT([$proc_mem_file])
1048+ ], [
1049+ proc_mem_file=""
1050+ AC_MSG_RESULT([no])
1051+ ])
1052+ fi
1053+
1054+ if test -n "$proc_mem_file"; then
1055+ AC_DEFINE_UNQUOTED([PROC_MEM_FILE], "$proc_mem_file", [/proc/pid/mem interface])
1056+ fi
1057+
1058+ FPM_TRACE_SRCS=""
1059+
1060+ if test "$have_ptrace" = "yes"; then
1061+ FPM_TRACE_SRCS="fpm_trace_ptrace.c"
1062+ elif test -n "$proc_mem_file"; then
1063+ FPM_TRACE_SRCS="fpm_trace_pread.c"
1064+ elif test "$have_mach_vm_read" = "yes" ; then
1065+ FPM_TRACE_SRCS="fpm_trace_mach.c"
1066+ fi
1067+
1068+ if test -n "$FPM_TRACE_SRCS"; then
1069+ FPM_TRACE_SRCS="fpm_trace.c $FPM_TRACE_SRCS"
1070+ fi
1071+
1072+])
1073+
1074+AC_DEFUN([AC_FPM_PRCTL],
1075+[
1076+ AC_MSG_CHECKING([for prctl])
1077+
1078+ AC_TRY_COMPILE([ #include <sys/prctl.h> ], [prctl(0, 0, 0, 0, 0);], [
1079+ AC_DEFINE([HAVE_PRCTL], 1, [do we have prctl?])
1080+ AC_MSG_RESULT([yes])
1081+ ], [
1082+ AC_MSG_RESULT([no])
1083+ ])
1084+])
8c0dac15
ER
1085diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/conf/php-fpm.conf.in php-5.2.6.fpm/sapi/cgi/fpm/conf/php-fpm.conf.in
1086--- php-5.2.6.vanilla/sapi/cgi/fpm/conf/php-fpm.conf.in 1970-01-01 03:00:00.000000000 +0300
1087+++ php-5.2.6.fpm/sapi/cgi/fpm/conf/php-fpm.conf.in 2008-05-23 00:53:15.000000000 +0400
c6a6bfc9 1088@@ -0,0 +1,156 @@
fd1be940
ER
1089+<?xml version="1.0" ?>
1090+<configuration>
1091+
1092+ All relative paths in this config are relative to php's install prefix
1093+
1094+ <section name="global_options">
1095+
1096+ Pid file
c6a6bfc9 1097+ <value name="pid_file">@php_fpm_pid_path@</value>
fd1be940
ER
1098+
1099+ Error log file
c6a6bfc9
ER
1100+ <value name="error_log">@php_fpm_log_path@</value>
1101+
1102+ Log level
1103+ <value name="log_level">notice</value>
fd1be940
ER
1104+
1105+ When this amount of php processes exited with SIGSEGV or SIGBUS ...
1106+ <value name="emergency_restart_threshold">10</value>
1107+
c6a6bfc9 1108+ ... in a less than this interval of time, a graceful restart will be initiated.
fd1be940
ER
1109+ Useful to work around accidental curruptions in accelerator's shared memory.
1110+ <value name="emergency_restart_interval">1m</value>
1111+
1112+ Time limit on waiting child's reaction on signals from master
1113+ <value name="process_control_timeout">5s</value>
1114+
1115+ Set to 'no' to debug fpm
1116+ <value name="daemonize">yes</value>
1117+
1118+ </section>
1119+
1120+ <workers>
1121+
1122+ <section name="pool">
1123+
1124+ Name of pool. Used in logs and stats.
c6a6bfc9 1125+ <value name="name">default</value>
fd1be940
ER
1126+
1127+ Address to accept fastcgi requests on.
1128+ Valid syntax is 'ip.ad.re.ss:port' or just 'port' or '/path/to/unix/socket'
1129+ <value name="listen_address">127.0.0.1:9000</value>
1130+
1131+ <value name="listen_options">
1132+
1133+ Set listen(2) backlog
1134+ <value name="backlog">-1</value>
1135+
1136+ Set permissions for unix socket, if one used.
1137+ In Linux read/write permissions must be set in order to allow connections from web server.
1138+ Many BSD-derrived systems allow connections regardless of permissions.
1139+ <value name="owner"></value>
1140+ <value name="group"></value>
1141+ <value name="mode">0666</value>
1142+ </value>
1143+
1144+ Additional php.ini defines, specific to this pool of workers.
1145+ <value name="php_defines">
1146+ <!-- <value name="sendmail_path">/usr/sbin/sendmail -t -i</value> -->
1147+ <!-- <value name="display_errors">0</value> -->
1148+ </value>
1149+
1150+ Unix user of processes
c6a6bfc9 1151+ <!-- <value name="user">nobody</value> -->
fd1be940
ER
1152+
1153+ Unix group of processes
c6a6bfc9 1154+ <!-- <value name="group">@php_fpm_group@</value> -->
fd1be940
ER
1155+
1156+ Process manager settings
1157+ <value name="pm">
1158+
1159+ Sets style of controling worker process count.
1160+ Valid values are 'static' and 'apache-like'
1161+ <value name="style">static</value>
1162+
1163+ Sets the limit on the number of simultaneous requests that will be served.
1164+ Equivalent to Apache MaxClients directive.
1165+ Equivalent to PHP_FCGI_CHILDREN environment in original php.fcgi
1166+ Used with any pm_style.
1167+ <value name="max_children">5</value>
1168+
1169+ Settings group for 'apache-like' pm style
1170+ <value name="apache_like">
1171+
1172+ Sets the number of server processes created on startup.
1173+ Used only when 'apache-like' pm_style is selected
1174+ <value name="StartServers">20</value>
1175+
1176+ Sets the desired minimum number of idle server processes.
1177+ Used only when 'apache-like' pm_style is selected
1178+ <value name="MinSpareServers">5</value>
1179+
1180+ Sets the desired maximum number of idle server processes.
1181+ Used only when 'apache-like' pm_style is selected
1182+ <value name="MaxSpareServers">35</value>
1183+
1184+ </value>
1185+
1186+ </value>
1187+
c6a6bfc9
ER
1188+ The timeout (in seconds) for serving a single request after which the worker process will be terminated
1189+ Should be used when 'max_execution_time' ini option does not stop script execution for some reason
1190+ '0s' means 'off'
1191+ <value name="request_terminate_timeout">0s</value>
1192+
1193+ The timeout (in seconds) for serving of single request after which a php backtrace will be dumped to slow.log file
1194+ '0s' means 'off'
1195+ <value name="request_slowlog_timeout">0s</value>
1196+
1197+ The log file for slow requests
1198+ <value name="slowlog">logs/slow.log</value>
fd1be940
ER
1199+
1200+ Set open file desc rlimit
1201+ <value name="rlimit_files">1024</value>
1202+
1203+ Set max core size rlimit
c6a6bfc9 1204+ <value name="rlimit_core">0</value>
fd1be940 1205+
c6a6bfc9 1206+ Chroot to this directory at the start, absolute path
fd1be940
ER
1207+ <value name="chroot"></value>
1208+
c6a6bfc9 1209+ Chdir to this directory at the start, absolute path
fd1be940
ER
1210+ <value name="chdir"></value>
1211+
c6a6bfc9 1212+ Redirect workers' stdout and stderr into main error log.
fd1be940
ER
1213+ If not set, they will be redirected to /dev/null, according to FastCGI specs
1214+ <value name="catch_workers_output">yes</value>
1215+
1216+ How much requests each process should execute before respawn.
1217+ Useful to work around memory leaks in 3rd party libraries.
1218+ For endless request processing please specify 0
1219+ Equivalent to PHP_FCGI_MAX_REQUESTS
1220+ <value name="max_requests">500</value>
1221+
1222+ Comma separated list of ipv4 addresses of FastCGI clients that allowed to connect.
1223+ Equivalent to FCGI_WEB_SERVER_ADDRS environment in original php.fcgi (5.2.2+)
1224+ Makes sense only with AF_INET listening socket.
1225+ <value name="allowed_clients">127.0.0.1</value>
1226+
1227+ Pass environment variables like LD_LIBRARY_PATH
1228+ All $VARIABLEs are taken from current environment
1229+ <value name="environment">
1230+ <value name="HOSTNAME">$HOSTNAME</value>
1231+ <value name="PATH">/usr/local/bin:/usr/bin:/bin</value>
1232+ <value name="TMP">/tmp</value>
1233+ <value name="TMPDIR">/tmp</value>
1234+ <value name="TEMP">/tmp</value>
1235+ <value name="OSTYPE">$OSTYPE</value>
1236+ <value name="MACHTYPE">$MACHTYPE</value>
1237+ <value name="MALLOC_CHECK_">2</value>
1238+ </value>
1239+
1240+ </section>
1241+
1242+ </workers>
1243+
1244+</configuration>
75ddaf45
ER
1245--- php-5.2.6.fpm/sapi/cgi/fpm/config.m4 2008-09-19 05:22:37.000000000 +0400
1246+++ php-5.2.6.fpm/sapi/cgi/fpm/config.m4 2008-09-19 05:22:37.000000000 +0400
1247@@ -0,0 +1,118 @@
c6a6bfc9
ER
1248+
1249+FPM_VERSION="0.5.9"
1250+
1251+PHP_ARG_WITH(fpm-conf, for php-fpm config file path,
1252+[ --with-fpm-conf=PATH Set the path for php-fpm configuration file [PREFIX/etc/php-fpm.conf]], \$prefix/etc/php-fpm.conf, no)
1253+
1254+PHP_ARG_WITH(fpm-log, for php-fpm log file path,
1255+[ --with-fpm-log=PATH Set the path for php-fpm log file [PREFIX/logs/php-fpm.log]], \$prefix/logs/php-fpm.log, no)
1256+
1257+PHP_ARG_WITH(fpm-pid, for php-fpm pid file path,
1258+[ --with-fpm-pid=PATH Set the path for php-fpm pid file [PREFIX/logs/php-fpm.pid]], \$prefix/logs/php-fpm.pid, no)
fd1be940
ER
1259+
1260+dnl AC_FPM_LIBEVENT
1261+AC_FPM_LIBXML
c6a6bfc9
ER
1262+AC_FPM_PRCTL
1263+AC_FPM_CLOCK
1264+AC_FPM_TRACE
fd1be940
ER
1265+dnl AC_FPM_JUDY
1266+
75ddaf45
ER
1267+LIBEVENT_CFLAGS=""
1268+LIBEVENT_LIBS="-levent"
fd1be940
ER
1269+
1270+SAPI_EXTRA_DEPS="$LIBEVENT_LIBS"
1271+
c6a6bfc9
ER
1272+FPM_SOURCES="fpm.c \
1273+ fpm_conf.c \
1274+ fpm_signals.c \
1275+ fpm_children.c \
1276+ fpm_worker_pool.c \
1277+ fpm_unix.c \
1278+ fpm_cleanup.c \
1279+ fpm_sockets.c \
1280+ fpm_stdio.c \
1281+ fpm_env.c \
1282+ fpm_events.c \
1283+ fpm_php.c \
1284+ fpm_php_trace.c \
1285+ $FPM_TRACE_SRCS \
1286+ fpm_process_ctl.c \
1287+ fpm_request.c \
1288+ fpm_clock.c \
1289+ fpm_shm.c \
1290+ fpm_shm_slots.c \
1291+ xml_config.c \
1292+ zlog.c"
fd1be940
ER
1293+
1294+FPM_CFLAGS="$LIBEVENT_CFLAGS $LIBXML_CFLAGS $JUDY_CFLAGS"
fd1be940
ER
1295+
1296+dnl FPM_CFLAGS="$FPM_CFLAGS -DJUDYERROR_NOTEST" # for Judy
8c0dac15 1297+FPM_CFLAGS="$FPM_CFLAGS -I$abs_srcdir/sapi/cgi" # for fastcgi.h
fd1be940 1298+
c6a6bfc9
ER
1299+if test "$ICC" = "yes" ; then
1300+ FPM_ADD_CFLAGS="-Wall -wd279,310,869,810,981"
1301+elif test "$GCC" = "yes" ; then
1302+ FPM_ADD_CFLAGS="-Wall -Wpointer-arith -Wno-unused-parameter -Wunused-variable -Wunused-value -fno-strict-aliasing"
1303+fi
1304+
1305+if test -n "$FPM_WERROR" ; then
1306+ FPM_ADD_CFLAGS="$FPM_ADD_CFLAGS -Werror"
fd1be940
ER
1307+fi
1308+
c6a6bfc9
ER
1309+FPM_CFLAGS="$FPM_ADD_CFLAGS $FPM_CFLAGS"
1310+
8c0dac15 1311+PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/cgi/fpm/Makefile.frag)
fd1be940 1312+
8c0dac15 1313+PHP_ADD_SOURCES(sapi/cgi/fpm, $FPM_SOURCES, $FPM_CFLAGS, sapi)
fd1be940 1314+
8c0dac15 1315+PHP_ADD_BUILD_DIR(sapi/cgi/fpm)
fd1be940
ER
1316+
1317+install_fpm="install-fpm"
1318+
c6a6bfc9
ER
1319+SAPI_EXTRA_LIBS="$LIBEVENT_LIBS $LIBXML_LIBS $JUDY_LIBS"
1320+
1321+
1322+if test "$prefix" = "NONE" ; then
1323+ fpm_prefix=/usr/local
1324+else
1325+ fpm_prefix="$prefix"
1326+fi
1327+
1328+if test "$PHP_FPM_CONF" = "\$prefix/etc/php-fpm.conf" ; then
1329+ php_fpm_conf_path="$fpm_prefix/etc/php-fpm.conf"
1330+else
1331+ php_fpm_conf_path="$PHP_FPM_CONF"
1332+fi
1333+
1334+if test "$PHP_FPM_LOG" = "\$prefix/logs/php-fpm.log" ; then
1335+ php_fpm_log_path="$fpm_prefix/logs/php-fpm.log"
1336+else
1337+ php_fpm_log_path="$PHP_FPM_LOG"
1338+fi
1339+
1340+if test "$PHP_FPM_PID" = "\$prefix/logs/php-fpm.pid" ; then
1341+ php_fpm_pid_path="$fpm_prefix/logs/php-fpm.pid"
1342+else
1343+ php_fpm_pid_path="$PHP_FPM_PID"
1344+fi
1345+
1346+
1347+if grep nobody /etc/group >/dev/null 2>&1; then
1348+ php_fpm_group=nobody
1349+else
1350+ if grep nogroup /etc/group >/dev/null 2>&1; then
1351+ php_fpm_group=nogroup
1352+ else
1353+ php_fpm_group=nobody
1354+ fi
1355+fi
1356+
1357+PHP_SUBST_OLD(php_fpm_conf_path)
1358+PHP_SUBST_OLD(php_fpm_log_path)
1359+PHP_SUBST_OLD(php_fpm_pid_path)
1360+PHP_SUBST_OLD(php_fpm_group)
1361+PHP_SUBST_OLD(FPM_VERSION)
1362+
8c0dac15
ER
1363+PHP_OUTPUT(sapi/cgi/fpm/fpm_autoconf.h)
1364+PHP_OUTPUT(sapi/cgi/fpm/php-fpm.conf:sapi/cgi/fpm/conf/php-fpm.conf.in)
1365+PHP_OUTPUT(sapi/cgi/fpm/php-fpm:sapi/cgi/fpm/init.d/php-fpm.in)
1366diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_arrays.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_arrays.h
1367--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_arrays.h 1970-01-01 03:00:00.000000000 +0300
1368+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_arrays.h 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9
ER
1369@@ -0,0 +1,110 @@
1370+
1371+ /* $Id$ */
1372+ /* (c) 2007,2008 Andrei Nigmatulin */
1373+
1374+#ifndef FPM_ARRAYS_H
1375+#define FPM_ARRAYS_H 1
1376+
1377+#include <stdlib.h>
1378+#include <string.h>
1379+
1380+struct fpm_array_s {
1381+ void *data;
1382+ size_t sz;
1383+ size_t used;
1384+ size_t allocated;
1385+};
1386+
1387+static inline struct fpm_array_s *fpm_array_init(struct fpm_array_s *a, unsigned int sz, unsigned int initial_num)
1388+{
1389+ void *allocated = 0;
1390+
1391+ if (!a) {
1392+ a = malloc(sizeof(struct fpm_array_s));
1393+
1394+ if (!a) {
1395+ return 0;
1396+ }
1397+
1398+ allocated = a;
1399+ }
1400+
1401+ a->sz = sz;
1402+
1403+ a->data = calloc(sz, initial_num);
1404+
1405+ if (!a->data) {
1406+ free(allocated);
1407+ return 0;
1408+ }
1409+
1410+ a->allocated = initial_num;
1411+ a->used = 0;
1412+
1413+ return a;
1414+}
1415+
1416+static inline void *fpm_array_item(struct fpm_array_s *a, unsigned int n)
1417+{
1418+ char *ret;
1419+
1420+ ret = (char *) a->data + a->sz * n;
1421+
1422+ return ret;
1423+}
1424+
1425+static inline void *fpm_array_item_last(struct fpm_array_s *a)
1426+{
1427+ return fpm_array_item(a, a->used - 1);
1428+}
1429+
1430+static inline int fpm_array_item_remove(struct fpm_array_s *a, unsigned int n)
1431+{
1432+ int ret = -1;
1433+
1434+ if (n < a->used - 1) {
1435+ void *last = fpm_array_item(a, a->used - 1);
1436+ void *to_remove = fpm_array_item(a, n);
1437+
1438+ memcpy(to_remove, last, a->sz);
1439+
1440+ ret = n;
1441+ }
1442+
1443+ --a->used;
1444+
1445+ return ret;
1446+}
1447+
1448+static inline void *fpm_array_push(struct fpm_array_s *a)
1449+{
1450+ void *ret;
1451+
1452+ if (a->used == a->allocated) {
1453+ size_t new_allocated = a->allocated ? a->allocated * 2 : 20;
1454+ void *new_ptr = realloc(a->data, a->sz * new_allocated);
1455+
1456+ if (!new_ptr) {
1457+ return 0;
1458+ }
1459+
1460+ a->data = new_ptr;
1461+ a->allocated = new_allocated;
1462+ }
1463+
1464+ ret = fpm_array_item(a, a->used);
1465+
1466+ ++a->used;
1467+
1468+ return ret;
1469+}
1470+
1471+static inline void fpm_array_free(struct fpm_array_s *a)
1472+{
1473+ free(a->data);
1474+ a->data = 0;
1475+ a->sz = 0;
1476+ a->used = a->allocated = 0;
1477+}
1478+
1479+#endif
8c0dac15
ER
1480diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_atomic.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_atomic.h
1481--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_atomic.h 1970-01-01 03:00:00.000000000 +0300
1482+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_atomic.h 2008-09-19 03:34:11.000000000 +0400
c6a6bfc9 1483@@ -0,0 +1,85 @@
fd1be940
ER
1484+
1485+ /* $Id$ */
c6a6bfc9
ER
1486+ /* (c) 2007,2008 Andrei Nigmatulin */
1487+
1488+#ifndef FPM_ATOMIC_H
1489+#define FPM_ATOMIC_H 1
1490+
1491+#include <stdint.h>
1492+#include <sched.h>
1493+
1494+#if ( __i386__ || __i386 )
1495+
1496+typedef int32_t atomic_int_t;
1497+typedef uint32_t atomic_uint_t;
1498+typedef volatile atomic_uint_t atomic_t;
1499+
1500+
1501+static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add)
1502+{
1503+ __asm__ volatile ( "lock;" "xaddl %0, %1;" :
1504+ "+r" (add) : "m" (*value) : "memory");
1505+
1506+ return add;
1507+}
1508+
1509+static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set)
1510+{
1511+ unsigned char res;
1512+
1513+ __asm__ volatile ( "lock;" "cmpxchgl %3, %1;" "sete %0;" :
1514+ "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory");
1515+
1516+ return res;
1517+}
1518+
1519+#elif ( __amd64__ || __amd64 )
1520+
1521+typedef int64_t atomic_int_t;
1522+typedef uint64_t atomic_uint_t;
1523+typedef volatile atomic_uint_t atomic_t;
1524+
1525+static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add)
1526+{
1527+ __asm__ volatile ( "lock;" "xaddq %0, %1;" :
1528+ "+r" (add) : "m" (*value) : "memory");
1529+
1530+ return add;
1531+}
1532+
1533+static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set)
1534+{
1535+ unsigned char res;
1536+
1537+ __asm__ volatile ( "lock;" "cmpxchgq %3, %1;" "sete %0;" :
1538+ "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory");
1539+
1540+ return res;
1541+}
1542+
1543+#else
1544+
1545+#error unsupported processor. please write a patch and send it to me
1546+
1547+#endif
1548+
1549+static inline int fpm_spinlock(atomic_t *lock, int try_once)
1550+{
1551+ if (try_once) {
1552+ return atomic_cmp_set(lock, 0, 1) ? 0 : -1;
1553+ }
1554+
1555+ for (;;) {
1556+
1557+ if (atomic_cmp_set(lock, 0, 1)) {
1558+ break;
1559+ }
1560+
1561+ sched_yield();
1562+ }
1563+
1564+ return 0;
1565+}
1566+
1567+#endif
1568+
8c0dac15
ER
1569diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_autoconf.h.in php-5.2.6.fpm/sapi/cgi/fpm/fpm_autoconf.h.in
1570--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_autoconf.h.in 1970-01-01 03:00:00.000000000 +0300
1571+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_autoconf.h.in 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9
ER
1572@@ -0,0 +1,9 @@
1573+
1574+ /* $Id$ */
1575+ /* (c) 2007,2008 Andrei Nigmatulin */
1576+
1577+#define PHP_FPM_VERSION "@FPM_VERSION@"
1578+#define PHP_FPM_CONF_PATH "@php_fpm_conf_path@"
1579+#define PHP_FPM_LOG_PATH "@php_fpm_log_path@"
1580+#define PHP_FPM_PID_PATH "@php_fpm_pid_path@"
1581+
8c0dac15
ER
1582diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm.c php-5.2.6.fpm/sapi/cgi/fpm/fpm.c
1583--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm.c 1970-01-01 03:00:00.000000000 +0300
1584+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm.c 2008-07-20 20:38:31.000000000 +0400
c6a6bfc9
ER
1585@@ -0,0 +1,84 @@
1586+
1587+ /* $Id$ */
1588+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
1589+
1590+#include "fpm_config.h"
1591+
1592+#include <stdlib.h> /* for exit */
1593+
1594+#include "fpm.h"
1595+#include "fpm_children.h"
1596+#include "fpm_signals.h"
1597+#include "fpm_env.h"
1598+#include "fpm_events.h"
1599+#include "fpm_cleanup.h"
1600+#include "fpm_php.h"
1601+#include "fpm_sockets.h"
1602+#include "fpm_unix.h"
1603+#include "fpm_process_ctl.h"
1604+#include "fpm_conf.h"
1605+#include "fpm_worker_pool.h"
1606+#include "fpm_stdio.h"
1607+#include "zlog.h"
1608+
c6a6bfc9
ER
1609+int fpm;
1610+
fd1be940
ER
1611+struct fpm_globals_s fpm_globals;
1612+
1613+int fpm_init(int argc, char **argv, char *config)
1614+{
c6a6bfc9
ER
1615+ fpm_globals.argc = argc;
1616+ fpm_globals.argv = argv;
1617+ fpm_globals.config = config;
fd1be940 1618+
c6a6bfc9
ER
1619+ if (0 > fpm_php_init_main() ||
1620+ 0 > fpm_stdio_init_main() ||
1621+ 0 > fpm_conf_init_main() ||
fd1be940
ER
1622+ 0 > fpm_unix_init_main() ||
1623+ 0 > fpm_env_init_main() ||
1624+ 0 > fpm_signals_init_main() ||
c6a6bfc9 1625+ 0 > fpm_pctl_init_main() ||
fd1be940
ER
1626+ 0 > fpm_children_init_main() ||
1627+ 0 > fpm_sockets_init_main() ||
fd1be940 1628+ 0 > fpm_worker_pool_init_main() ||
c6a6bfc9 1629+ 0 > fpm_event_init_main()) {
fd1be940
ER
1630+ return -1;
1631+ }
1632+
1633+ if (0 > fpm_conf_write_pid()) {
1634+ return -1;
1635+ }
1636+
c6a6bfc9 1637+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "fpm is running, pid %d", (int) fpm_globals.parent_pid);
fd1be940
ER
1638+
1639+ return 0;
1640+}
1641+
1642+/* children: return listening socket
1643+ parent: never return */
1644+int fpm_run(int *max_requests)
1645+{
1646+ struct fpm_worker_pool_s *wp;
1647+
1648+ /* create initial children in all pools */
1649+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
1650+ int is_parent;
1651+
1652+ is_parent = fpm_children_create_initial(wp);
1653+
1654+ if (!is_parent) {
1655+ goto run_child;
1656+ }
1657+ }
1658+
1659+ /* run event loop forever */
1660+ fpm_event_loop();
1661+
c6a6bfc9 1662+run_child: /* only workers reach this point */
fd1be940
ER
1663+
1664+ fpm_cleanups_run(FPM_CLEANUP_CHILD);
1665+
1666+ *max_requests = fpm_globals.max_requests;
1667+ return fpm_globals.listening_socket;
1668+}
1669+
8c0dac15
ER
1670diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_children.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_children.c
1671--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_children.c 1970-01-01 03:00:00.000000000 +0300
1672+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_children.c 2008-08-26 19:09:15.000000000 +0400
c6a6bfc9 1673@@ -0,0 +1,383 @@
fd1be940
ER
1674+
1675+ /* $Id$ */
c6a6bfc9 1676+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
1677+
1678+#include "fpm_config.h"
1679+
1680+#include <sys/types.h>
1681+#include <sys/wait.h>
1682+#include <time.h>
1683+#include <unistd.h>
1684+#include <string.h>
1685+#include <stdio.h>
1686+
1687+#include "fpm.h"
1688+#include "fpm_children.h"
1689+#include "fpm_signals.h"
1690+#include "fpm_worker_pool.h"
1691+#include "fpm_sockets.h"
1692+#include "fpm_process_ctl.h"
1693+#include "fpm_php.h"
1694+#include "fpm_conf.h"
1695+#include "fpm_cleanup.h"
1696+#include "fpm_events.h"
c6a6bfc9 1697+#include "fpm_clock.h"
fd1be940
ER
1698+#include "fpm_stdio.h"
1699+#include "fpm_unix.h"
1700+#include "fpm_env.h"
c6a6bfc9 1701+#include "fpm_shm_slots.h"
fd1be940
ER
1702+
1703+#include "zlog.h"
1704+
1705+static time_t *last_faults;
1706+static int fault;
1707+
fd1be940
ER
1708+static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop);
1709+
1710+static void fpm_children_cleanup(int which, void *arg)
1711+{
fd1be940 1712+ free(last_faults);
fd1be940
ER
1713+}
1714+
1715+static struct fpm_child_s *fpm_child_alloc()
1716+{
1717+ struct fpm_child_s *ret;
1718+
fd1be940
ER
1719+ ret = malloc(sizeof(struct fpm_child_s));
1720+
1721+ if (!ret) return 0;
1722+
fd1be940
ER
1723+ memset(ret, 0, sizeof(*ret));
1724+
1725+ return ret;
1726+}
1727+
c6a6bfc9 1728+static void fpm_child_free(struct fpm_child_s *child)
fd1be940 1729+{
c6a6bfc9
ER
1730+ free(child);
1731+}
fd1be940 1732+
c6a6bfc9
ER
1733+static void fpm_child_close(struct fpm_child_s *child, int in_event_loop)
1734+{
fd1be940
ER
1735+ if (child->fd_stdout != -1) {
1736+ if (in_event_loop) {
1737+ fpm_event_fire(&child->ev_stdout);
1738+ }
1739+ if (child->fd_stdout != -1) {
1740+ close(child->fd_stdout);
1741+ }
1742+ }
1743+
1744+ if (child->fd_stderr != -1) {
1745+ if (in_event_loop) {
1746+ fpm_event_fire(&child->ev_stderr);
1747+ }
1748+ if (child->fd_stderr != -1) {
1749+ close(child->fd_stderr);
1750+ }
1751+ }
1752+
c6a6bfc9 1753+ fpm_child_free(child);
fd1be940
ER
1754+}
1755+
c6a6bfc9 1756+static void fpm_child_link(struct fpm_child_s *child)
fd1be940 1757+{
c6a6bfc9 1758+ struct fpm_worker_pool_s *wp = child->wp;
fd1be940 1759+
c6a6bfc9 1760+ ++wp->running_children;
fd1be940
ER
1761+ ++fpm_globals.running_children;
1762+
c6a6bfc9 1763+ child->next = wp->children;
fd1be940
ER
1764+ if (child->next) child->next->prev = child;
1765+ child->prev = 0;
c6a6bfc9
ER
1766+ wp->children = child;
1767+}
1768+
1769+static void fpm_child_unlink(struct fpm_child_s *child)
1770+{
1771+ --child->wp->running_children;
1772+ --fpm_globals.running_children;
1773+
1774+ if (child->prev) child->prev->next = child->next;
1775+ else child->wp->children = child->next;
1776+ if (child->next) child->next->prev = child->prev;
fd1be940 1777+
fd1be940
ER
1778+}
1779+
c6a6bfc9 1780+static struct fpm_child_s *fpm_child_find(pid_t pid)
fd1be940 1781+{
c6a6bfc9 1782+ struct fpm_worker_pool_s *wp;
fd1be940
ER
1783+ struct fpm_child_s *child = 0;
1784+
c6a6bfc9
ER
1785+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
1786+
1787+ for (child = wp->children; child; child = child->next) {
1788+ if (child->pid == pid) {
1789+ break;
1790+ }
fd1be940 1791+ }
c6a6bfc9
ER
1792+
1793+ if (child) break;
fd1be940
ER
1794+ }
1795+
1796+ if (!child) {
1797+ return 0;
1798+ }
1799+
fd1be940
ER
1800+ return child;
1801+}
1802+
1803+static void fpm_child_init(struct fpm_worker_pool_s *wp)
1804+{
1805+ fpm_globals.max_requests = wp->config->max_requests;
c6a6bfc9
ER
1806+
1807+ if (0 > fpm_stdio_init_child(wp) ||
1808+ 0 > fpm_unix_init_child(wp) ||
1809+ 0 > fpm_signals_init_child() ||
1810+ 0 > fpm_env_init_child(wp) ||
1811+ 0 > fpm_php_init_child(wp)) {
1812+
1813+ zlog(ZLOG_STUFF, ZLOG_ERROR, "child failed to initialize (pool %s)", wp->config->name);
1814+ exit(255);
1815+ }
fd1be940
ER
1816+}
1817+
1818+int fpm_children_free(struct fpm_child_s *child)
1819+{
1820+ struct fpm_child_s *next;
1821+
1822+ for (; child; child = next) {
1823+ next = child->next;
c6a6bfc9 1824+ fpm_child_close(child, 0 /* in_event_loop */);
fd1be940
ER
1825+ }
1826+
1827+ return 0;
1828+}
1829+
fd1be940
ER
1830+void fpm_children_bury()
1831+{
1832+ int status;
1833+ pid_t pid;
1834+ struct fpm_child_s *child;
1835+
c6a6bfc9 1836+ while ( (pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
fd1be940
ER
1837+ char buf[128];
1838+ int severity = ZLOG_NOTICE;
1839+
c6a6bfc9
ER
1840+ child = fpm_child_find(pid);
1841+
fd1be940
ER
1842+ if (WIFEXITED(status)) {
1843+
1844+ snprintf(buf, sizeof(buf), "with code %d", WEXITSTATUS(status));
1845+
1846+ if (WEXITSTATUS(status) != 0) {
1847+ severity = ZLOG_WARNING;
1848+ }
1849+
1850+ }
c6a6bfc9
ER
1851+ else if (WIFSIGNALED(status)) {
1852+ const char *signame = fpm_signal_names[WTERMSIG(status)];
1853+ const char *have_core = WCOREDUMP(status) ? " (core dumped)" : "";
fd1be940 1854+
c6a6bfc9
ER
1855+ if (signame == NULL) {
1856+ signame = "";
1857+ }
1858+
1859+ snprintf(buf, sizeof(buf), "on signal %d %s%s", WTERMSIG(status), signame, have_core);
fd1be940
ER
1860+
1861+ if (WTERMSIG(status) != SIGQUIT) { /* possible request loss */
1862+ severity = ZLOG_WARNING;
1863+ }
1864+ }
c6a6bfc9
ER
1865+ else if (WIFSTOPPED(status)) {
1866+
1867+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "child %d stopped for tracing", (int) pid);
1868+
1869+ if (child && child->tracer) {
1870+ child->tracer(child);
1871+ }
fd1be940 1872+
c6a6bfc9
ER
1873+ continue;
1874+ }
fd1be940
ER
1875+
1876+ if (child) {
1877+ struct fpm_worker_pool_s *wp = child->wp;
1878+ struct timeval tv1, tv2;
1879+
c6a6bfc9
ER
1880+ fpm_child_unlink(child);
1881+
1882+ fpm_shm_slots_discard_slot(child);
1883+
1884+ fpm_clock_get(&tv1);
fd1be940
ER
1885+
1886+ timersub(&tv1, &child->started, &tv2);
1887+
c6a6bfc9 1888+ zlog(ZLOG_STUFF, severity, "child %d (pool %s) exited %s after %ld.%06d seconds from start", (int) pid,
fd1be940
ER
1889+ child->wp->config->name, buf, tv2.tv_sec, (int) tv2.tv_usec);
1890+
c6a6bfc9 1891+ fpm_child_close(child, 1 /* in event_loop */);
fd1be940
ER
1892+
1893+ fpm_pctl_child_exited();
1894+
1895+ if (last_faults && (WTERMSIG(status) == SIGSEGV || WTERMSIG(status) == SIGBUS)) {
1896+ time_t now = tv1.tv_sec;
1897+ int restart_condition = 1;
1898+ int i;
1899+
1900+ last_faults[fault++] = now;
1901+
1902+ if (fault == fpm_global_options.emergency_restart_threshold) {
1903+ fault = 0;
1904+ }
1905+
1906+ for (i = 0; i < fpm_global_options.emergency_restart_threshold; i++) {
1907+ if (now - last_faults[i] > fpm_global_options.emergency_restart_interval) {
1908+ restart_condition = 0;
1909+ break;
1910+ }
1911+ }
1912+
1913+ if (restart_condition) {
1914+
1915+ zlog(ZLOG_STUFF, ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload",
1916+ fpm_global_options.emergency_restart_threshold, fpm_global_options.emergency_restart_interval);
1917+
1918+ fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET);
1919+ }
1920+ }
1921+
1922+ fpm_children_make(wp, 1 /* in event loop */);
c6a6bfc9
ER
1923+
1924+ if (fpm_globals.is_child) {
1925+ break;
1926+ }
fd1be940
ER
1927+ }
1928+ else {
1929+ zlog(ZLOG_STUFF, ZLOG_ALERT, "oops, unknown child exited %s", buf);
1930+ }
1931+ }
1932+
1933+}
1934+
c6a6bfc9
ER
1935+static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp)
1936+{
1937+ struct fpm_child_s *c;
1938+
1939+ c = fpm_child_alloc();
1940+
1941+ if (!c) {
1942+ zlog(ZLOG_STUFF, ZLOG_ERROR, "malloc failed (pool %s)", wp->config->name);
1943+ return 0;
1944+ }
1945+
1946+ c->wp = wp;
1947+ c->fd_stdout = -1; c->fd_stderr = -1;
1948+
1949+ if (0 > fpm_stdio_prepare_pipes(c)) {
1950+ fpm_child_free(c);
1951+ return 0;
1952+ }
1953+
1954+ if (0 > fpm_shm_slots_prepare_slot(c)) {
1955+ fpm_stdio_discard_pipes(c);
1956+ fpm_child_free(c);
1957+ return 0;
1958+ }
1959+
1960+ return c;
1961+}
1962+
1963+static void fpm_resources_discard(struct fpm_child_s *child)
1964+{
1965+ fpm_shm_slots_discard_slot(child);
1966+ fpm_stdio_discard_pipes(child);
1967+ fpm_child_free(child);
1968+}
1969+
1970+static void fpm_child_resources_use(struct fpm_child_s *child)
1971+{
1972+ fpm_shm_slots_child_use_slot(child);
1973+ fpm_stdio_child_use_pipes(child);
1974+ fpm_child_free(child);
1975+}
1976+
1977+static void fpm_parent_resources_use(struct fpm_child_s *child)
1978+{
1979+ fpm_shm_slots_parent_use_slot(child);
1980+ fpm_stdio_parent_use_pipes(child);
1981+ fpm_child_link(child);
1982+}
1983+
fd1be940
ER
1984+static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop)
1985+{
1986+ int enough = 0;
c6a6bfc9
ER
1987+ pid_t pid;
1988+ struct fpm_child_s *child;
fd1be940
ER
1989+
1990+ while (!enough && fpm_pctl_can_spawn_children() && wp->running_children < wp->config->pm->max_children) {
fd1be940 1991+
c6a6bfc9
ER
1992+ child = fpm_resources_prepare(wp);
1993+
1994+ if (!child) {
fd1be940
ER
1995+ enough = 1;
1996+ break;
1997+ }
1998+
1999+ pid = fork();
2000+
2001+ switch (pid) {
2002+
2003+ case 0 :
c6a6bfc9 2004+ fpm_child_resources_use(child);
fd1be940
ER
2005+ fpm_globals.is_child = 1;
2006+ if (in_event_loop) {
2007+ fpm_event_exit_loop();
2008+ }
2009+ fpm_child_init(wp);
2010+ return 0;
2011+
2012+ case -1 :
2013+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fork() failed");
2014+ enough = 1;
c6a6bfc9
ER
2015+
2016+ fpm_resources_discard(child);
2017+
fd1be940
ER
2018+ break; /* dont try any more on error */
2019+
2020+ default :
c6a6bfc9
ER
2021+ child->pid = pid;
2022+ fpm_clock_get(&child->started);
2023+ fpm_parent_resources_use(child);
fd1be940 2024+
c6a6bfc9 2025+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "child %d (pool %s) started", (int) pid, wp->config->name);
fd1be940
ER
2026+ }
2027+
2028+ }
2029+
2030+ return 1; /* we are done */
2031+}
2032+
2033+int fpm_children_create_initial(struct fpm_worker_pool_s *wp)
2034+{
2035+ return fpm_children_make(wp, 0 /* not in event loop yet */);
2036+}
2037+
2038+int fpm_children_init_main()
2039+{
2040+ if (fpm_global_options.emergency_restart_threshold &&
2041+ fpm_global_options.emergency_restart_interval) {
2042+
2043+ last_faults = malloc(sizeof(time_t) * fpm_global_options.emergency_restart_threshold);
2044+
2045+ if (!last_faults) {
2046+ return -1;
2047+ }
2048+
2049+ memset(last_faults, 0, sizeof(time_t) * fpm_global_options.emergency_restart_threshold);
2050+ }
2051+
2052+ fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_children_cleanup, 0);
2053+
2054+ return 0;
2055+}
c6a6bfc9 2056+
8c0dac15
ER
2057diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_children.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_children.h
2058--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_children.h 1970-01-01 03:00:00.000000000 +0300
2059+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_children.h 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9 2060@@ -0,0 +1,33 @@
fd1be940
ER
2061+
2062+ /* $Id$ */
c6a6bfc9 2063+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
2064+
2065+#ifndef FPM_CHILDREN_H
2066+#define FPM_CHILDREN_H 1
2067+
2068+#include <sys/time.h>
2069+#include <sys/types.h>
2070+#include <event.h>
2071+
2072+#include "fpm_worker_pool.h"
2073+
2074+int fpm_children_create_initial(struct fpm_worker_pool_s *wp);
2075+int fpm_children_free(struct fpm_child_s *child);
2076+void fpm_children_bury();
2077+int fpm_children_init_main();
2078+
2079+struct fpm_child_s;
2080+
2081+struct fpm_child_s {
2082+ struct fpm_child_s *prev, *next;
2083+ struct timeval started;
2084+ struct fpm_worker_pool_s *wp;
2085+ struct event ev_stdout, ev_stderr;
c6a6bfc9 2086+ int shm_slot_i;
fd1be940 2087+ int fd_stdout, fd_stderr;
c6a6bfc9
ER
2088+ void (*tracer)(struct fpm_child_s *);
2089+ struct timeval slow_logged;
fd1be940
ER
2090+ pid_t pid;
2091+};
2092+
2093+#endif
8c0dac15
ER
2094diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_cleanup.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_cleanup.c
2095--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_cleanup.c 1970-01-01 03:00:00.000000000 +0300
2096+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_cleanup.c 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9 2097@@ -0,0 +1,51 @@
fd1be940
ER
2098+
2099+ /* $Id$ */
c6a6bfc9 2100+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
2101+
2102+#include "fpm_config.h"
2103+
2104+#include <stdlib.h>
2105+
c6a6bfc9 2106+#include "fpm_arrays.h"
fd1be940
ER
2107+#include "fpm_cleanup.h"
2108+#include "zlog.h"
2109+
2110+struct cleanup_s {
2111+ int type;
2112+ void (*cleanup)(int, void *);
2113+ void *arg;
2114+};
2115+
c6a6bfc9 2116+static struct fpm_array_s cleanups = { .sz = sizeof(struct cleanup_s) };
fd1be940
ER
2117+
2118+int fpm_cleanup_add(int type, void (*cleanup)(int, void *), void *arg)
2119+{
c6a6bfc9 2120+ struct cleanup_s *c;
fd1be940 2121+
c6a6bfc9 2122+ c = fpm_array_push(&cleanups);
fd1be940 2123+
c6a6bfc9
ER
2124+ if (!c) {
2125+ return -1;
fd1be940
ER
2126+ }
2127+
c6a6bfc9
ER
2128+ c->type = type;
2129+ c->cleanup = cleanup;
2130+ c->arg = arg;
fd1be940
ER
2131+
2132+ return 0;
2133+}
2134+
2135+void fpm_cleanups_run(int type)
2136+{
c6a6bfc9
ER
2137+ struct cleanup_s *c = fpm_array_item_last(&cleanups);
2138+ int cl = cleanups.used;
fd1be940 2139+
c6a6bfc9 2140+ for ( ; cl--; c--) {
fd1be940
ER
2141+ if (c->type & type) {
2142+ c->cleanup(type, c->arg);
2143+ }
2144+ }
2145+
c6a6bfc9 2146+ fpm_array_free(&cleanups);
fd1be940 2147+}
c6a6bfc9 2148+
8c0dac15
ER
2149diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_cleanup.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_cleanup.h
2150--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_cleanup.h 1970-01-01 03:00:00.000000000 +0300
2151+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_cleanup.h 2008-05-24 21:38:47.000000000 +0400
fd1be940
ER
2152@@ -0,0 +1,21 @@
2153+
2154+ /* $Id$ */
c6a6bfc9 2155+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
2156+
2157+#ifndef FPM_CLEANUP_H
2158+#define FPM_CLEANUP_H 1
2159+
2160+int fpm_cleanup_add(int type, void (*cleanup)(int, void *), void *);
2161+void fpm_cleanups_run(int type);
2162+
2163+enum {
2164+ FPM_CLEANUP_CHILD = (1 << 0),
2165+ FPM_CLEANUP_PARENT_EXIT = (1 << 1),
2166+ FPM_CLEANUP_PARENT_EXIT_MAIN = (1 << 2),
2167+ FPM_CLEANUP_PARENT_EXEC = (1 << 3),
2168+ FPM_CLEANUP_PARENT = (1 << 1) | (1 << 2) | (1 << 3),
2169+ FPM_CLEANUP_ALL = ~0,
2170+};
2171+
2172+#endif
2173+
8c0dac15
ER
2174diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_clock.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_clock.c
2175--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_clock.c 1970-01-01 03:00:00.000000000 +0300
2176+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_clock.c 2008-09-19 03:19:59.000000000 +0400
c6a6bfc9
ER
2177@@ -0,0 +1,115 @@
2178+
2179+ /* $Id$ */
2180+ /* (c) 2007,2008 Andrei Nigmatulin */
2181+
2182+#include "fpm_config.h"
2183+
2184+#if defined(HAVE_CLOCK_GETTIME)
2185+#include <time.h> /* for CLOCK_MONOTONIC */
2186+#endif
2187+
2188+#include "fpm_clock.h"
2189+#include "zlog.h"
2190+
2191+
2192+/* posix monotonic clock - preferred source of time */
2193+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
2194+
2195+static int monotonic_works;
2196+
2197+int fpm_clock_init()
2198+{
2199+ struct timespec ts;
2200+
2201+ monotonic_works = 0;
2202+
2203+ if (0 == clock_gettime(CLOCK_MONOTONIC, &ts)) {
2204+ monotonic_works = 1;
2205+ }
2206+
2207+ return 0;
2208+}
2209+
2210+int fpm_clock_get(struct timeval *tv)
2211+{
2212+ if (monotonic_works) {
2213+ struct timespec ts;
2214+
2215+ if (0 > clock_gettime(CLOCK_MONOTONIC, &ts)) {
2216+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "clock_gettime() failed");
2217+ return -1;
2218+ }
2219+
2220+ tv->tv_sec = ts.tv_sec;
2221+ tv->tv_usec = ts.tv_nsec / 1000;
2222+ return 0;
2223+ }
2224+
2225+ return gettimeofday(tv, 0);
2226+}
2227+
2228+/* macosx clock */
2229+#elif defined(HAVE_CLOCK_GET_TIME)
2230+
2231+#include <mach/mach.h>
2232+#include <mach/clock.h>
2233+#include <mach/mach_error.h>
2234+
2235+static clock_serv_t mach_clock;
2236+
2237+/* this code borrowed from here: http://lists.apple.com/archives/Darwin-development/2002/Mar/msg00746.html */
2238+/* mach_clock also should be re-initialized in child process after fork */
2239+int fpm_clock_init()
2240+{
2241+ kern_return_t ret;
2242+ mach_timespec_t aTime;
2243+
2244+ ret = host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &mach_clock);
2245+
2246+ if (ret != KERN_SUCCESS) {
2247+ zlog(ZLOG_STUFF, ZLOG_ERROR, "host_get_clock_service() failed: %s", mach_error_string(ret));
2248+ return -1;
2249+ }
2250+
2251+ /* test if it works */
2252+ ret = clock_get_time(mach_clock, &aTime);
2253+
2254+ if (ret != KERN_SUCCESS) {
2255+ zlog(ZLOG_STUFF, ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret));
2256+ return -1;
2257+ }
2258+
2259+ return 0;
2260+}
2261+
2262+int fpm_clock_get(struct timeval *tv)
2263+{
2264+ kern_return_t ret;
2265+ mach_timespec_t aTime;
2266+
2267+ ret = clock_get_time(mach_clock, &aTime);
2268+
2269+ if (ret != KERN_SUCCESS) {
2270+ zlog(ZLOG_STUFF, ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret));
2271+ return -1;
2272+ }
2273+
2274+ tv->tv_sec = aTime.tv_sec;
2275+ tv->tv_usec = aTime.tv_nsec / 1000;
2276+
2277+ return 0;
2278+}
2279+
2280+#else /* no clock */
2281+
2282+int fpm_clock_init()
2283+{
2284+ return 0;
2285+}
2286+
2287+int fpm_clock_get(struct timeval *tv)
2288+{
2289+ return gettimeofday(tv, 0);
2290+}
2291+
2292+#endif
8c0dac15
ER
2293diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_clock.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_clock.h
2294--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_clock.h 1970-01-01 03:00:00.000000000 +0300
2295+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_clock.h 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9
ER
2296@@ -0,0 +1,13 @@
2297+
2298+ /* $Id$ */
2299+ /* (c) 2007,2008 Andrei Nigmatulin */
2300+
2301+#ifndef FPM_CLOCK_H
2302+#define FPM_CLOCK_H 1
2303+
2304+#include <sys/time.h>
2305+
2306+int fpm_clock_init();
2307+int fpm_clock_get(struct timeval *tv);
2308+
2309+#endif
8c0dac15
ER
2310diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_conf.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_conf.c
2311--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_conf.c 1970-01-01 03:00:00.000000000 +0300
2312+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_conf.c 2008-09-19 04:54:15.000000000 +0400
c6a6bfc9 2313@@ -0,0 +1,530 @@
fd1be940
ER
2314+
2315+ /* $Id$ */
c6a6bfc9 2316+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
2317+
2318+#include "fpm_config.h"
2319+
2320+#include <sys/types.h>
2321+#include <sys/stat.h>
2322+#include <fcntl.h>
2323+#include <string.h>
2324+#include <stdlib.h>
2325+#include <stddef.h>
2326+#include <stdint.h>
2327+#include <stdio.h>
2328+#include <unistd.h>
2329+
2330+#include "fpm.h"
2331+#include "fpm_conf.h"
c6a6bfc9 2332+#include "fpm_stdio.h"
fd1be940
ER
2333+#include "fpm_worker_pool.h"
2334+#include "fpm_cleanup.h"
2335+#include "fpm_php.h"
2336+#include "fpm_sockets.h"
2337+#include "xml_config.h"
2338+#include "zlog.h"
2339+
2340+
2341+struct fpm_options_s fpm_global_options;
2342+
2343+static void *fpm_global_options_ptr()
2344+{
2345+ return &fpm_global_options;
2346+}
2347+
c6a6bfc9
ER
2348+static char *fpm_conf_set_log_level(void **conf, char *name, void *vv, intptr_t offset)
2349+{
2350+ char *value = vv;
2351+
2352+ if (!strcmp(value, "debug")) {
2353+ fpm_globals.log_level = ZLOG_DEBUG;
2354+ }
2355+ else if (!strcmp(value, "notice")) {
2356+ fpm_globals.log_level = ZLOG_NOTICE;
2357+ }
2358+ else if (!strcmp(value, "warn")) {
2359+ fpm_globals.log_level = ZLOG_WARNING;
2360+ }
2361+ else if (!strcmp(value, "error")) {
2362+ fpm_globals.log_level = ZLOG_ERROR;
2363+ }
2364+ else if (!strcmp(value, "alert")) {
2365+ fpm_globals.log_level = ZLOG_ALERT;
2366+ }
2367+ else {
2368+ return "invalid value for 'log_level'";
2369+ }
2370+
2371+ return NULL;
2372+}
2373+
fd1be940
ER
2374+static struct xml_conf_section xml_section_fpm_global_options = {
2375+ .conf = &fpm_global_options_ptr,
2376+ .path = "/configuration/global_options",
c6a6bfc9 2377+ .parsers = (struct xml_value_parser []) {
fd1be940
ER
2378+ { XML_CONF_SCALAR, "emergency_restart_threshold", &xml_conf_set_slot_integer, offsetof(struct fpm_options_s, emergency_restart_threshold) },
2379+ { XML_CONF_SCALAR, "emergency_restart_interval", &xml_conf_set_slot_time, offsetof(struct fpm_options_s, emergency_restart_interval) },
2380+ { XML_CONF_SCALAR, "process_control_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_options_s, process_control_timeout) },
2381+ { XML_CONF_SCALAR, "daemonize", &xml_conf_set_slot_boolean, offsetof(struct fpm_options_s, daemonize) },
2382+ { XML_CONF_SCALAR, "pid_file", &xml_conf_set_slot_string, offsetof(struct fpm_options_s, pid_file) },
2383+ { XML_CONF_SCALAR, "error_log", &xml_conf_set_slot_string, offsetof(struct fpm_options_s, error_log) },
c6a6bfc9 2384+ { XML_CONF_SCALAR, "log_level", &fpm_conf_set_log_level, 0 },
fd1be940
ER
2385+ { 0, 0, 0, 0 }
2386+ }
2387+};
2388+
2389+static char *fpm_conf_set_pm_style(void **conf, char *name, void *vv, intptr_t offset)
2390+{
2391+ char *value = vv;
2392+ struct fpm_pm_s *c = *conf;
2393+
2394+ if (!strcmp(value, "static")) {
2395+ c->style = PM_STYLE_STATIC;
2396+ }
2397+ else if (!strcmp(value, "apache-like")) {
2398+ c->style = PM_STYLE_APACHE_LIKE;
2399+ }
2400+ else {
2401+ return "invalid value for 'style'";
2402+ }
2403+
2404+ return NULL;
2405+}
2406+
2407+static char *fpm_conf_set_rlimit_core(void **conf, char *name, void *vv, intptr_t offset)
2408+{
2409+ char *value = vv;
2410+ struct fpm_worker_pool_config_s *c = *conf;
2411+
2412+ if (!strcmp(value, "unlimited")) {
2413+ c->rlimit_core = -1;
2414+ }
2415+ else {
2416+ int int_value;
2417+ void *subconf = &int_value;
2418+ char *error;
2419+
2420+ error = xml_conf_set_slot_integer(&subconf, name, vv, 0);
2421+
2422+ if (error) return error;
2423+
2424+ if (int_value < 0) return "invalid value for 'rlimit_core'";
2425+
2426+ c->rlimit_core = int_value;
2427+ }
2428+
2429+ return NULL;
2430+}
2431+
2432+static char *fpm_conf_set_catch_workers_output(void **conf, char *name, void *vv, intptr_t offset)
2433+{
2434+ struct fpm_worker_pool_config_s *c = *conf;
2435+ int int_value;
2436+ void *subconf = &int_value;
2437+ char *error;
2438+
2439+ error = xml_conf_set_slot_boolean(&subconf, name, vv, 0);
2440+
2441+ if (error) return error;
2442+
2443+ c->catch_workers_output = int_value;
2444+
2445+ return NULL;
2446+}
2447+
c6a6bfc9
ER
2448+static struct xml_conf_section fpm_conf_set_apache_like_subsection_conf = {
2449+ .path = "apache_like somewhere", /* fixme */
2450+ .parsers = (struct xml_value_parser []) {
2451+ { XML_CONF_SCALAR, "StartServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.StartServers) },
2452+ { XML_CONF_SCALAR, "MinSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MinSpareServers) },
2453+ { XML_CONF_SCALAR, "MaxSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MaxSpareServers) },
2454+ { 0, 0, 0, 0 }
2455+ }
2456+};
2457+
fd1be940
ER
2458+static char *fpm_conf_set_apache_like_subsection(void **conf, char *name, void *xml_node, intptr_t offset)
2459+{
fd1be940
ER
2460+ return xml_conf_parse_section(conf, &fpm_conf_set_apache_like_subsection_conf, xml_node);
2461+}
2462+
c6a6bfc9
ER
2463+static struct xml_conf_section fpm_conf_set_listen_options_subsection_conf = {
2464+ .path = "listen options somewhere", /* fixme */
2465+ .parsers = (struct xml_value_parser []) {
2466+ { XML_CONF_SCALAR, "backlog", &xml_conf_set_slot_integer, offsetof(struct fpm_listen_options_s, backlog) },
2467+ { XML_CONF_SCALAR, "owner", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, owner) },
2468+ { XML_CONF_SCALAR, "group", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, group) },
2469+ { XML_CONF_SCALAR, "mode", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, mode) },
2470+ { 0, 0, 0, 0 }
2471+ }
2472+};
2473+
fd1be940
ER
2474+static char *fpm_conf_set_listen_options_subsection(void **conf, char *name, void *xml_node, intptr_t offset)
2475+{
2476+ void *subconf = (char *) *conf + offset;
2477+ struct fpm_listen_options_s *lo;
2478+
fd1be940
ER
2479+ lo = malloc(sizeof(*lo));
2480+
2481+ if (!lo) {
c6a6bfc9 2482+ return "malloc() failed";
fd1be940
ER
2483+ }
2484+
2485+ memset(lo, 0, sizeof(*lo));
2486+
2487+ lo->backlog = -1;
2488+
2489+ * (struct fpm_listen_options_s **) subconf = lo;
2490+
2491+ subconf = lo;
2492+
2493+ return xml_conf_parse_section(&subconf, &fpm_conf_set_listen_options_subsection_conf, xml_node);
2494+}
2495+
c6a6bfc9
ER
2496+static struct xml_conf_section fpm_conf_set_pm_subsection_conf = {
2497+ .path = "pm settings somewhere", /* fixme */
2498+ .parsers = (struct xml_value_parser []) {
2499+ { XML_CONF_SCALAR, "style", &fpm_conf_set_pm_style, 0 },
2500+ { XML_CONF_SCALAR, "max_children", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, max_children) },
2501+ { XML_CONF_SUBSECTION, "apache_like", &fpm_conf_set_apache_like_subsection, offsetof(struct fpm_pm_s, options_apache_like) },
2502+ { 0, 0, 0, 0 }
2503+ }
2504+};
2505+
fd1be940
ER
2506+static char *fpm_conf_set_pm_subsection(void **conf, char *name, void *xml_node, intptr_t offset)
2507+{
2508+ void *subconf = (char *) *conf + offset;
2509+ struct fpm_pm_s *pm;
2510+
fd1be940
ER
2511+ pm = malloc(sizeof(*pm));
2512+
2513+ if (!pm) {
2514+ return "fpm_conf_set_pm_subsection(): malloc failed";
2515+ }
2516+
2517+ memset(pm, 0, sizeof(*pm));
2518+
2519+ * (struct fpm_pm_s **) subconf = pm;
2520+
2521+ subconf = pm;
2522+
2523+ return xml_conf_parse_section(&subconf, &fpm_conf_set_pm_subsection_conf, xml_node);
2524+}
2525+
2526+static char *xml_conf_set_slot_key_value_pair(void **conf, char *name, void *vv, intptr_t offset)
2527+{
2528+ char *value = vv;
2529+ struct key_value_s *kv;
2530+ struct key_value_s ***parent = (struct key_value_s ***) conf;
2531+
2532+ kv = malloc(sizeof(*kv));
2533+
2534+ if (!kv) {
c6a6bfc9 2535+ return "malloc() failed";
fd1be940
ER
2536+ }
2537+
2538+ memset(kv, 0, sizeof(*kv));
2539+
2540+ kv->key = strdup(name);
2541+ kv->value = strdup(value);
2542+
2543+ if (!kv->key || !kv->value) {
2544+ return "xml_conf_set_slot_key_value_pair(): strdup() failed";
2545+ }
2546+
2547+ **parent = kv;
2548+
2549+ *parent = &kv->next;
2550+
2551+ return NULL;
2552+}
2553+
c6a6bfc9
ER
2554+static struct xml_conf_section fpm_conf_set_key_value_pairs_subsection_conf = {
2555+ .path = "key_value_pairs somewhere", /* fixme */
2556+ .parsers = (struct xml_value_parser []) {
2557+ { XML_CONF_SCALAR, 0, &xml_conf_set_slot_key_value_pair, 0 },
2558+ { 0, 0, 0, 0 }
2559+ }
2560+};
2561+
fd1be940
ER
2562+static char *fpm_conf_set_key_value_pairs_subsection(void **conf, char *name, void *xml_node, intptr_t offset)
2563+{
2564+ void *next_kv = (char *) *conf + offset;
2565+
fd1be940
ER
2566+ return xml_conf_parse_section(&next_kv, &fpm_conf_set_key_value_pairs_subsection_conf, xml_node);
2567+}
2568+
2569+static void *fpm_worker_pool_config_alloc()
2570+{
2571+ static struct fpm_worker_pool_s *current_wp = 0;
2572+ struct fpm_worker_pool_s *wp;
2573+
2574+ wp = fpm_worker_pool_alloc();
2575+
2576+ if (!wp) return 0;
2577+
2578+ wp->config = malloc(sizeof(struct fpm_worker_pool_config_s));
2579+
2580+ if (!wp->config) return 0;
2581+
2582+ memset(wp->config, 0, sizeof(struct fpm_worker_pool_config_s));
2583+
2584+ if (current_wp) current_wp->next = wp;
2585+
2586+ current_wp = wp;
2587+
2588+ return wp->config;
2589+}
2590+
2591+int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc)
2592+{
2593+ struct key_value_s *kv, *kv_next;
2594+
2595+ free(wpc->name);
2596+ free(wpc->listen_address);
2597+ if (wpc->listen_options) {
2598+ free(wpc->listen_options->owner);
2599+ free(wpc->listen_options->group);
2600+ free(wpc->listen_options->mode);
2601+ free(wpc->listen_options);
2602+ }
2603+ for (kv = wpc->php_defines; kv; kv = kv_next) {
2604+ kv_next = kv->next;
2605+ free(kv->key);
2606+ free(kv->value);
2607+ free(kv);
2608+ }
2609+ for (kv = wpc->environment; kv; kv = kv_next) {
2610+ kv_next = kv->next;
2611+ free(kv->key);
2612+ free(kv->value);
2613+ free(kv);
2614+ }
2615+ free(wpc->pm);
2616+ free(wpc->user);
2617+ free(wpc->group);
2618+ free(wpc->chroot);
2619+ free(wpc->chdir);
2620+ free(wpc->allowed_clients);
c6a6bfc9 2621+ free(wpc->slowlog);
fd1be940
ER
2622+
2623+ return 0;
2624+}
2625+
2626+static struct xml_conf_section xml_section_fpm_worker_pool_config = {
2627+ .conf = &fpm_worker_pool_config_alloc,
2628+ .path = "/configuration/workers/pool",
c6a6bfc9 2629+ .parsers = (struct xml_value_parser []) {
fd1be940
ER
2630+ { XML_CONF_SCALAR, "name", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, name) },
2631+ { XML_CONF_SCALAR, "listen_address", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, listen_address) },
2632+ { XML_CONF_SUBSECTION, "listen_options", &fpm_conf_set_listen_options_subsection, offsetof(struct fpm_worker_pool_config_s, listen_options) },
2633+ { XML_CONF_SUBSECTION, "php_defines", &fpm_conf_set_key_value_pairs_subsection, offsetof(struct fpm_worker_pool_config_s, php_defines) },
2634+ { XML_CONF_SCALAR, "user", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, user) },
2635+ { XML_CONF_SCALAR, "group", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, group) },
2636+ { XML_CONF_SCALAR, "chroot", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, chroot) },
2637+ { XML_CONF_SCALAR, "chdir", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, chdir) },
2638+ { XML_CONF_SCALAR, "allowed_clients", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, allowed_clients) },
2639+ { XML_CONF_SUBSECTION, "environment", &fpm_conf_set_key_value_pairs_subsection, offsetof(struct fpm_worker_pool_config_s, environment) },
c6a6bfc9
ER
2640+ { XML_CONF_SCALAR, "request_terminate_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_worker_pool_config_s, request_terminate_timeout) },
2641+ { XML_CONF_SCALAR, "request_slowlog_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_worker_pool_config_s, request_slowlog_timeout) },
2642+ { XML_CONF_SCALAR, "slowlog", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, slowlog) },
fd1be940
ER
2643+ { XML_CONF_SCALAR, "rlimit_files", &xml_conf_set_slot_integer, offsetof(struct fpm_worker_pool_config_s, rlimit_files) },
2644+ { XML_CONF_SCALAR, "rlimit_core", &fpm_conf_set_rlimit_core, 0 },
2645+ { XML_CONF_SCALAR, "max_requests", &xml_conf_set_slot_integer, offsetof(struct fpm_worker_pool_config_s, max_requests) },
2646+ { XML_CONF_SCALAR, "catch_workers_output", &fpm_conf_set_catch_workers_output, 0 },
2647+ { XML_CONF_SUBSECTION, "pm", &fpm_conf_set_pm_subsection, offsetof(struct fpm_worker_pool_config_s, pm) },
2648+ { 0, 0, 0, 0 }
2649+ }
2650+};
2651+
2652+static struct xml_conf_section *fpm_conf_all_sections[] = {
2653+ &xml_section_fpm_global_options,
2654+ &xml_section_fpm_worker_pool_config,
2655+ 0
2656+};
2657+
2658+static int fpm_evaluate_full_path(char **path)
2659+{
2660+ if (**path != '/') {
2661+ char *full_path;
2662+
2663+ full_path = malloc(sizeof(PHP_PREFIX) + strlen(*path) + 1);
2664+
2665+ if (!full_path) return -1;
2666+
2667+ sprintf(full_path, "%s/%s", PHP_PREFIX, *path);
2668+
2669+ free(*path);
2670+
2671+ *path = full_path;
2672+ }
2673+
2674+ return 0;
2675+}
2676+
2677+static int fpm_conf_process_all_pools()
2678+{
2679+ struct fpm_worker_pool_s *wp;
2680+
2681+ if (!fpm_worker_all_pools) {
2682+ zlog(ZLOG_STUFF, ZLOG_ERROR, "at least one pool section must be specified in config file");
2683+ return -1;
2684+ }
2685+
2686+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
2687+
2688+ if (wp->config->listen_address && *wp->config->listen_address) {
2689+
2690+ wp->listen_address_domain = fpm_sockets_domain_from_address(wp->config->listen_address);
2691+
2692+ if (wp->listen_address_domain == FPM_AF_UNIX && *wp->config->listen_address != '/') {
2693+ fpm_evaluate_full_path(&wp->config->listen_address);
2694+ }
2695+
2696+ }
2697+ else {
2698+
2699+ wp->is_template = 1;
2700+
2701+ }
c6a6bfc9
ER
2702+
2703+ if (wp->config->request_slowlog_timeout) {
2704+#if HAVE_FPM_TRACE
2705+ if (! (wp->config->slowlog && *wp->config->slowlog)) {
2706+ zlog(ZLOG_STUFF, ZLOG_ERROR, "pool %s: 'slowlog' must be specified for use with 'request_slowlog_timeout'",
2707+ wp->config->name);
2708+ return -1;
2709+ }
2710+#else
2711+ static int warned = 0;
2712+
2713+ if (!warned) {
2714+ zlog(ZLOG_STUFF, ZLOG_WARNING, "pool %s: 'request_slowlog_timeout' is not supported on your system",
2715+ wp->config->name);
2716+ warned = 1;
2717+ }
2718+
2719+ wp->config->request_slowlog_timeout = 0;
2720+#endif
2721+ }
2722+
2723+ if (wp->config->request_slowlog_timeout && wp->config->slowlog && *wp->config->slowlog) {
2724+ int fd;
2725+
2726+ fpm_evaluate_full_path(&wp->config->slowlog);
2727+
2728+ if (wp->config->request_slowlog_timeout) {
2729+ fd = open(wp->config->slowlog, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
2730+
2731+ if (0 > fd) {
2732+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(%s) failed", wp->config->slowlog);
2733+ return -1;
2734+ }
2735+ close(fd);
2736+ }
2737+ }
fd1be940
ER
2738+ }
2739+
2740+ return 0;
2741+}
2742+
2743+int fpm_conf_unlink_pid()
2744+{
c6a6bfc9
ER
2745+ if (fpm_global_options.pid_file) {
2746+
2747+ if (0 > unlink(fpm_global_options.pid_file)) {
2748+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "unlink(\"%s\") failed", fpm_global_options.pid_file);
2749+ return -1;
2750+ }
2751+
fd1be940
ER
2752+ }
2753+
2754+ return 0;
2755+}
2756+
2757+int fpm_conf_write_pid()
2758+{
2759+ int fd;
2760+
2761+ if (fpm_global_options.pid_file) {
2762+ char buf[64];
2763+ int len;
2764+
2765+ unlink(fpm_global_options.pid_file);
2766+
2767+ fd = creat(fpm_global_options.pid_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
2768+
c6a6bfc9 2769+ if (fd < 0) {
fd1be940
ER
2770+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "creat(\"%s\") failed", fpm_global_options.pid_file);
2771+ return -1;
2772+ }
2773+
c6a6bfc9 2774+ len = sprintf(buf, "%d", (int) fpm_globals.parent_pid);
fd1be940
ER
2775+
2776+ if (len != write(fd, buf, len)) {
2777+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "write() failed");
2778+ return -1;
2779+ }
2780+
2781+ close(fd);
2782+ }
2783+
2784+ return 0;
2785+}
2786+
2787+static int fpm_conf_post_process()
2788+{
fd1be940
ER
2789+ if (fpm_global_options.pid_file) {
2790+ fpm_evaluate_full_path(&fpm_global_options.pid_file);
2791+ }
2792+
2793+ if (!fpm_global_options.error_log) {
c6a6bfc9 2794+ fpm_global_options.error_log = strdup(PHP_FPM_LOG_PATH);
fd1be940
ER
2795+ }
2796+
2797+ fpm_evaluate_full_path(&fpm_global_options.error_log);
2798+
c6a6bfc9 2799+ if (0 > fpm_stdio_open_error_log(0)) {
fd1be940
ER
2800+ return -1;
2801+ }
2802+
fd1be940
ER
2803+ return fpm_conf_process_all_pools();
2804+}
2805+
2806+static void fpm_conf_cleanup(int which, void *arg)
2807+{
2808+ free(fpm_global_options.pid_file);
2809+ free(fpm_global_options.error_log);
2810+ fpm_global_options.pid_file = 0;
2811+ fpm_global_options.error_log = 0;
2812+}
2813+
c6a6bfc9 2814+int fpm_conf_init_main()
fd1be940 2815+{
c6a6bfc9 2816+ char *filename = fpm_globals.config;
fd1be940
ER
2817+ char *err;
2818+
2819+ if (0 > xml_conf_sections_register(fpm_conf_all_sections)) {
2820+ return -1;
2821+ }
2822+
2823+ if (filename == NULL) {
c6a6bfc9 2824+ filename = PHP_FPM_CONF_PATH;
fd1be940
ER
2825+ }
2826+
2827+ err = xml_conf_load_file(filename);
2828+
2829+ if (err) {
2830+ zlog(ZLOG_STUFF, ZLOG_ERROR, "failed to load configuration file: %s", err);
2831+ return -1;
2832+ }
2833+
2834+ if (0 > fpm_conf_post_process()) {
2835+ return -1;
2836+ }
2837+
2838+ xml_conf_clean();
2839+
2840+ fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_conf_cleanup, 0);
2841+
2842+ return 0;
2843+}
8c0dac15
ER
2844diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_conf.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_conf.h
2845--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_conf.h 1970-01-01 03:00:00.000000000 +0300
2846+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_conf.h 2008-08-26 19:09:15.000000000 +0400
c6a6bfc9 2847@@ -0,0 +1,73 @@
fd1be940
ER
2848+
2849+ /* $Id$ */
c6a6bfc9 2850+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
2851+
2852+#ifndef FPM_CONF_H
2853+#define FPM_CONF_H 1
2854+
fd1be940
ER
2855+struct key_value_s;
2856+
2857+struct key_value_s {
2858+ struct key_value_s *next;
2859+ char *key;
2860+ char *value;
2861+};
2862+
2863+struct fpm_options_s {
2864+ int emergency_restart_threshold;
2865+ int emergency_restart_interval;
2866+ int process_control_timeout;
2867+ int daemonize;
2868+ char *pid_file;
2869+ char *error_log;
2870+};
2871+
2872+extern struct fpm_options_s fpm_global_options;
2873+
2874+struct fpm_pm_s {
2875+ int style;
2876+ int max_children;
2877+ struct {
2878+ int StartServers;
2879+ int MinSpareServers;
2880+ int MaxSpareServers;
2881+ } options_apache_like;
2882+};
2883+
2884+struct fpm_listen_options_s {
2885+ int backlog;
2886+ char *owner;
2887+ char *group;
2888+ char *mode;
2889+};
2890+
2891+struct fpm_worker_pool_config_s {
2892+ char *name;
2893+ char *listen_address;
2894+ struct fpm_listen_options_s *listen_options;
2895+ struct key_value_s *php_defines;
2896+ char *user;
2897+ char *group;
2898+ char *chroot;
2899+ char *chdir;
2900+ char *allowed_clients;
2901+ struct key_value_s *environment;
2902+ struct fpm_pm_s *pm;
c6a6bfc9
ER
2903+ int request_terminate_timeout;
2904+ int request_slowlog_timeout;
2905+ char *slowlog;
fd1be940
ER
2906+ int max_requests;
2907+ int rlimit_files;
2908+ int rlimit_core;
c6a6bfc9 2909+ unsigned catch_workers_output:1;
fd1be940
ER
2910+};
2911+
2912+enum { PM_STYLE_STATIC = 1, PM_STYLE_APACHE_LIKE = 2 };
2913+
c6a6bfc9 2914+int fpm_conf_init_main();
fd1be940
ER
2915+int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc);
2916+int fpm_conf_write_pid();
2917+int fpm_conf_unlink_pid();
2918+
2919+#endif
2920+
8c0dac15
ER
2921diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_config.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_config.h
2922--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_config.h 1970-01-01 03:00:00.000000000 +0300
2923+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_config.h 2008-05-25 04:30:43.000000000 +0400
c6a6bfc9 2924@@ -0,0 +1,39 @@
fd1be940
ER
2925+
2926+ /* $Id$ */
c6a6bfc9 2927+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
2928+
2929+#include "php_config.h"
c6a6bfc9 2930+#include "fpm_autoconf.h"
fd1be940
ER
2931+
2932+
2933+/* Solaris does not have it */
2934+#ifndef INADDR_NONE
2935+#define INADDR_NONE (-1)
2936+#endif
2937+
2938+
2939+/* If we're not using GNU C, elide __attribute__ */
2940+#ifndef __GNUC__
2941+# define __attribute__(x) /*NOTHING*/
2942+#endif
2943+
2944+
2945+/* Solaris does not have it */
2946+#ifndef timersub
2947+#define timersub(tvp, uvp, vvp) \
2948+ do { \
2949+ (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
2950+ (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
2951+ if ((vvp)->tv_usec < 0) { \
2952+ (vvp)->tv_sec--; \
2953+ (vvp)->tv_usec += 1000000; \
2954+ } \
2955+ } while (0)
2956+#endif
c6a6bfc9
ER
2957+
2958+#if defined(HAVE_PTRACE) || defined(PROC_MEM_FILE) || defined(HAVE_MACH_VM_READ)
2959+#define HAVE_FPM_TRACE 1
2960+#else
2961+#define HAVE_FPM_TRACE 0
2962+#endif
2963+
8c0dac15
ER
2964diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_env.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_env.c
2965--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_env.c 1970-01-01 03:00:00.000000000 +0300
2966+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_env.c 2008-09-19 03:19:59.000000000 +0400
fd1be940
ER
2967@@ -0,0 +1,125 @@
2968+
2969+ /* $Id$ */
c6a6bfc9 2970+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
2971+
2972+#include "fpm_config.h"
2973+
2974+#ifdef HAVE_ALLOCA_H
2975+#include <alloca.h>
2976+#endif
2977+#include <stdio.h>
2978+#include <stdlib.h>
2979+#include <string.h>
2980+
2981+#include "fpm_env.h"
2982+#include "zlog.h"
2983+
c6a6bfc9 2984+#ifndef HAVE_SETENV
fd1be940
ER
2985+int setenv(char *name, char *value, int overwrite)
2986+{
2987+ int name_len = strlen(name);
2988+ int value_len = strlen(value);
2989+ char *var = alloca(name_len + 1 + value_len + 1);
2990+
2991+ memcpy(var, name, name_len);
2992+
2993+ var[name_len] = '=';
2994+
2995+ memcpy(var + name_len + 1, value, value_len);
2996+
2997+ var[name_len + 1 + value_len] = '\0';
2998+
2999+ return putenv(var);
3000+}
3001+#endif
3002+
c6a6bfc9 3003+#ifndef HAVE_CLEARENV
fd1be940
ER
3004+void clearenv()
3005+{
3006+ char **envp;
3007+ char *s;
3008+
3009+ /* this algo is the only one known to me
3010+ that works well on all systems */
3011+ while (*(envp = environ)) {
3012+ char *eq = strchr(*envp, '=');
3013+
3014+ s = strdup(*envp);
3015+
3016+ if (eq) s[eq - *envp] = '\0';
3017+
3018+ unsetenv(s);
3019+ free(s);
3020+ }
3021+
3022+}
3023+#endif
3024+
3025+
3026+int fpm_env_init_child(struct fpm_worker_pool_s *wp)
3027+{
3028+ struct key_value_s *kv;
3029+
3030+ clearenv();
3031+
3032+ for (kv = wp->config->environment; kv; kv = kv->next) {
3033+ setenv(kv->key, kv->value, 1);
3034+ }
3035+
3036+ if (wp->user) {
3037+ setenv("USER", wp->user, 1);
3038+ }
3039+
3040+ if (wp->home) {
3041+ setenv("HOME", wp->home, 1);
3042+ }
3043+
3044+ return 0;
3045+}
3046+
3047+static int fpm_env_conf_wp(struct fpm_worker_pool_s *wp)
3048+{
3049+ struct key_value_s *kv;
3050+
3051+ kv = wp->config->environment;
3052+
3053+ for (kv = wp->config->environment; kv; kv = kv->next) {
3054+ if (*kv->value == '$') {
3055+ char *value = getenv(kv->value + 1);
3056+
3057+ if (!value) value = "";
3058+
3059+ free(kv->value);
3060+ kv->value = strdup(value);
3061+ }
3062+
3063+ /* autodetected values should be removed
3064+ if these vars specified in config */
3065+ if (!strcmp(kv->key, "USER")) {
3066+ free(wp->user);
3067+ wp->user = 0;
3068+ }
3069+
3070+ if (!strcmp(kv->key, "HOME")) {
3071+ free(wp->home);
3072+ wp->home = 0;
3073+ }
3074+ }
3075+
3076+ return 0;
3077+}
3078+
3079+int fpm_env_init_main()
3080+{
3081+ struct fpm_worker_pool_s *wp;
3082+
3083+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
3084+
3085+ if (0 > fpm_env_conf_wp(wp)) {
3086+ return -1;
3087+ }
3088+
3089+ }
3090+
3091+ return 0;
3092+}
8c0dac15
ER
3093diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_env.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_env.h
3094--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_env.h 1970-01-01 03:00:00.000000000 +0300
3095+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_env.h 2008-09-19 03:19:59.000000000 +0400
fd1be940
ER
3096@@ -0,0 +1,24 @@
3097+
3098+ /* $Id$ */
c6a6bfc9 3099+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
3100+
3101+#ifndef FPM_ENV_H
3102+#define FPM_ENV_H 1
3103+
3104+#include "fpm_worker_pool.h"
3105+
3106+int fpm_env_init_child(struct fpm_worker_pool_s *wp);
3107+int fpm_env_init_main();
3108+
3109+extern char **environ;
3110+
c6a6bfc9 3111+#ifndef HAVE_SETENV
fd1be940
ER
3112+int setenv(char *name, char *value, int overwrite);
3113+#endif
3114+
c6a6bfc9 3115+#ifndef HAVE_CLEARENV
fd1be940
ER
3116+void clearenv();
3117+#endif
3118+
3119+#endif
3120+
8c0dac15
ER
3121diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_events.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_events.c
3122--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_events.c 1970-01-01 03:00:00.000000000 +0300
3123+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_events.c 2008-08-26 19:09:15.000000000 +0400
c6a6bfc9 3124@@ -0,0 +1,133 @@
fd1be940
ER
3125+
3126+ /* $Id$ */
c6a6bfc9 3127+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
3128+
3129+#include "fpm_config.h"
3130+
3131+#include <unistd.h>
3132+#include <errno.h>
3133+#include <stdlib.h> /* for putenv */
3134+#include <string.h>
3135+#include <sys/types.h> /* for event.h below */
3136+#include <event.h>
3137+
c6a6bfc9 3138+#include "fpm.h"
fd1be940
ER
3139+#include "fpm_process_ctl.h"
3140+#include "fpm_events.h"
3141+#include "fpm_cleanup.h"
c6a6bfc9 3142+#include "fpm_stdio.h"
fd1be940
ER
3143+#include "fpm_signals.h"
3144+#include "fpm_children.h"
3145+#include "zlog.h"
3146+
fd1be940
ER
3147+static void fpm_event_cleanup(int which, void *arg)
3148+{
3149+ event_base_free(0);
3150+}
3151+
3152+static void fpm_got_signal(int fd, short ev, void *arg)
3153+{
3154+ char c;
3155+ int res;
3156+
3157+ do {
fd1be940 3158+
c6a6bfc9
ER
3159+ do {
3160+ res = read(fd, &c, 1);
3161+ } while (res == -1 && errno == EINTR);
3162+
3163+ if (res <= 0) {
3164+ if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
3165+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed");
3166+ }
3167+ return;
fd1be940 3168+ }
fd1be940 3169+
c6a6bfc9
ER
3170+ switch (c) {
3171+ case 'C' : /* SIGCHLD */
3172+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGCHLD");
3173+ fpm_children_bury();
3174+ break;
3175+ case 'I' : /* SIGINT */
3176+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGINT");
3177+ fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET);
3178+ break;
3179+ case 'T' : /* SIGTERM */
3180+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGTERM");
3181+ fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET);
3182+ break;
3183+ case 'Q' : /* SIGQUIT */
3184+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGQUIT");
3185+ fpm_pctl(FPM_PCTL_STATE_FINISHING, FPM_PCTL_ACTION_SET);
3186+ break;
3187+ case '1' : /* SIGUSR1 */
3188+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGUSR1");
3189+ if (0 == fpm_stdio_open_error_log(1)) {
3190+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "log file re-opened");
3191+ }
3192+ break;
3193+ case '2' : /* SIGUSR2 */
3194+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGUSR2");
3195+ fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET);
3196+ break;
3197+ }
3198+
3199+ if (fpm_globals.is_child) {
fd1be940 3200+ break;
c6a6bfc9
ER
3201+ }
3202+
3203+ } while (1);
fd1be940
ER
3204+
3205+ return;
3206+}
3207+
3208+int fpm_event_init_main()
3209+{
3210+ event_init();
3211+
3212+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "libevent: using %s", event_get_method());
3213+
3214+ fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_event_cleanup, 0);
3215+
3216+ return 0;
3217+}
3218+
3219+int fpm_event_loop()
3220+{
3221+ static struct event signal_fd_event;
3222+
3223+ event_set(&signal_fd_event, fpm_signals_get_fd(), EV_PERSIST | EV_READ, &fpm_got_signal, 0);
3224+
3225+ event_add(&signal_fd_event, 0);
3226+
c6a6bfc9
ER
3227+ fpm_pctl_heartbeat(-1, 0, 0);
3228+
fd1be940
ER
3229+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "libevent: entering main loop");
3230+
3231+ event_loop(0);
3232+
fd1be940
ER
3233+ return 0;
3234+}
3235+
3236+int fpm_event_add(int fd, struct event *ev, void (*callback)(int, short, void *), void *arg)
3237+{
3238+ event_set(ev, fd, EV_PERSIST | EV_READ, callback, arg);
3239+
3240+ return event_add(ev, 0);
3241+}
3242+
3243+int fpm_event_del(struct event *ev)
3244+{
3245+ return event_del(ev);
3246+}
3247+
3248+void fpm_event_exit_loop()
3249+{
3250+ event_loopexit(0);
3251+}
3252+
3253+void fpm_event_fire(struct event *ev)
3254+{
c6a6bfc9 3255+ (*ev->ev_callback)( (int) ev->ev_fd, (short) ev->ev_res, ev->ev_arg);
fd1be940 3256+}
c6a6bfc9 3257+
8c0dac15
ER
3258diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_events.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_events.h
3259--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_events.h 1970-01-01 03:00:00.000000000 +0300
3260+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_events.h 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9 3261@@ -0,0 +1,16 @@
fd1be940
ER
3262+
3263+ /* $Id$ */
c6a6bfc9 3264+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
3265+
3266+#ifndef FPM_EVENTS_H
3267+#define FPM_EVENTS_H 1
3268+
fd1be940
ER
3269+void fpm_event_exit_loop();
3270+int fpm_event_loop();
3271+int fpm_event_add(int fd, struct event *ev, void (*callback)(int, short, void *), void *arg);
3272+int fpm_event_del(struct event *ev);
3273+void fpm_event_fire(struct event *ev);
3274+int fpm_event_init_main();
3275+
3276+
3277+#endif
8c0dac15
ER
3278diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm.h php-5.2.6.fpm/sapi/cgi/fpm/fpm.h
3279--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm.h 1970-01-01 03:00:00.000000000 +0300
3280+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm.h 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9 3281@@ -0,0 +1,30 @@
fd1be940
ER
3282+
3283+ /* $Id$ */
c6a6bfc9 3284+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
3285+
3286+#ifndef FPM_H
3287+#define FPM_H 1
3288+
c6a6bfc9
ER
3289+#include <unistd.h>
3290+
fd1be940
ER
3291+int fpm_run(int *max_requests);
3292+int fpm_init(int argc, char **argv, char *config);
fd1be940
ER
3293+
3294+struct fpm_globals_s {
c6a6bfc9
ER
3295+ pid_t parent_pid;
3296+ int argc;
3297+ char **argv;
3298+ char *config;
fd1be940
ER
3299+ int running_children;
3300+ int error_log_fd;
c6a6bfc9 3301+ int log_level;
fd1be940
ER
3302+ int listening_socket; /* for this child */
3303+ int max_requests; /* for this child */
3304+ int is_child;
3305+};
3306+
3307+extern struct fpm_globals_s fpm_globals;
3308+
c6a6bfc9
ER
3309+extern int fpm;
3310+
fd1be940 3311+#endif
8c0dac15
ER
3312diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_php.c
3313--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php.c 1970-01-01 03:00:00.000000000 +0300
3314+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_php.c 2008-07-20 20:16:28.000000000 +0400
c6a6bfc9 3315@@ -0,0 +1,171 @@
fd1be940
ER
3316+
3317+ /* $Id$ */
c6a6bfc9 3318+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
3319+
3320+#include "fpm_config.h"
3321+
fd1be940
ER
3322+#include <stdlib.h>
3323+#include <string.h>
3324+
3325+#include "php.h"
3326+#include "php_main.h"
3327+#include "php_ini.h"
c6a6bfc9 3328+#include "ext/standard/dl.h"
fd1be940
ER
3329+
3330+#include "fastcgi.h"
3331+
3332+#include "fpm.h"
3333+#include "fpm_php.h"
3334+#include "fpm_cleanup.h"
3335+#include "fpm_worker_pool.h"
3336+
3337+static int zend_ini_alter_master(char *name, int name_length, char *new_value, int new_value_length, int stage)
3338+{
3339+ zend_ini_entry *ini_entry;
3340+ char *duplicate;
3341+
3342+ if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == FAILURE) {
3343+ return FAILURE;
3344+ }
3345+
3346+ duplicate = strdup(new_value);
3347+
3348+ if (!ini_entry->on_modify
3349+ || ini_entry->on_modify(ini_entry, duplicate, new_value_length,
c6a6bfc9 3350+ ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage) == SUCCESS) {
fd1be940
ER
3351+ ini_entry->value = duplicate;
3352+ ini_entry->value_length = new_value_length;
3353+ } else {
3354+ free(duplicate);
3355+ }
3356+
3357+ return SUCCESS;
3358+}
3359+
c6a6bfc9
ER
3360+static void fpm_php_disable(char *value, int (*zend_disable)(char *, uint))
3361+{
3362+ char *s = 0, *e = value;
3363+
3364+ while (*e) {
3365+ switch (*e) {
3366+ case ' ':
3367+ case ',':
3368+ if (s) {
3369+ *e = '\0';
3370+ zend_disable(s, e - s);
3371+ s = 0;
3372+ }
3373+ break;
3374+ default:
3375+ if (!s) {
3376+ s = e;
3377+ }
3378+ break;
3379+ }
3380+ e++;
3381+ }
3382+
3383+ if (s) {
3384+ zend_disable(s, e - s);
3385+ }
3386+}
3387+
fd1be940
ER
3388+static int fpm_php_apply_defines(struct fpm_worker_pool_s *wp)
3389+{
c6a6bfc9
ER
3390+ struct key_value_s *kv;
3391+
3392+ for (kv = wp->config->php_defines; kv; kv = kv->next) {
3393+ char *name = kv->key;
3394+ char *value = kv->value;
3395+ int name_len = strlen(name);
3396+ int value_len = strlen(value);
fd1be940 3397+
c6a6bfc9
ER
3398+ if (!strcmp(name, "extension") && *value) {
3399+ zval zv;
fd1be940 3400+
c6a6bfc9
ER
3401+#if defined(PHP_VERSION_ID) && (PHP_VERSION_ID >= 50300)
3402+ php_dl(value, MODULE_PERSISTENT, &zv, 1);
3403+#else
3404+ zval filename;
3405+ ZVAL_STRINGL(&filename, value, value_len, 0);
3406+#if (PHP_MAJOR_VERSION >= 5)
3407+ php_dl(&filename, MODULE_PERSISTENT, &zv, 1);
3408+#else
3409+ php_dl(&filename, MODULE_PERSISTENT, &zv);
3410+#endif
3411+#endif
3412+ continue;
3413+ }
fd1be940
ER
3414+
3415+ zend_ini_alter_master(name, name_len + 1, value, value_len, PHP_INI_STAGE_ACTIVATE);
3416+
c6a6bfc9
ER
3417+ if (!strcmp(name, "disable_functions") && *value) {
3418+ char *v = strdup(value);
3419+#if (PHP_MAJOR_VERSION >= 5)
3420+ PG(disable_functions) = v;
3421+#endif
3422+ fpm_php_disable(v, zend_disable_function);
3423+ }
3424+ else if (!strcmp(name, "disable_classes") && *value) {
3425+ char *v = strdup(value);
3426+#if (PHP_MAJOR_VERSION >= 5)
3427+ PG(disable_classes) = v;
3428+#endif
3429+ fpm_php_disable(v, zend_disable_class);
3430+ }
fd1be940
ER
3431+ }
3432+
3433+ return 0;
3434+}
3435+
3436+static int fpm_php_set_allowed_clients(struct fpm_worker_pool_s *wp)
3437+{
3438+ if (wp->listen_address_domain == FPM_AF_INET) {
3439+ fcgi_set_allowed_clients(wp->config->allowed_clients);
3440+ }
3441+
3442+ return 0;
3443+}
3444+
c6a6bfc9
ER
3445+char *fpm_php_script_filename()
3446+{
3447+ return SG(request_info).path_translated;
3448+}
3449+
3450+char *fpm_php_request_method()
3451+{
3452+ return (char *) SG(request_info).request_method;
3453+}
3454+
3455+size_t fpm_php_content_length()
3456+{
3457+ return SG(request_info).content_length;
3458+}
3459+
fd1be940
ER
3460+static void fpm_php_cleanup(int which, void *arg)
3461+{
c6a6bfc9 3462+ php_module_shutdown();
fd1be940
ER
3463+ sapi_shutdown();
3464+}
3465+
c6a6bfc9
ER
3466+void fpm_php_soft_quit()
3467+{
3468+ fcgi_set_in_shutdown(1);
3469+}
3470+
fd1be940
ER
3471+int fpm_php_init_main()
3472+{
3473+ fpm_cleanup_add(FPM_CLEANUP_PARENT, fpm_php_cleanup, 0);
3474+
3475+ return 0;
3476+}
3477+
3478+int fpm_php_init_child(struct fpm_worker_pool_s *wp)
3479+{
3480+ if (0 > fpm_php_apply_defines(wp) ||
3481+ 0 > fpm_php_set_allowed_clients(wp)) {
3482+ return -1;
3483+ }
3484+
3485+ return 0;
3486+}
8c0dac15
ER
3487diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_php.h
3488--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php.h 1970-01-01 03:00:00.000000000 +0300
3489+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_php.h 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9 3490@@ -0,0 +1,20 @@
fd1be940
ER
3491+
3492+ /* $Id$ */
c6a6bfc9 3493+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
3494+
3495+#ifndef FPM_PHP_H
3496+#define FPM_PHP_H 1
3497+
3498+#include "fpm_worker_pool.h"
3499+
3500+#include "build-defs.h" /* for PHP_ defines */
3501+
3502+int fpm_php_init_child(struct fpm_worker_pool_s *wp);
c6a6bfc9
ER
3503+char *fpm_php_script_filename();
3504+char *fpm_php_request_method();
3505+size_t fpm_php_content_length();
3506+void fpm_php_soft_quit();
fd1be940
ER
3507+int fpm_php_init_main();
3508+
3509+#endif
3510+
8c0dac15
ER
3511diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php_trace.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_php_trace.c
3512--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php_trace.c 1970-01-01 03:00:00.000000000 +0300
3513+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_php_trace.c 2008-08-26 19:09:15.000000000 +0400
c6a6bfc9 3514@@ -0,0 +1,170 @@
fd1be940
ER
3515+
3516+ /* $Id$ */
c6a6bfc9
ER
3517+ /* (c) 2007,2008 Andrei Nigmatulin */
3518+
3519+#include "fpm_config.h"
3520+
3521+#if HAVE_FPM_TRACE
3522+
3523+#include "php.h"
3524+#include "php_main.h"
3525+
3526+#include <stdio.h>
3527+#include <stddef.h>
3528+#include <stdint.h>
3529+#include <unistd.h>
3530+#include <sys/time.h>
3531+#include <sys/types.h>
3532+#include <errno.h>
3533+
3534+#include "fpm_trace.h"
3535+#include "fpm_php_trace.h"
3536+#include "fpm_children.h"
3537+#include "fpm_worker_pool.h"
3538+#include "fpm_process_ctl.h"
3539+
3540+#include "zlog.h"
3541+
3542+
3543+#define valid_ptr(p) ((p) && 0 == ((p) & (sizeof(long) - 1)))
3544+
3545+#if SIZEOF_LONG == 4
3546+#define PTR_FMT "08"
3547+#elif SIZEOF_LONG == 8
3548+#define PTR_FMT "016"
3549+#endif
3550+
3551+
3552+static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog)
3553+{
3554+ int callers_limit = 20;
3555+ pid_t pid = child->pid;
3556+ struct timeval tv;
3557+ static const int buf_size = 1024;
3558+ char buf[buf_size];
3559+ long execute_data;
3560+ long l;
3561+
3562+ gettimeofday(&tv, 0);
3563+
3564+ zlog_print_time(&tv, buf, buf_size);
3565+
3566+ fprintf(slowlog, "\n%s pid %d (pool %s)\n", buf, (int) pid, child->wp->config->name);
3567+
3568+ if (0 > fpm_trace_get_strz(buf, buf_size, (long) &SG(request_info).path_translated)) {
3569+ return -1;
3570+ }
3571+
3572+ fprintf(slowlog, "script_filename = %s\n", buf);
3573+
3574+ if (0 > fpm_trace_get_long((long) &EG(current_execute_data), &l)) {
3575+ return -1;
3576+ }
3577+
3578+ execute_data = l;
3579+
3580+ while (execute_data) {
3581+ long function;
3582+ uint lineno = 0;
3583+
3584+ fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data);
3585+
3586+ if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) {
3587+ return -1;
3588+ }
3589+
3590+ function = l;
3591+
3592+ if (valid_ptr(function)) {
3593+ if (0 > fpm_trace_get_strz(buf, buf_size, function + offsetof(zend_function, common.function_name))) {
3594+ return -1;
3595+ }
3596+
3597+ fprintf(slowlog, "%s()", buf);
3598+ }
3599+ else {
3600+ fprintf(slowlog, "???");
3601+ }
3602+
3603+ if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, op_array), &l)) {
3604+ return -1;
3605+ }
3606+
3607+ *buf = '\0';
3608+
3609+ if (valid_ptr(l)) {
3610+ long op_array = l;
3611+
3612+ if (0 > fpm_trace_get_strz(buf, buf_size, op_array + offsetof(zend_op_array, filename))) {
3613+ return -1;
3614+ }
3615+ }
3616+
3617+ if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, opline), &l)) {
3618+ return -1;
3619+ }
3620+
3621+ if (valid_ptr(l)) {
3622+ long opline = l;
3623+ uint *lu = (uint *) &l;
3624+
3625+ if (0 > fpm_trace_get_long(opline + offsetof(struct _zend_op, lineno), &l)) {
3626+ return -1;
3627+ }
3628+
3629+ lineno = *lu;
3630+ }
3631+
3632+ fprintf(slowlog, " %s:%u\n", *buf ? buf : "unknown", lineno);
3633+
3634+ if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, prev_execute_data), &l)) {
3635+ return -1;
3636+ }
3637+
3638+ execute_data = l;
3639+
3640+ if (0 == --callers_limit) {
3641+ break;
3642+ }
3643+ }
3644+
3645+ return 0;
3646+}
3647+
3648+void fpm_php_trace(struct fpm_child_s *child)
3649+{
3650+ FILE *slowlog;
3651+
3652+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "about to trace %d", (int) child->pid);
3653+
3654+ slowlog = fopen(child->wp->config->slowlog, "a+");
3655+
3656+ if (!slowlog) {
3657+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fopen(%s) failed", child->wp->config->slowlog);
3658+ goto done0;
3659+ }
3660+
3661+ if (0 > fpm_trace_ready(child->pid)) {
3662+ goto done1;
3663+ }
3664+
3665+ if (0 > fpm_php_trace_dump(child, slowlog)) {
3666+ fprintf(slowlog, "+++ dump failed\n");
3667+ }
3668+
3669+ if (0 > fpm_trace_close(child->pid)) {
3670+ goto done1;
3671+ }
3672+
3673+done1:
3674+ fclose(slowlog);
3675+
3676+done0:
3677+ fpm_pctl_kill(child->pid, FPM_PCTL_CONT);
3678+ child->tracer = 0;
3679+
3680+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "finished trace of %d", (int) child->pid);
3681+}
3682+
3683+#endif
3684+
8c0dac15
ER
3685diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php_trace.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_php_trace.h
3686--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php_trace.h 1970-01-01 03:00:00.000000000 +0300
3687+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_php_trace.h 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9
ER
3688@@ -0,0 +1,13 @@
3689+
3690+ /* $Id$ */
3691+ /* (c) 2007,2008 Andrei Nigmatulin */
3692+
3693+#ifndef FPM_PHP_TRACE_H
3694+#define FPM_PHP_TRACE_H 1
3695+
3696+struct fpm_child_s;
3697+
3698+void fpm_php_trace(struct fpm_child_s *);
3699+
3700+#endif
3701+
8c0dac15
ER
3702diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_process_ctl.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_process_ctl.c
3703--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_process_ctl.c 1970-01-01 03:00:00.000000000 +0300
3704+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_process_ctl.c 2008-07-21 17:13:44.000000000 +0400
c6a6bfc9
ER
3705@@ -0,0 +1,352 @@
3706+
3707+ /* $Id$ */
3708+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
3709+
3710+#include "fpm_config.h"
3711+
3712+#include <sys/types.h>
3713+#include <signal.h>
3714+#include <unistd.h>
3715+#include <stdlib.h>
3716+
3717+#include "fpm.h"
c6a6bfc9 3718+#include "fpm_clock.h"
fd1be940
ER
3719+#include "fpm_children.h"
3720+#include "fpm_signals.h"
3721+#include "fpm_events.h"
3722+#include "fpm_process_ctl.h"
3723+#include "fpm_cleanup.h"
c6a6bfc9 3724+#include "fpm_request.h"
fd1be940
ER
3725+#include "fpm_worker_pool.h"
3726+#include "zlog.h"
3727+
3728+
3729+static int fpm_state = FPM_PCTL_STATE_NORMAL;
3730+static int fpm_signal_sent = 0;
3731+
3732+
3733+static const char *fpm_state_names[] = {
3734+ [FPM_PCTL_STATE_NORMAL] = "normal",
3735+ [FPM_PCTL_STATE_RELOADING] = "reloading",
3736+ [FPM_PCTL_STATE_TERMINATING] = "terminating",
3737+ [FPM_PCTL_STATE_FINISHING] = "finishing"
3738+};
3739+
3740+static int saved_argc;
3741+static char **saved_argv;
fd1be940
ER
3742+
3743+static void fpm_pctl_cleanup(int which, void *arg)
3744+{
3745+ int i;
3746+
3747+ if (which != FPM_CLEANUP_PARENT_EXEC) {
3748+
c6a6bfc9 3749+ for (i = 0; i < saved_argc; i++) {
fd1be940
ER
3750+ free(saved_argv[i]);
3751+ }
3752+
3753+ free(saved_argv);
3754+
3755+ }
3756+}
3757+
c6a6bfc9
ER
3758+static struct event pctl_event;
3759+
3760+static void fpm_pctl_action(int fd, short which, void *arg)
3761+{
3762+ evtimer_del(&pctl_event);
3763+
3764+ memset(&pctl_event, 0, sizeof(pctl_event));
3765+
3766+ fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_TIMEOUT);
3767+}
3768+
3769+static int fpm_pctl_timeout_set(int sec)
3770+{
3771+ struct timeval tv = { .tv_sec = sec, .tv_usec = 0 };
3772+
3773+ if (evtimer_initialized(&pctl_event)) {
3774+ evtimer_del(&pctl_event);
3775+ }
3776+
3777+ evtimer_set(&pctl_event, &fpm_pctl_action, 0);
3778+
3779+ evtimer_add(&pctl_event, &tv);
3780+
3781+ return 0;
3782+}
3783+
fd1be940
ER
3784+static void fpm_pctl_exit()
3785+{
3786+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "exiting, bye-bye!");
3787+
3788+ fpm_conf_unlink_pid();
3789+
3790+ fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT_MAIN);
3791+
3792+ exit(0);
3793+}
3794+
3795+#define optional_arg(c) (saved_argc > c ? ", \"" : ""), (saved_argc > c ? saved_argv[c] : ""), (saved_argc > c ? "\"" : "")
3796+
3797+static void fpm_pctl_exec()
3798+{
3799+
3800+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "reloading: execvp(\"%s\", {\"%s\""
3801+ "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s"
3802+ "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s"
3803+ "})",
3804+ saved_argv[0], saved_argv[0],
3805+ optional_arg(1),
3806+ optional_arg(2),
3807+ optional_arg(3),
3808+ optional_arg(4),
3809+ optional_arg(5),
3810+ optional_arg(6),
3811+ optional_arg(7),
3812+ optional_arg(8),
3813+ optional_arg(9),
3814+ optional_arg(10)
3815+ );
3816+
3817+ fpm_cleanups_run(FPM_CLEANUP_PARENT_EXEC);
3818+
3819+ execvp(saved_argv[0], saved_argv);
3820+
3821+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "execvp() failed");
3822+
c6a6bfc9 3823+ exit(1);
fd1be940
ER
3824+}
3825+
3826+static void fpm_pctl_action_last()
3827+{
3828+ switch (fpm_state) {
3829+
3830+ case FPM_PCTL_STATE_RELOADING :
3831+
3832+ fpm_pctl_exec();
3833+ break;
3834+
3835+ case FPM_PCTL_STATE_FINISHING :
3836+
3837+ case FPM_PCTL_STATE_TERMINATING :
3838+
3839+ fpm_pctl_exit();
3840+ break;
3841+ }
3842+}
3843+
c6a6bfc9
ER
3844+int fpm_pctl_kill(pid_t pid, int how)
3845+{
3846+ int s = 0;
3847+
3848+ switch (how) {
3849+ case FPM_PCTL_TERM :
3850+ s = SIGTERM;
3851+ break;
3852+ case FPM_PCTL_STOP :
3853+ s = SIGSTOP;
3854+ break;
3855+ case FPM_PCTL_CONT :
3856+ s = SIGCONT;
3857+ break;
3858+ default :
3859+ break;
3860+ }
3861+
3862+ return kill(pid, s);
3863+}
3864+
fd1be940
ER
3865+static void fpm_pctl_kill_all(int signo)
3866+{
3867+ struct fpm_worker_pool_s *wp;
3868+ int alive_children = 0;
3869+
3870+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
3871+ struct fpm_child_s *child;
3872+
3873+ for (child = wp->children; child; child = child->next) {
3874+
3875+ int res = kill(child->pid, signo);
3876+
3877+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "sending signal %d %s to child %d (pool %s)", signo,
3878+ fpm_signal_names[signo] ? fpm_signal_names[signo] : "",
3879+ (int) child->pid, child->wp->config->name);
3880+
3881+ if (res == 0) ++alive_children;
3882+ }
3883+ }
3884+
3885+ if (alive_children) {
3886+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "%d %s still alive", alive_children, alive_children == 1 ? "child is" : "children are");
3887+ }
3888+}
3889+
3890+static void fpm_pctl_action_next()
3891+{
3892+ int sig, timeout;
3893+
3894+ if (!fpm_globals.running_children) fpm_pctl_action_last();
3895+
3896+ if (fpm_signal_sent == 0) {
3897+ if (fpm_state == FPM_PCTL_STATE_TERMINATING) {
3898+ sig = SIGTERM;
3899+ }
3900+ else {
3901+ sig = SIGQUIT;
3902+ }
3903+ timeout = fpm_global_options.process_control_timeout;
3904+ }
3905+ else {
3906+ if (fpm_signal_sent == SIGQUIT) {
3907+ sig = SIGTERM;
3908+ }
3909+ else {
3910+ sig = SIGKILL;
3911+ }
3912+ timeout = 1;
3913+ }
3914+
3915+ fpm_pctl_kill_all(sig);
3916+
3917+ fpm_signal_sent = sig;
3918+
c6a6bfc9 3919+ fpm_pctl_timeout_set(timeout);
fd1be940
ER
3920+}
3921+
3922+void fpm_pctl(int new_state, int action)
3923+{
3924+ switch (action) {
3925+
3926+ case FPM_PCTL_ACTION_SET :
3927+
3928+ if (fpm_state == new_state) { /* already in progress - just ignore duplicate signal */
3929+ return;
3930+ }
3931+
3932+ switch (fpm_state) { /* check which states can be overridden */
3933+
3934+ case FPM_PCTL_STATE_NORMAL :
3935+
3936+ /* 'normal' can be overridden by any other state */
3937+ break;
3938+
3939+ case FPM_PCTL_STATE_RELOADING :
3940+
3941+ /* 'reloading' can be overridden by 'finishing' */
3942+ if (new_state == FPM_PCTL_STATE_FINISHING) break;
3943+
3944+ case FPM_PCTL_STATE_FINISHING :
3945+
3946+ /* 'reloading' and 'finishing' can be overridden by 'terminating' */
3947+ if (new_state == FPM_PCTL_STATE_TERMINATING) break;
3948+
3949+ case FPM_PCTL_STATE_TERMINATING :
3950+
3951+ /* nothing can override 'terminating' state */
3952+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "not switching to '%s' state, because already in '%s' state",
3953+ fpm_state_names[new_state], fpm_state_names[fpm_state]);
3954+
3955+ return;
3956+ }
3957+
3958+ fpm_signal_sent = 0;
3959+ fpm_state = new_state;
3960+
3961+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "switching to '%s' state", fpm_state_names[fpm_state]);
3962+
3963+ /* fall down */
3964+
3965+ case FPM_PCTL_ACTION_TIMEOUT :
3966+
3967+ fpm_pctl_action_next();
3968+
3969+ break;
3970+
3971+ case FPM_PCTL_ACTION_LAST_CHILD_EXITED :
3972+
3973+ fpm_pctl_action_last();
3974+
3975+ break;
3976+
3977+ }
3978+}
3979+
3980+int fpm_pctl_can_spawn_children()
3981+{
3982+ return fpm_state == FPM_PCTL_STATE_NORMAL;
3983+}
3984+
3985+int fpm_pctl_child_exited()
3986+{
3987+ if (fpm_state == FPM_PCTL_STATE_NORMAL) return 0;
3988+
3989+ if (!fpm_globals.running_children) {
3990+ fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_LAST_CHILD_EXITED);
3991+ }
3992+
3993+ return 0;
3994+}
3995+
c6a6bfc9 3996+int fpm_pctl_init_main()
fd1be940 3997+{
c6a6bfc9 3998+ int i;
fd1be940 3999+
c6a6bfc9 4000+ saved_argc = fpm_globals.argc;
fd1be940 4001+
c6a6bfc9 4002+ saved_argv = malloc(sizeof(char *) * (saved_argc + 1));
fd1be940 4003+
c6a6bfc9
ER
4004+ if (!saved_argv) {
4005+ return -1;
4006+ }
fd1be940 4007+
c6a6bfc9
ER
4008+ for (i = 0; i < saved_argc; i++) {
4009+ saved_argv[i] = strdup(fpm_globals.argv[i]);
fd1be940 4010+
c6a6bfc9
ER
4011+ if (!saved_argv[i]) {
4012+ return -1;
4013+ }
fd1be940
ER
4014+ }
4015+
c6a6bfc9 4016+ saved_argv[i] = 0;
fd1be940
ER
4017+
4018+ fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_pctl_cleanup, 0);
4019+
4020+ return 0;
4021+}
4022+
c6a6bfc9
ER
4023+static void fpm_pctl_check_request_timeout(struct timeval *now)
4024+{
4025+ struct fpm_worker_pool_s *wp;
4026+
4027+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
4028+ int terminate_timeout = wp->config->request_terminate_timeout;
4029+ int slowlog_timeout = wp->config->request_slowlog_timeout;
4030+ struct fpm_child_s *child;
4031+
4032+ if (terminate_timeout || slowlog_timeout) {
4033+ for (child = wp->children; child; child = child->next) {
4034+ fpm_request_check_timed_out(child, now, terminate_timeout, slowlog_timeout);
4035+ }
4036+ }
4037+ }
4038+
4039+}
4040+
4041+void fpm_pctl_heartbeat(int fd, short which, void *arg)
4042+{
4043+ static struct event heartbeat;
4044+ struct timeval tv = { .tv_sec = 0, .tv_usec = 130000 };
4045+ struct timeval now;
4046+
4047+ if (which == EV_TIMEOUT) {
4048+ evtimer_del(&heartbeat);
4049+ fpm_clock_get(&now);
4050+ fpm_pctl_check_request_timeout(&now);
4051+ }
4052+
4053+ evtimer_set(&heartbeat, &fpm_pctl_heartbeat, 0);
4054+
4055+ evtimer_add(&heartbeat, &tv);
4056+}
4057+
8c0dac15
ER
4058diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_process_ctl.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_process_ctl.h
4059--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_process_ctl.h 1970-01-01 03:00:00.000000000 +0300
4060+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_process_ctl.h 2008-07-21 01:33:10.000000000 +0400
c6a6bfc9 4061@@ -0,0 +1,39 @@
fd1be940
ER
4062+
4063+ /* $Id$ */
c6a6bfc9 4064+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
4065+
4066+#ifndef FPM_PROCESS_CTL_H
4067+#define FPM_PROCESS_CTL_H 1
4068+
c6a6bfc9
ER
4069+struct fpm_child_s;
4070+
fd1be940
ER
4071+void fpm_pctl(int new_state, int action);
4072+int fpm_pctl_can_spawn_children();
c6a6bfc9
ER
4073+int fpm_pctl_kill(pid_t pid, int how);
4074+void fpm_pctl_heartbeat(int fd, short which, void *arg);
fd1be940 4075+int fpm_pctl_child_exited();
c6a6bfc9 4076+int fpm_pctl_init_main();
fd1be940
ER
4077+
4078+
4079+enum {
4080+ FPM_PCTL_STATE_UNSPECIFIED,
4081+ FPM_PCTL_STATE_NORMAL,
4082+ FPM_PCTL_STATE_RELOADING,
4083+ FPM_PCTL_STATE_TERMINATING,
4084+ FPM_PCTL_STATE_FINISHING
4085+};
4086+
4087+enum {
4088+ FPM_PCTL_ACTION_SET,
4089+ FPM_PCTL_ACTION_TIMEOUT,
4090+ FPM_PCTL_ACTION_LAST_CHILD_EXITED
4091+};
4092+
c6a6bfc9
ER
4093+enum {
4094+ FPM_PCTL_TERM,
4095+ FPM_PCTL_STOP,
4096+ FPM_PCTL_CONT
4097+};
fd1be940
ER
4098+
4099+#endif
4100+
8c0dac15
ER
4101diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_request.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_request.c
4102--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_request.c 1970-01-01 03:00:00.000000000 +0300
4103+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_request.c 2008-09-01 03:34:36.000000000 +0400
c6a6bfc9 4104@@ -0,0 +1,163 @@
fd1be940
ER
4105+
4106+ /* $Id$ */
c6a6bfc9
ER
4107+ /* (c) 2007,2008 Andrei Nigmatulin */
4108+
4109+#include "fpm_config.h"
4110+
4111+#include "fpm_php.h"
4112+#include "fpm_str.h"
4113+#include "fpm_clock.h"
4114+#include "fpm_conf.h"
4115+#include "fpm_trace.h"
4116+#include "fpm_php_trace.h"
4117+#include "fpm_process_ctl.h"
4118+#include "fpm_children.h"
4119+#include "fpm_shm_slots.h"
4120+#include "fpm_request.h"
fd1be940 4121+
c6a6bfc9
ER
4122+#include "zlog.h"
4123+
4124+void fpm_request_accepting()
4125+{
4126+ struct fpm_shm_slot_s *slot;
4127+
4128+ slot = fpm_shm_slots_acquire(0, 0);
4129+
4130+ slot->request_stage = FPM_REQUEST_ACCEPTING;
4131+
4132+ fpm_clock_get(&slot->tv);
4133+ memset(slot->request_method, 0, sizeof(slot->request_method));
4134+ slot->content_length = 0;
4135+ memset(slot->script_filename, 0, sizeof(slot->script_filename));
4136+
4137+ fpm_shm_slots_release(slot);
4138+}
4139+
4140+void fpm_request_reading_headers()
4141+{
4142+ struct fpm_shm_slot_s *slot;
4143+
4144+ slot = fpm_shm_slots_acquire(0, 0);
4145+
4146+ slot->request_stage = FPM_REQUEST_READING_HEADERS;
4147+
4148+ fpm_clock_get(&slot->tv);
4149+ slot->accepted = slot->tv;
4150+
4151+ fpm_shm_slots_release(slot);
4152+}
4153+
4154+void fpm_request_info()
4155+{
4156+ struct fpm_shm_slot_s *slot;
4157+ char *request_method = fpm_php_request_method();
4158+ char *script_filename = fpm_php_script_filename();
4159+
4160+ slot = fpm_shm_slots_acquire(0, 0);
4161+
4162+ slot->request_stage = FPM_REQUEST_INFO;
4163+
4164+ fpm_clock_get(&slot->tv);
4165+
4166+ if (request_method) {
4167+ cpystrn(slot->request_method, request_method, sizeof(slot->request_method));
4168+ }
4169+
4170+ slot->content_length = fpm_php_content_length();
4171+
4172+ /* if cgi.fix_pathinfo is set to "1" and script cannot be found (404)
4173+ the sapi_globals.request_info.path_translated is set to NULL */
4174+ if (script_filename) {
4175+ cpystrn(slot->script_filename, script_filename, sizeof(slot->script_filename));
4176+ }
4177+
4178+ fpm_shm_slots_release(slot);
4179+}
4180+
4181+void fpm_request_executing()
4182+{
4183+ struct fpm_shm_slot_s *slot;
4184+
4185+ slot = fpm_shm_slots_acquire(0, 0);
4186+
4187+ slot->request_stage = FPM_REQUEST_EXECUTING;
4188+
4189+ fpm_clock_get(&slot->tv);
4190+
4191+ fpm_shm_slots_release(slot);
4192+}
4193+
4194+void fpm_request_finished()
4195+{
4196+ struct fpm_shm_slot_s *slot;
4197+
4198+ slot = fpm_shm_slots_acquire(0, 0);
4199+
4200+ slot->request_stage = FPM_REQUEST_FINISHED;
4201+
4202+ fpm_clock_get(&slot->tv);
4203+ memset(&slot->accepted, 0, sizeof(slot->accepted));
4204+
4205+ fpm_shm_slots_release(slot);
4206+}
4207+
4208+void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, int terminate_timeout, int slowlog_timeout)
4209+{
4210+ struct fpm_shm_slot_s *slot;
4211+ struct fpm_shm_slot_s slot_c;
4212+
4213+ slot = fpm_shm_slot(child);
4214+
4215+ if (!fpm_shm_slots_acquire(slot, 1)) {
4216+ return;
4217+ }
4218+
4219+ slot_c = *slot;
4220+
4221+ fpm_shm_slots_release(slot);
4222+
4223+#if HAVE_FPM_TRACE
4224+ if (child->slow_logged.tv_sec) {
4225+ if (child->slow_logged.tv_sec != slot_c.accepted.tv_sec || child->slow_logged.tv_usec != slot_c.accepted.tv_usec) {
4226+ child->slow_logged.tv_sec = 0;
4227+ child->slow_logged.tv_usec = 0;
4228+ }
4229+ }
4230+#endif
4231+
4232+ if (slot_c.request_stage > FPM_REQUEST_ACCEPTING && slot_c.request_stage < FPM_REQUEST_FINISHED) {
4233+ char purified_script_filename[sizeof(slot_c.script_filename)];
4234+ struct timeval tv;
4235+
4236+ timersub(now, &slot_c.accepted, &tv);
4237+
4238+#if HAVE_FPM_TRACE
4239+ if (child->slow_logged.tv_sec == 0 && slowlog_timeout &&
4240+ slot_c.request_stage == FPM_REQUEST_EXECUTING && tv.tv_sec >= slowlog_timeout) {
4241+
4242+ str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename));
4243+
4244+ child->slow_logged = slot_c.accepted;
4245+ child->tracer = fpm_php_trace;
4246+
4247+ fpm_trace_signal(child->pid);
4248+
4249+ zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d, script '%s' (pool %s) executing too slow (%d.%06d sec), logging",
4250+ (int) child->pid, purified_script_filename, child->wp->config->name, (int) tv.tv_sec, (int) tv.tv_usec);
4251+ }
4252+
4253+ else
4254+#endif
4255+ if (terminate_timeout && tv.tv_sec >= terminate_timeout) {
4256+
4257+ str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename));
4258+
4259+ fpm_pctl_kill(child->pid, FPM_PCTL_TERM);
4260+
4261+ zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d, script '%s' (pool %s) execution timed out (%d.%06d sec), terminating",
4262+ (int) child->pid, purified_script_filename, child->wp->config->name, (int) tv.tv_sec, (int) tv.tv_usec);
4263+ }
4264+ }
4265+
4266+}
4267+
8c0dac15
ER
4268diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_request.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_request.h
4269--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_request.h 1970-01-01 03:00:00.000000000 +0300
4270+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_request.h 2008-07-20 05:47:16.000000000 +0400
c6a6bfc9 4271@@ -0,0 +1,27 @@
fd1be940
ER
4272+
4273+ /* $Id$ */
c6a6bfc9
ER
4274+ /* (c) 2007,2008 Andrei Nigmatulin */
4275+
4276+#ifndef FPM_REQUEST_H
4277+#define FPM_REQUEST_H 1
4278+
4279+void fpm_request_accepting(); /* hanging in accept() */
4280+void fpm_request_reading_headers(); /* start reading fastcgi request from very first byte */
4281+void fpm_request_info(); /* not a stage really but a point in the php code, where all request params have become known to sapi */
4282+void fpm_request_executing(); /* the script is executing */
4283+void fpm_request_finished(); /* request processed: script response have been sent to web server */
4284+
4285+struct fpm_child_s;
4286+struct timeval;
4287+
4288+void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *tv, int terminate_timeout, int slowlog_timeout);
4289+
4290+enum fpm_request_stage_e {
4291+ FPM_REQUEST_ACCEPTING = 1,
4292+ FPM_REQUEST_READING_HEADERS,
4293+ FPM_REQUEST_INFO,
4294+ FPM_REQUEST_EXECUTING,
4295+ FPM_REQUEST_FINISHED
4296+};
4297+
4298+#endif
8c0dac15
ER
4299diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm.c
4300--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm.c 1970-01-01 03:00:00.000000000 +0300
4301+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm.c 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9
ER
4302@@ -0,0 +1,100 @@
4303+
4304+ /* $Id$ */
4305+ /* (c) 2007,2008 Andrei Nigmatulin */
4306+
4307+#include "fpm_config.h"
4308+
4309+#include <unistd.h>
4310+#include <sys/mman.h>
4311+#include <stdlib.h>
4312+
4313+#include "fpm_shm.h"
4314+#include "zlog.h"
4315+
4316+
4317+/* MAP_ANON is depricated, but not in macosx */
4318+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
4319+#define MAP_ANONYMOUS MAP_ANON
4320+#endif
4321+
4322+
4323+struct fpm_shm_s *fpm_shm_alloc(size_t sz)
4324+{
4325+ struct fpm_shm_s *shm;
4326+
4327+ shm = malloc(sizeof(*shm));
4328+
4329+ if (!shm) {
4330+ return 0;
4331+ }
4332+
4333+ shm->mem = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
4334+
4335+ if (!shm->mem) {
4336+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "mmap(MAP_ANONYMOUS | MAP_SHARED) failed");
4337+ free(shm);
4338+ return 0;
4339+ }
4340+
4341+ shm->used = 0;
4342+ shm->sz = sz;
4343+
4344+ return shm;
4345+}
4346+
4347+static void fpm_shm_free(struct fpm_shm_s *shm, int do_unmap)
4348+{
4349+ if (do_unmap) {
4350+ munmap(shm->mem, shm->sz);
4351+ }
4352+
4353+ free(shm);
4354+}
4355+
4356+void fpm_shm_free_list(struct fpm_shm_s *shm, void *mem)
4357+{
4358+ struct fpm_shm_s *next;
4359+
4360+ for (; shm; shm = next) {
4361+ next = shm->next;
4362+
4363+ fpm_shm_free(shm, mem != shm->mem);
4364+ }
4365+}
4366+
4367+void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem)
4368+{
4369+ size_t pagesize = getpagesize();
4370+ static const size_t cache_line_size = 16;
4371+ size_t aligned_sz;
4372+ struct fpm_shm_s *shm;
4373+ void *ret;
4374+
4375+ sz = (sz + cache_line_size - 1) & -cache_line_size;
4376+
4377+ shm = *head;
4378+
4379+ if (0 == shm || shm->sz - shm->used < sz) {
4380+ /* allocate one more shm segment */
4381+
4382+ aligned_sz = (sz + pagesize - 1) & -pagesize;
4383+
4384+ shm = fpm_shm_alloc(aligned_sz);
4385+
4386+ if (!shm) {
4387+ return 0;
4388+ }
4389+
4390+ shm->next = *head;
4391+ if (shm->next) shm->next->prev = shm;
4392+ shm->prev = 0;
4393+ *head = shm;
4394+ }
4395+
4396+ *mem = shm->mem;
4397+ ret = (char *) shm->mem + shm->used;
4398+ shm->used += sz;
4399+
4400+ return ret;
4401+}
4402+
8c0dac15
ER
4403diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm.h
4404--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm.h 1970-01-01 03:00:00.000000000 +0300
4405+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm.h 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9
ER
4406@@ -0,0 +1,22 @@
4407+
4408+ /* $Id$ */
4409+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
4410+
4411+#ifndef FPM_SHM_H
4412+#define FPM_SHM_H 1
4413+
c6a6bfc9 4414+struct fpm_shm_s;
fd1be940 4415+
c6a6bfc9
ER
4416+struct fpm_shm_s {
4417+ struct fpm_shm_s *prev, *next;
4418+ void *mem;
4419+ size_t sz;
4420+ size_t used;
4421+};
4422+
4423+struct fpm_shm_s *fpm_shm_alloc(size_t sz);
4424+void fpm_shm_free_list(struct fpm_shm_s *, void *);
4425+void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem);
fd1be940
ER
4426+
4427+#endif
4428+
8c0dac15
ER
4429diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm_slots.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm_slots.c
4430--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm_slots.c 1970-01-01 03:00:00.000000000 +0300
4431+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm_slots.c 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9
ER
4432@@ -0,0 +1,127 @@
4433+
4434+ /* $Id$ */
4435+ /* (c) 2007,2008 Andrei Nigmatulin */
4436+
4437+#include "fpm_config.h"
4438+
4439+#include "fpm_atomic.h"
4440+#include "fpm_worker_pool.h"
4441+#include "fpm_children.h"
4442+#include "fpm_shm.h"
4443+#include "fpm_shm_slots.h"
4444+#include "zlog.h"
4445+
4446+static void *shm_mem;
4447+static struct fpm_shm_slot_s *shm_slot;
4448+
4449+int fpm_shm_slots_prepare_slot(struct fpm_child_s *child)
4450+{
4451+ struct fpm_worker_pool_s *wp = child->wp;
4452+ struct fpm_shm_slot_ptr_s *shm_slot_ptr;
4453+
4454+ child->shm_slot_i = wp->slots_used.used;
4455+
4456+ shm_slot_ptr = fpm_array_push(&wp->slots_used);
4457+
4458+ if (0 == shm_slot_ptr) {
4459+ return -1;
4460+ }
4461+
4462+ if (0 == wp->slots_free.used) {
4463+ shm_slot_ptr->shm_slot = fpm_shm_alloc_chunk(&wp->shm_list, sizeof(struct fpm_shm_slot_s), &shm_slot_ptr->mem);
4464+
4465+ if (!shm_slot_ptr->shm_slot) {
4466+ return -1;
4467+ }
4468+ }
4469+ else {
4470+ *shm_slot_ptr = *(struct fpm_shm_slot_ptr_s *) fpm_array_item_last(&wp->slots_free);
4471+
4472+ --wp->slots_free.used;
4473+ }
4474+
4475+ memset(shm_slot_ptr->shm_slot, 0, sizeof(struct fpm_shm_slot_s));
4476+
4477+ shm_slot_ptr->child = child;
4478+
4479+ return 0;
4480+}
4481+
4482+void fpm_shm_slots_discard_slot(struct fpm_child_s *child)
4483+{
4484+ struct fpm_shm_slot_ptr_s *shm_slot_ptr;
4485+ struct fpm_worker_pool_s *wp = child->wp;
4486+ int n;
4487+
4488+ shm_slot_ptr = fpm_array_push(&wp->slots_free);
4489+
4490+ if (shm_slot_ptr) {
4491+
4492+ struct fpm_shm_slot_ptr_s *shm_slot_ptr_used;
4493+
4494+ shm_slot_ptr_used = fpm_array_item(&wp->slots_used, child->shm_slot_i);
4495+
4496+ *shm_slot_ptr = *shm_slot_ptr_used;
4497+
4498+ shm_slot_ptr->child = 0;
4499+
4500+ }
4501+
4502+ n = fpm_array_item_remove(&wp->slots_used, child->shm_slot_i);
4503+
4504+ if (n > -1) {
4505+ shm_slot_ptr = fpm_array_item(&wp->slots_used, n);
4506+
4507+ shm_slot_ptr->child->shm_slot_i = n;
4508+ }
4509+}
4510+
4511+void fpm_shm_slots_child_use_slot(struct fpm_child_s *child)
4512+{
4513+ struct fpm_shm_slot_ptr_s *shm_slot_ptr;
4514+ struct fpm_worker_pool_s *wp = child->wp;
4515+
4516+ shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i);
4517+
4518+ shm_slot = shm_slot_ptr->shm_slot;
4519+ shm_mem = shm_slot_ptr->mem;
4520+}
4521+
4522+void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child)
4523+{
4524+ /* nothing to do */
4525+}
4526+
4527+void *fpm_shm_slots_mem()
4528+{
4529+ return shm_mem;
4530+}
4531+
4532+struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child)
4533+{
4534+ struct fpm_shm_slot_ptr_s *shm_slot_ptr;
4535+ struct fpm_worker_pool_s *wp = child->wp;
4536+
4537+ shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i);
4538+
4539+ return shm_slot_ptr->shm_slot;
4540+}
4541+
4542+struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *s, int nohang)
4543+{
4544+ if (s == 0) {
4545+ s = shm_slot;
4546+ }
4547+
4548+ if (0 > fpm_spinlock(&s->lock, nohang)) {
4549+ return 0;
4550+ }
4551+
4552+ return s;
4553+}
4554+
4555+void fpm_shm_slots_release(struct fpm_shm_slot_s *s)
4556+{
4557+ s->lock = 0;
4558+}
4559+
8c0dac15
ER
4560diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm_slots.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm_slots.h
4561--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm_slots.h 1970-01-01 03:00:00.000000000 +0300
4562+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm_slots.h 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9 4563@@ -0,0 +1,43 @@
fd1be940
ER
4564+
4565+ /* $Id$ */
c6a6bfc9
ER
4566+ /* (c) 2007,2008 Andrei Nigmatulin */
4567+
4568+#ifndef FPM_SHM_SLOTS_H
4569+#define FPM_SHM_SLOTS_H 1
4570+
4571+#include "fpm_atomic.h"
4572+#include "fpm_worker_pool.h"
4573+#include "fpm_request.h"
4574+
4575+struct fpm_child_s;
4576+
4577+struct fpm_shm_slot_s {
4578+ union {
4579+ atomic_t lock;
4580+ char dummy[16];
4581+ };
4582+ enum fpm_request_stage_e request_stage;
4583+ struct timeval accepted;
4584+ struct timeval tv;
4585+ char request_method[16];
4586+ size_t content_length; /* used with POST only */
4587+ char script_filename[256];
4588+};
4589+
4590+struct fpm_shm_slot_ptr_s {
4591+ void *mem;
4592+ struct fpm_shm_slot_s *shm_slot;
4593+ struct fpm_child_s *child;
4594+};
4595+
4596+int fpm_shm_slots_prepare_slot(struct fpm_child_s *child);
4597+void fpm_shm_slots_discard_slot(struct fpm_child_s *child);
4598+void fpm_shm_slots_child_use_slot(struct fpm_child_s *child);
4599+void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child);
4600+void *fpm_shm_slots_mem();
4601+struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child);
4602+struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *, int nohang);
4603+void fpm_shm_slots_release(struct fpm_shm_slot_s *);
4604+
4605+#endif
4606+
8c0dac15
ER
4607diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_signals.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_signals.c
4608--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_signals.c 1970-01-01 03:00:00.000000000 +0300
4609+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_signals.c 2008-08-26 19:09:15.000000000 +0400
c6a6bfc9
ER
4610@@ -0,0 +1,252 @@
4611+
4612+ /* $Id$ */
4613+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
4614+
4615+#include "fpm_config.h"
4616+
4617+#include <signal.h>
4618+#include <stdio.h>
4619+#include <sys/types.h>
4620+#include <sys/socket.h>
4621+#include <stdlib.h>
4622+#include <string.h>
4623+#include <fcntl.h>
4624+#include <unistd.h>
4625+#include <errno.h>
4626+
c6a6bfc9 4627+#include "fpm.h"
fd1be940
ER
4628+#include "fpm_signals.h"
4629+#include "fpm_sockets.h"
c6a6bfc9 4630+#include "fpm_php.h"
fd1be940
ER
4631+#include "zlog.h"
4632+
4633+static int sp[2];
4634+
fd1be940
ER
4635+const char *fpm_signal_names[NSIG + 1] = {
4636+#ifdef SIGHUP
4637+ [SIGHUP] = "SIGHUP",
4638+#endif
4639+#ifdef SIGINT
4640+ [SIGINT] = "SIGINT",
4641+#endif
4642+#ifdef SIGQUIT
4643+ [SIGQUIT] = "SIGQUIT",
4644+#endif
4645+#ifdef SIGILL
4646+ [SIGILL] = "SIGILL",
4647+#endif
4648+#ifdef SIGTRAP
4649+ [SIGTRAP] = "SIGTRAP",
4650+#endif
4651+#ifdef SIGABRT
4652+ [SIGABRT] = "SIGABRT",
4653+#endif
4654+#ifdef SIGEMT
4655+ [SIGEMT] = "SIGEMT",
4656+#endif
4657+#ifdef SIGBUS
4658+ [SIGBUS] = "SIGBUS",
4659+#endif
4660+#ifdef SIGFPE
4661+ [SIGFPE] = "SIGFPE",
4662+#endif
4663+#ifdef SIGKILL
4664+ [SIGKILL] = "SIGKILL",
4665+#endif
4666+#ifdef SIGUSR1
4667+ [SIGUSR1] = "SIGUSR1",
4668+#endif
4669+#ifdef SIGSEGV
4670+ [SIGSEGV] = "SIGSEGV",
4671+#endif
4672+#ifdef SIGUSR2
4673+ [SIGUSR2] = "SIGUSR2",
4674+#endif
4675+#ifdef SIGPIPE
4676+ [SIGPIPE] = "SIGPIPE",
4677+#endif
4678+#ifdef SIGALRM
4679+ [SIGALRM] = "SIGALRM",
4680+#endif
4681+#ifdef SIGTERM
4682+ [SIGTERM] = "SIGTERM",
4683+#endif
4684+#ifdef SIGCHLD
4685+ [SIGCHLD] = "SIGCHLD",
4686+#endif
4687+#ifdef SIGCONT
4688+ [SIGCONT] = "SIGCONT",
4689+#endif
4690+#ifdef SIGSTOP
4691+ [SIGSTOP] = "SIGSTOP",
4692+#endif
4693+#ifdef SIGTSTP
4694+ [SIGTSTP] = "SIGTSTP",
4695+#endif
4696+#ifdef SIGTTIN
4697+ [SIGTTIN] = "SIGTTIN",
4698+#endif
4699+#ifdef SIGTTOU
4700+ [SIGTTOU] = "SIGTTOU",
4701+#endif
4702+#ifdef SIGURG
4703+ [SIGURG] = "SIGURG",
4704+#endif
4705+#ifdef SIGXCPU
4706+ [SIGXCPU] = "SIGXCPU",
4707+#endif
4708+#ifdef SIGXFSZ
4709+ [SIGXFSZ] = "SIGXFSZ",
4710+#endif
4711+#ifdef SIGVTALRM
4712+ [SIGVTALRM] = "SIGVTALRM",
4713+#endif
4714+#ifdef SIGPROF
4715+ [SIGPROF] = "SIGPROF",
4716+#endif
4717+#ifdef SIGWINCH
4718+ [SIGWINCH] = "SIGWINCH",
4719+#endif
4720+#ifdef SIGINFO
4721+ [SIGINFO] = "SIGINFO",
4722+#endif
4723+#ifdef SIGIO
4724+ [SIGIO] = "SIGIO",
4725+#endif
4726+#ifdef SIGPWR
4727+ [SIGPWR] = "SIGPWR",
4728+#endif
4729+#ifdef SIGSYS
4730+ [SIGSYS] = "SIGSYS",
4731+#endif
4732+#ifdef SIGWAITING
4733+ [SIGWAITING] = "SIGWAITING",
4734+#endif
4735+#ifdef SIGLWP
4736+ [SIGLWP] = "SIGLWP",
4737+#endif
4738+#ifdef SIGFREEZE
4739+ [SIGFREEZE] = "SIGFREEZE",
4740+#endif
4741+#ifdef SIGTHAW
4742+ [SIGTHAW] = "SIGTHAW",
4743+#endif
4744+#ifdef SIGCANCEL
4745+ [SIGCANCEL] = "SIGCANCEL",
4746+#endif
4747+#ifdef SIGLOST
4748+ [SIGLOST] = "SIGLOST",
4749+#endif
4750+};
4751+
4752+static void sig_soft_quit(int signo)
4753+{
c6a6bfc9
ER
4754+ int saved_errno = errno;
4755+
fd1be940
ER
4756+ /* closing fastcgi listening socket will force fcgi_accept() exit immediately */
4757+ close(0);
4758+ socket(AF_UNIX, SOCK_STREAM, 0);
c6a6bfc9
ER
4759+
4760+ fpm_php_soft_quit();
4761+
4762+ errno = saved_errno;
fd1be940
ER
4763+}
4764+
4765+static void sig_handler(int signo)
4766+{
c6a6bfc9 4767+ static const char sig_chars[NSIG + 1] = {
fd1be940
ER
4768+ [SIGTERM] = 'T',
4769+ [SIGINT] = 'I',
c6a6bfc9 4770+ [SIGUSR1] = '1',
fd1be940
ER
4771+ [SIGUSR2] = '2',
4772+ [SIGQUIT] = 'Q',
4773+ [SIGCHLD] = 'C'
4774+ };
c6a6bfc9
ER
4775+ char s;
4776+ int saved_errno;
fd1be940 4777+
c6a6bfc9
ER
4778+ if (fpm_globals.parent_pid != getpid()) {
4779+ /* prevent a signal race condition when child process
4780+ have not set up it's own signal handler yet */
4781+ return;
fd1be940
ER
4782+ }
4783+
c6a6bfc9
ER
4784+ saved_errno = errno;
4785+
4786+ s = sig_chars[signo];
4787+
4788+ write(sp[1], &s, sizeof(s));
4789+
fd1be940
ER
4790+ errno = saved_errno;
4791+}
4792+
4793+int fpm_signals_init_main()
4794+{
4795+ struct sigaction act;
4796+
4797+ if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) {
4798+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "socketpair() failed");
4799+ return -1;
4800+ }
4801+
4802+ if (0 > fd_set_blocked(sp[0], 0) || 0 > fd_set_blocked(sp[1], 0)) {
4803+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fd_set_blocked() failed");
4804+ return -1;
4805+ }
4806+
4807+ if (0 > fcntl(sp[0], F_SETFD, FD_CLOEXEC) || 0 > fcntl(sp[1], F_SETFD, FD_CLOEXEC)) {
4808+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fcntl(F_SETFD, FD_CLOEXEC) failed");
4809+ return -1;
4810+ }
4811+
4812+ memset(&act, 0, sizeof(act));
c6a6bfc9 4813+ act.sa_handler = sig_handler;
fd1be940
ER
4814+ sigfillset(&act.sa_mask);
4815+
4816+ if (0 > sigaction(SIGTERM, &act, 0) ||
4817+ 0 > sigaction(SIGINT, &act, 0) ||
c6a6bfc9 4818+ 0 > sigaction(SIGUSR1, &act, 0) ||
fd1be940
ER
4819+ 0 > sigaction(SIGUSR2, &act, 0) ||
4820+ 0 > sigaction(SIGCHLD, &act, 0) ||
4821+ 0 > sigaction(SIGQUIT, &act, 0)) {
4822+
4823+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed");
4824+ return -1;
4825+ }
4826+
4827+ return 0;
4828+}
4829+
4830+int fpm_signals_init_child()
4831+{
4832+ struct sigaction act, act_dfl;
4833+
4834+ memset(&act, 0, sizeof(act));
4835+ memset(&act_dfl, 0, sizeof(act_dfl));
4836+
c6a6bfc9 4837+ act.sa_handler = &sig_soft_quit;
fd1be940
ER
4838+ act.sa_flags |= SA_RESTART;
4839+
4840+ act_dfl.sa_handler = SIG_DFL;
4841+
4842+ close(sp[0]);
4843+ close(sp[1]);
4844+
4845+ if (0 > sigaction(SIGTERM, &act_dfl, 0) ||
4846+ 0 > sigaction(SIGINT, &act_dfl, 0) ||
c6a6bfc9 4847+ 0 > sigaction(SIGUSR1, &act_dfl, 0) ||
fd1be940
ER
4848+ 0 > sigaction(SIGUSR2, &act_dfl, 0) ||
4849+ 0 > sigaction(SIGCHLD, &act_dfl, 0) ||
4850+ 0 > sigaction(SIGQUIT, &act, 0)) {
4851+
4852+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed");
4853+ return -1;
4854+ }
4855+
4856+ return 0;
4857+}
4858+
4859+int fpm_signals_get_fd()
4860+{
4861+ return sp[0];
4862+}
8c0dac15
ER
4863diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_signals.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_signals.h
4864--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_signals.h 1970-01-01 03:00:00.000000000 +0300
4865+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_signals.h 2008-05-24 21:38:47.000000000 +0400
fd1be940
ER
4866@@ -0,0 +1,16 @@
4867+
4868+ /* $Id$ */
c6a6bfc9 4869+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
4870+
4871+#ifndef FPM_SIGNALS_H
4872+#define FPM_SIGNALS_H 1
4873+
4874+#include <signal.h>
4875+
4876+int fpm_signals_init_main();
4877+int fpm_signals_init_child();
4878+int fpm_signals_get_fd();
4879+
4880+extern const char *fpm_signal_names[NSIG + 1];
4881+
4882+#endif
8c0dac15
ER
4883diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_sockets.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_sockets.c
4884--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_sockets.c 1970-01-01 03:00:00.000000000 +0300
4885+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_sockets.c 2008-08-26 19:09:15.000000000 +0400
c6a6bfc9 4886@@ -0,0 +1,425 @@
fd1be940
ER
4887+
4888+ /* $Id$ */
c6a6bfc9 4889+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
4890+
4891+#include "fpm_config.h"
4892+
4893+#ifdef HAVE_ALLOCA_H
4894+#include <alloca.h>
4895+#endif
4896+#include <sys/types.h>
4897+#include <sys/stat.h> /* for chmod(2) */
4898+#include <sys/socket.h>
4899+#include <netinet/in.h>
4900+#include <arpa/inet.h>
4901+#include <sys/un.h>
4902+#include <netdb.h>
4903+#include <stdio.h>
4904+#include <stdlib.h>
4905+#include <string.h>
4906+#include <errno.h>
4907+#include <unistd.h>
4908+
4909+#include "zlog.h"
c6a6bfc9 4910+#include "fpm_arrays.h"
fd1be940
ER
4911+#include "fpm_sockets.h"
4912+#include "fpm_worker_pool.h"
4913+#include "fpm_unix.h"
c6a6bfc9 4914+#include "fpm_str.h"
fd1be940
ER
4915+#include "fpm_env.h"
4916+#include "fpm_cleanup.h"
4917+
c6a6bfc9 4918+struct listening_socket_s {
fd1be940
ER
4919+ int refcount;
4920+ int sock;
4921+ int type;
4922+ char *key;
4923+};
4924+
c6a6bfc9 4925+static struct fpm_array_s sockets_list;
fd1be940
ER
4926+
4927+static int fpm_sockets_resolve_af_inet(char *node, char *service, struct sockaddr_in *addr)
4928+{
4929+ struct addrinfo *res;
4930+ struct addrinfo hints;
4931+ int ret;
4932+
4933+ memset(&hints, 0, sizeof(hints));
4934+
4935+ hints.ai_family = AF_INET;
4936+
4937+ ret = getaddrinfo(node, service, &hints, &res);
4938+
4939+ if (ret != 0) {
4940+ zlog(ZLOG_STUFF, ZLOG_ERROR, "can't resolve hostname '%s%s%s': getaddrinfo said: %s%s%s\n",
4941+ node, service ? ":" : "", service ? service : "",
4942+ gai_strerror(ret), ret == EAI_SYSTEM ? ", system error: " : "", ret == EAI_SYSTEM ? strerror(errno) : "");
4943+ return -1;
4944+ }
4945+
4946+ *addr = *(struct sockaddr_in *) res->ai_addr;
4947+
4948+ freeaddrinfo(res);
4949+
4950+ return 0;
4951+}
4952+
4953+enum { FPM_GET_USE_SOCKET = 1, FPM_STORE_SOCKET = 2, FPM_STORE_USE_SOCKET = 3 };
4954+
4955+static void fpm_sockets_cleanup(int which, void *arg)
4956+{
4957+ int i;
4958+ char *env_value = 0;
4959+ int p = 0;
c6a6bfc9 4960+ struct listening_socket_s *ls = sockets_list.data;
fd1be940 4961+
c6a6bfc9 4962+ for (i = 0; i < sockets_list.used; i++, ls++) {
fd1be940
ER
4963+
4964+ if (which != FPM_CLEANUP_PARENT_EXEC) {
4965+
4966+ close(ls->sock);
4967+
4968+ }
4969+ else { /* on PARENT EXEC we want socket fds to be inherited through environment variable */
4970+ char fd[32];
4971+ sprintf(fd, "%d", ls->sock);
4972+ env_value = realloc(env_value, p + (p ? 1 : 0) + strlen(ls->key) + 1 + strlen(fd) + 1);
4973+ p += sprintf(env_value + p, "%s%s=%s", p ? "," : "", ls->key, fd);
4974+ }
4975+
4976+ if (which == FPM_CLEANUP_PARENT_EXIT_MAIN) {
4977+
4978+ if (ls->type == FPM_AF_UNIX) {
4979+ unlink(ls->key);
4980+ }
4981+
4982+ }
4983+
4984+ free(ls->key);
4985+ }
4986+
4987+ if (env_value) {
4988+ setenv("FPM_SOCKETS", env_value, 1);
c6a6bfc9 4989+ free(env_value);
fd1be940
ER
4990+ }
4991+
c6a6bfc9 4992+ fpm_array_free(&sockets_list);
fd1be940
ER
4993+}
4994+
4995+static int fpm_sockets_hash_op(int sock, struct sockaddr *sa, char *key, int type, int op)
4996+{
4997+
4998+ if (key == NULL) {
4999+
5000+ switch (type) {
5001+
5002+ case FPM_AF_INET : {
5003+ struct sockaddr_in *sa_in = (struct sockaddr_in *) sa;
5004+
5005+ key = alloca(sizeof("xxx.xxx.xxx.xxx:ppppp"));
5006+
c6a6bfc9 5007+ sprintf(key, "%u.%u.%u.%u:%u", IPQUAD(&sa_in->sin_addr), (unsigned int) ntohs(sa_in->sin_port));
fd1be940
ER
5008+
5009+ break;
5010+ }
5011+
5012+ case FPM_AF_UNIX : {
5013+ struct sockaddr_un *sa_un = (struct sockaddr_un *) sa;
5014+
5015+ key = alloca(strlen(sa_un->sun_path) + 1);
5016+
5017+ strcpy(key, sa_un->sun_path);
5018+
5019+ break;
5020+ }
5021+
5022+ default :
5023+
5024+ return -1;
5025+ }
5026+
5027+ }
5028+
5029+ switch (op) {
5030+
5031+ case FPM_GET_USE_SOCKET :
5032+ {
5033+
5034+ int i;
c6a6bfc9 5035+ struct listening_socket_s *ls = sockets_list.data;
fd1be940 5036+
c6a6bfc9 5037+ for (i = 0; i < sockets_list.used; i++, ls++) {
fd1be940
ER
5038+
5039+ if (!strcmp(ls->key, key)) {
5040+ ++ls->refcount;
5041+ return ls->sock;
5042+ }
5043+ }
5044+
5045+ break;
5046+ }
5047+
5048+ case FPM_STORE_SOCKET : /* inherited socket */
5049+ case FPM_STORE_USE_SOCKET : /* just created */
5050+ {
5051+
c6a6bfc9 5052+ struct listening_socket_s *ls;
fd1be940 5053+
c6a6bfc9 5054+ ls = fpm_array_push(&sockets_list);
fd1be940 5055+
c6a6bfc9
ER
5056+ if (!ls) {
5057+ break;
fd1be940
ER
5058+ }
5059+
fd1be940
ER
5060+ if (op == FPM_STORE_SOCKET) {
5061+ ls->refcount = 0;
5062+ }
5063+ else {
5064+ ls->refcount = 1;
5065+ }
5066+ ls->type = type;
5067+ ls->sock = sock;
5068+ ls->key = strdup(key);
5069+
fd1be940
ER
5070+ return 0;
5071+
5072+ }
5073+ }
5074+
5075+ return -1;
5076+
5077+}
5078+
5079+static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct sockaddr *sa, int socklen)
5080+{
5081+ int backlog = -1;
5082+ int flags = 1;
5083+ int sock;
5084+ mode_t saved_umask;
5085+
5086+ /* we have custom backlog value */
5087+ if (wp->config->listen_options) {
5088+ backlog = wp->config->listen_options->backlog;
5089+ }
5090+
5091+ sock = socket(sa->sa_family, SOCK_STREAM, 0);
5092+
5093+ if (0 > sock) {
5094+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "socket() failed");
5095+ return -1;
5096+ }
5097+
5098+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
5099+
5100+ if (wp->listen_address_domain == FPM_AF_UNIX) {
5101+ unlink( ((struct sockaddr_un *) sa)->sun_path);
5102+ }
5103+
5104+ saved_umask = umask(0777 ^ wp->socket_mode);
5105+
5106+ if (0 > bind(sock, sa, socklen)) {
5107+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "bind() for address '%s' failed", wp->config->listen_address);
5108+ return -1;
5109+ }
5110+
5111+ if (wp->listen_address_domain == FPM_AF_UNIX) {
5112+
5113+ char *path = ((struct sockaddr_un *) sa)->sun_path;
5114+
5115+ if (wp->socket_uid != -1 || wp->socket_gid != -1) {
5116+
5117+ if (0 > chown(path, wp->socket_uid, wp->socket_gid)) {
5118+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chown() for address '%s' failed", wp->config->listen_address);
5119+ return -1;
5120+ }
5121+
5122+ }
5123+
5124+ }
5125+
5126+ umask(saved_umask);
5127+
5128+ if (0 > listen(sock, backlog)) {
5129+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "listen() for address '%s' failed", wp->config->listen_address);
5130+ return -1;
5131+ }
5132+
5133+ return sock;
5134+}
5135+
5136+static int fpm_sockets_get_listening_socket(struct fpm_worker_pool_s *wp, struct sockaddr *sa, int socklen)
5137+{
5138+ int sock;
5139+
5140+ sock = fpm_sockets_hash_op(0, sa, 0, wp->listen_address_domain, FPM_GET_USE_SOCKET);
5141+
5142+ if (sock >= 0) return sock;
5143+
5144+ sock = fpm_sockets_new_listening_socket(wp, sa, socklen);
5145+
5146+ fpm_sockets_hash_op(sock, sa, 0, wp->listen_address_domain, FPM_STORE_USE_SOCKET);
5147+
5148+ return sock;
5149+}
5150+
5151+enum fpm_address_domain fpm_sockets_domain_from_address(char *address)
5152+{
5153+ if (strchr(address, ':')) return FPM_AF_INET;
5154+
5155+ if (strlen(address) == strspn(address, "0123456789")) return FPM_AF_INET;
5156+
5157+ return FPM_AF_UNIX;
5158+}
5159+
5160+static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp)
5161+{
5162+ struct sockaddr_in sa_in;
5163+ char *dup_address = strdup(wp->config->listen_address);
5164+ char *port_str = strchr(dup_address, ':');
5165+ char *addr = NULL;
5166+ int port = 0;
5167+
5168+ if (port_str) { /* this is host:port pair */
5169+ *port_str++ = '\0';
5170+ port = atoi(port_str);
5171+ addr = dup_address;
5172+ }
5173+ else if (strlen(dup_address) == strspn(dup_address, "0123456789")) { /* this is port */
5174+ port = atoi(dup_address);
5175+ port_str = dup_address;
5176+ }
5177+
5178+ if (port == 0) {
5179+ zlog(ZLOG_STUFF, ZLOG_ERROR, "invalid port value '%s'", port_str);
5180+ return -1;
5181+ }
5182+
5183+ memset(&sa_in, 0, sizeof(sa_in));
5184+
5185+ if (addr) {
5186+
5187+ sa_in.sin_addr.s_addr = inet_addr(addr);
5188+
5189+ if (sa_in.sin_addr.s_addr == INADDR_NONE) { /* do resolve */
5190+ if (0 > fpm_sockets_resolve_af_inet(addr, NULL, &sa_in)) {
5191+ return -1;
5192+ }
5193+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "address '%s' resolved as %u.%u.%u.%u", addr, IPQUAD(&sa_in.sin_addr));
5194+ }
5195+ }
5196+ else {
5197+
5198+ sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
5199+
5200+ }
5201+
5202+ sa_in.sin_family = AF_INET;
5203+ sa_in.sin_port = htons(port);
5204+
5205+ free(dup_address);
5206+
5207+ return fpm_sockets_get_listening_socket(wp, (struct sockaddr *) &sa_in, sizeof(struct sockaddr_in));
5208+}
5209+
5210+static int fpm_socket_af_unix_listening_socket(struct fpm_worker_pool_s *wp)
5211+{
5212+ struct sockaddr_un sa_un;
5213+
5214+ memset(&sa_un, 0, sizeof(sa_un));
5215+
c6a6bfc9 5216+ cpystrn(sa_un.sun_path, wp->config->listen_address, sizeof(sa_un.sun_path));
fd1be940 5217+ sa_un.sun_family = AF_UNIX;
fd1be940
ER
5218+
5219+ return fpm_sockets_get_listening_socket(wp, (struct sockaddr *) &sa_un, sizeof(struct sockaddr_un));
5220+}
5221+
5222+int fpm_sockets_init_main()
5223+{
5224+ int i;
5225+ struct fpm_worker_pool_s *wp;
5226+ char *inherited = getenv("FPM_SOCKETS");
c6a6bfc9
ER
5227+ struct listening_socket_s *ls;
5228+
5229+ if (0 == fpm_array_init(&sockets_list, sizeof(struct listening_socket_s), 10)) {
5230+ return -1;
5231+ }
fd1be940
ER
5232+
5233+ /* import inherited sockets */
5234+ while (inherited && *inherited) {
5235+ char *comma = strchr(inherited, ',');
5236+ int type, fd_no;
5237+ char *eq;
5238+
5239+ if (comma) *comma = '\0';
5240+
5241+ eq = strchr(inherited, '=');
5242+
5243+ if (eq) {
5244+ *eq = '\0';
5245+
5246+ fd_no = atoi(eq + 1);
5247+
5248+ type = fpm_sockets_domain_from_address(inherited);
5249+
5250+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "using inherited socket fd=%d, \"%s\"", fd_no, inherited);
5251+
5252+ fpm_sockets_hash_op(fd_no, 0, inherited, type, FPM_STORE_SOCKET);
5253+ }
5254+
5255+ if (comma) inherited = comma + 1;
5256+ else inherited = 0;
5257+ }
5258+
c6a6bfc9 5259+ /* create all required sockets */
fd1be940
ER
5260+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
5261+
5262+ if (!wp->is_template) {
5263+
5264+ switch (wp->listen_address_domain) {
5265+
5266+ case FPM_AF_INET :
5267+
5268+ wp->listening_socket = fpm_socket_af_inet_listening_socket(wp);
5269+ break;
5270+
5271+ case FPM_AF_UNIX :
5272+
5273+ if (0 > fpm_unix_resolve_socket_premissions(wp)) {
5274+ return -1;
5275+ }
5276+
5277+ wp->listening_socket = fpm_socket_af_unix_listening_socket(wp);
5278+ break;
5279+
5280+ }
5281+
5282+ if (wp->listening_socket == -1) {
5283+ return -1;
5284+ }
5285+ }
5286+
5287+ }
5288+
5289+ /* close unused sockets that was inherited */
c6a6bfc9
ER
5290+ ls = sockets_list.data;
5291+
5292+ for (i = 0; i < sockets_list.used; ) {
fd1be940
ER
5293+
5294+ if (ls->refcount == 0) {
5295+ close(ls->sock);
5296+ if (ls->type == FPM_AF_UNIX) {
5297+ unlink(ls->key);
5298+ }
5299+ free(ls->key);
c6a6bfc9 5300+ fpm_array_item_remove(&sockets_list, i);
fd1be940
ER
5301+ }
5302+ else {
5303+ ++i;
c6a6bfc9 5304+ ++ls;
fd1be940
ER
5305+ }
5306+ }
5307+
5308+ fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_sockets_cleanup, 0);
5309+
5310+ return 0;
5311+}
8c0dac15
ER
5312diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_sockets.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_sockets.h
5313--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_sockets.h 1970-01-01 03:00:00.000000000 +0300
5314+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_sockets.h 2008-08-26 19:09:15.000000000 +0400
fd1be940
ER
5315@@ -0,0 +1,37 @@
5316+
5317+ /* $Id$ */
c6a6bfc9 5318+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
5319+
5320+#ifndef FPM_MISC_H
5321+#define FPM_MISC_H 1
5322+
5323+#include <unistd.h>
5324+#include <fcntl.h>
5325+
5326+#include "fpm_worker_pool.h"
5327+
5328+enum fpm_address_domain fpm_sockets_domain_from_address(char *addr);
5329+int fpm_sockets_init_main();
5330+
5331+
5332+static inline int fd_set_blocked(int fd, int blocked)
5333+{
5334+ int flags = fcntl(fd, F_GETFL);
5335+
5336+ if (flags < 0) return -1;
5337+
5338+ if (blocked)
5339+ flags &= ~O_NONBLOCK;
5340+ else
5341+ flags |= O_NONBLOCK;
5342+
5343+ return fcntl(fd, F_SETFL, flags);
5344+}
5345+
5346+#define IPQUAD(sin_addr) \
c6a6bfc9
ER
5347+ (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[0], \
5348+ (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[1], \
5349+ (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[2], \
5350+ (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[3]
fd1be940
ER
5351+
5352+#endif
8c0dac15
ER
5353diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_stdio.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_stdio.c
5354--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_stdio.c 1970-01-01 03:00:00.000000000 +0300
5355+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_stdio.c 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9 5356@@ -0,0 +1,277 @@
fd1be940
ER
5357+
5358+ /* $Id$ */
c6a6bfc9 5359+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
5360+
5361+#include "fpm_config.h"
5362+
5363+#include <sys/types.h>
5364+#include <sys/stat.h>
5365+#include <string.h>
5366+#include <fcntl.h>
5367+#include <unistd.h>
5368+#include <errno.h>
5369+
5370+#include "fpm.h"
5371+#include "fpm_children.h"
5372+#include "fpm_events.h"
5373+#include "fpm_sockets.h"
5374+#include "fpm_stdio.h"
5375+#include "zlog.h"
5376+
c6a6bfc9
ER
5377+static int fd_stdout[2];
5378+static int fd_stderr[2];
5379+
fd1be940
ER
5380+int fpm_stdio_init_main()
5381+{
c6a6bfc9 5382+ int fd = open("/dev/null", O_RDWR);
fd1be940
ER
5383+
5384+ if (0 > fd) {
c6a6bfc9 5385+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(\"/dev/null\") failed");
fd1be940
ER
5386+ return -1;
5387+ }
5388+
5389+ dup2(fd, STDIN_FILENO);
5390+ dup2(fd, STDOUT_FILENO);
5391+ close(fd);
5392+
5393+ return 0;
5394+}
5395+
5396+int fpm_stdio_init_final()
5397+{
5398+ if (fpm_global_options.daemonize) {
5399+
5400+ if (fpm_globals.error_log_fd != STDERR_FILENO) {
c6a6bfc9 5401+ /* there might be messages to stderr from libevent, we need to log them all */
fd1be940
ER
5402+ dup2(fpm_globals.error_log_fd, STDERR_FILENO);
5403+ }
5404+
c6a6bfc9
ER
5405+ zlog_set_level(fpm_globals.log_level);
5406+
fd1be940
ER
5407+ zlog_set_fd(fpm_globals.error_log_fd);
5408+ }
5409+
5410+ return 0;
5411+}
5412+
5413+int fpm_stdio_init_child(struct fpm_worker_pool_s *wp)
5414+{
fd1be940
ER
5415+ close(fpm_globals.error_log_fd);
5416+ fpm_globals.error_log_fd = -1;
c6a6bfc9 5417+ zlog_set_fd(-1);
fd1be940
ER
5418+
5419+ if (wp->listening_socket != STDIN_FILENO) {
5420+ dup2(wp->listening_socket, STDIN_FILENO);
5421+ }
5422+
5423+ return 0;
5424+}
5425+
fd1be940
ER
5426+static void fpm_stdio_child_said(int fd, short which, void *arg)
5427+{
5428+ static const int max_buf_size = 1024;
5429+ char buf[max_buf_size];
5430+ struct fpm_child_s *child = arg;
5431+ int is_stdout = fd == child->fd_stdout;
5432+ struct event *ev = is_stdout ? &child->ev_stdout : &child->ev_stderr;
5433+ int fifo_in = 1, fifo_out = 1;
5434+ int is_last_message = 0;
5435+ int in_buf = 0;
5436+ int res;
5437+
5438+#if 0
5439+ zlog(ZLOG_STUFF, ZLOG_DEBUG, "child %d said %s", (int) child->pid, is_stdout ? "stdout" : "stderr");
5440+#endif
5441+
5442+ while (fifo_in || fifo_out) {
5443+
5444+ if (fifo_in) {
5445+
5446+ res = read(fd, buf + in_buf, max_buf_size - 1 - in_buf);
5447+
5448+ if (res <= 0) { /* no data */
5449+ fifo_in = 0;
5450+
5451+ if (res < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
5452+ /* just no more data ready */
5453+ }
5454+ else { /* error or pipe is closed */
5455+
5456+ if (res < 0) { /* error */
5457+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed");
5458+ }
5459+
5460+ fpm_event_del(ev);
5461+ is_last_message = 1;
5462+
5463+ if (is_stdout) {
5464+ close(child->fd_stdout);
5465+ child->fd_stdout = -1;
5466+ }
5467+ else {
5468+ close(child->fd_stderr);
5469+ child->fd_stderr = -1;
5470+ }
5471+
5472+#if 0
5473+ if (in_buf == 0 && !fpm_globals.is_child) {
5474+ zlog(ZLOG_STUFF, ZLOG_DEBUG, "child %d (pool %s) %s pipe is closed", (int) child->pid,
5475+ child->wp->config->name, is_stdout ? "stdout" : "stderr");
5476+ }
5477+#endif
5478+ }
5479+ }
5480+ else {
5481+ in_buf += res;
5482+ }
5483+ }
5484+
5485+ if (fifo_out) {
5486+ if (in_buf == 0) {
5487+ fifo_out = 0;
5488+ }
5489+ else {
5490+ char *nl;
5491+ int should_print = 0;
5492+ buf[in_buf] = '\0';
5493+
5494+ /* FIXME: there might be binary data */
5495+
5496+ /* we should print if no more space in the buffer */
5497+ if (in_buf == max_buf_size - 1) {
5498+ should_print = 1;
5499+ }
5500+
5501+ /* we should print if no more data to come */
5502+ if (!fifo_in) {
5503+ should_print = 1;
5504+ }
5505+
5506+ nl = strchr(buf, '\n');
5507+
5508+ if (nl || should_print) {
5509+
5510+ if (nl) {
5511+ *nl = '\0';
5512+ }
5513+
5514+ zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d (pool %s) said into %s: \"%s\"%s", (int) child->pid,
5515+ child->wp->config->name, is_stdout ? "stdout" : "stderr", buf, is_last_message ? ", pipe is closed" : "");
5516+
5517+ if (nl) {
5518+ int out_buf = 1 + nl - buf;
5519+ memmove(buf, buf + out_buf, in_buf - out_buf);
5520+ in_buf -= out_buf;
5521+ }
5522+ else {
5523+ in_buf = 0;
5524+ }
5525+ }
5526+ }
5527+ }
5528+ }
5529+
5530+}
5531+
c6a6bfc9 5532+int fpm_stdio_prepare_pipes(struct fpm_child_s *child)
fd1be940 5533+{
c6a6bfc9 5534+ if (0 == child->wp->config->catch_workers_output) { /* not required */
fd1be940
ER
5535+ return 0;
5536+ }
5537+
c6a6bfc9
ER
5538+ if (0 > pipe(fd_stdout)) {
5539+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pipe() failed");
5540+ return -1;
5541+ }
5542+
5543+ if (0 > pipe(fd_stderr)) {
5544+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pipe() failed");
5545+ close(fd_stdout[0]); close(fd_stdout[1]);
5546+ return -1;
5547+ }
fd1be940 5548+
c6a6bfc9
ER
5549+ if (0 > fd_set_blocked(fd_stdout[0], 0) || 0 > fd_set_blocked(fd_stderr[0], 0)) {
5550+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fd_set_blocked() failed");
5551+ close(fd_stdout[0]); close(fd_stdout[1]);
5552+ close(fd_stderr[0]); close(fd_stderr[1]);
5553+ return -1;
5554+ }
fd1be940 5555+
c6a6bfc9
ER
5556+ return 0;
5557+}
5558+
5559+int fpm_stdio_parent_use_pipes(struct fpm_child_s *child)
5560+{
5561+ if (0 == child->wp->config->catch_workers_output) { /* not required */
5562+ return 0;
5563+ }
5564+
5565+ close(fd_stdout[1]);
5566+ close(fd_stderr[1]);
5567+
5568+ child->fd_stdout = fd_stdout[0];
5569+ child->fd_stderr = fd_stderr[0];
fd1be940
ER
5570+
5571+ fpm_event_add(child->fd_stdout, &child->ev_stdout, fpm_stdio_child_said, child);
5572+ fpm_event_add(child->fd_stderr, &child->ev_stderr, fpm_stdio_child_said, child);
5573+
5574+ return 0;
5575+}
c6a6bfc9
ER
5576+
5577+int fpm_stdio_discard_pipes(struct fpm_child_s *child)
5578+{
5579+ if (0 == child->wp->config->catch_workers_output) { /* not required */
5580+ return 0;
5581+ }
5582+
5583+ close(fd_stdout[1]);
5584+ close(fd_stderr[1]);
5585+
5586+ close(fd_stdout[0]);
5587+ close(fd_stderr[0]);
5588+
5589+ return 0;
5590+}
5591+
5592+void fpm_stdio_child_use_pipes(struct fpm_child_s *child)
5593+{
5594+ if (child->wp->config->catch_workers_output) {
5595+ dup2(fd_stdout[1], STDOUT_FILENO);
5596+ dup2(fd_stderr[1], STDERR_FILENO);
5597+ close(fd_stdout[0]); close(fd_stdout[1]);
5598+ close(fd_stderr[0]); close(fd_stderr[1]);
5599+ }
5600+ else {
5601+ /* stdout of parent is always /dev/null */
5602+ dup2(STDOUT_FILENO, STDERR_FILENO);
5603+ }
5604+}
5605+
5606+int fpm_stdio_open_error_log(int reopen)
5607+{
5608+ int fd;
5609+
5610+ fd = open(fpm_global_options.error_log, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
5611+
5612+ if (0 > fd) {
5613+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(\"%s\") failed", fpm_global_options.error_log);
5614+ return -1;
5615+ }
5616+
5617+ if (reopen) {
5618+ if (fpm_global_options.daemonize) {
5619+ dup2(fd, STDERR_FILENO);
5620+ }
5621+
5622+ dup2(fd, fpm_globals.error_log_fd);
5623+ close(fd);
5624+ fd = fpm_globals.error_log_fd; /* for FD_CLOSEXEC to work */
5625+ }
5626+ else {
5627+ fpm_globals.error_log_fd = fd;
5628+ }
5629+
5630+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
5631+
5632+ return 0;
5633+}
8c0dac15
ER
5634diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_stdio.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_stdio.h
5635--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_stdio.h 1970-01-01 03:00:00.000000000 +0300
5636+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_stdio.h 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9 5637@@ -0,0 +1,20 @@
fd1be940
ER
5638+
5639+ /* $Id$ */
c6a6bfc9 5640+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
5641+
5642+#ifndef FPM_STDIO_H
5643+#define FPM_STDIO_H 1
5644+
5645+#include "fpm_worker_pool.h"
5646+
5647+int fpm_stdio_init_main();
5648+int fpm_stdio_init_final();
5649+int fpm_stdio_init_child(struct fpm_worker_pool_s *wp);
c6a6bfc9
ER
5650+int fpm_stdio_prepare_pipes(struct fpm_child_s *child);
5651+void fpm_stdio_child_use_pipes(struct fpm_child_s *child);
fd1be940 5652+int fpm_stdio_parent_use_pipes(struct fpm_child_s *child);
c6a6bfc9
ER
5653+int fpm_stdio_discard_pipes(struct fpm_child_s *child);
5654+int fpm_stdio_open_error_log(int reopen);
5655+
5656+#endif
5657+
8c0dac15
ER
5658diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_str.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_str.h
5659--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_str.h 1970-01-01 03:00:00.000000000 +0300
5660+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_str.h 2008-05-24 21:38:47.000000000 +0400
c6a6bfc9
ER
5661@@ -0,0 +1,49 @@
5662+
5663+ /* $Id$ */
5664+ /* (c) 2007,2008 Andrei Nigmatulin */
5665+
5666+#ifndef FPM_STR_H
5667+#define FPM_STR_H 1
5668+
5669+static inline char *cpystrn(char *dst, const char *src, size_t dst_size)
5670+{
5671+ char *d, *end;
5672+
5673+ if (!dst_size) return dst;
5674+
5675+ d = dst;
5676+ end = dst + dst_size - 1;
5677+
5678+ for (; d < end; ++d, ++src) {
5679+ if (!(*d = *src)) {
5680+ return d;
5681+ }
5682+ }
5683+
5684+ *d = '\0';
5685+
5686+ return d;
5687+}
5688+
5689+static inline char *str_purify_filename(char *dst, char *src, size_t size)
5690+{
5691+ char *d, *end;
5692+
5693+ d = dst;
5694+ end = dst + size - 1;
5695+
5696+ for (; d < end && *src; ++d, ++src) {
5697+ if (* (unsigned char *) src < ' ' || * (unsigned char *) src > '\x7f') {
5698+ *d = '.';
5699+ }
5700+ else {
5701+ *d = *src;
5702+ }
5703+ }
5704+
5705+ *d = '\0';
5706+
5707+ return d;
5708+}
5709+
5710+#endif
8c0dac15
ER
5711diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace.c
5712--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace.c 1970-01-01 03:00:00.000000000 +0300
5713+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace.c 2008-07-21 00:59:00.000000000 +0400
c6a6bfc9
ER
5714@@ -0,0 +1,46 @@
5715+
5716+ /* $Id$ */
5717+ /* (c) 2007,2008 Andrei Nigmatulin */
5718+
5719+#include "fpm_config.h"
5720+
5721+#include <sys/types.h>
5722+
5723+#include "fpm_trace.h"
5724+
5725+int fpm_trace_get_strz(char *buf, size_t sz, long addr)
5726+{
5727+ int i;
5728+ long l;
5729+ char *lc = (char *) &l;
5730+
5731+ if (0 > fpm_trace_get_long(addr, &l)) {
5732+ return -1;
5733+ }
5734+
5735+ i = l % SIZEOF_LONG;
5736+
5737+ l -= i;
5738+
5739+ for (addr = l; ; addr += SIZEOF_LONG) {
5740+
5741+ if (0 > fpm_trace_get_long(addr, &l)) {
5742+ return -1;
5743+ }
5744+
5745+ for ( ; i < SIZEOF_LONG; i++) {
5746+ --sz;
5747+
5748+ if (sz && lc[i]) {
5749+ *buf++ = lc[i];
5750+ continue;
5751+ }
5752+
5753+ *buf = '\0';
5754+ return 0;
5755+ }
5756+
5757+ i = 0;
5758+ }
5759+}
5760+
8c0dac15
ER
5761diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace.h
5762--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace.h 1970-01-01 03:00:00.000000000 +0300
5763+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace.h 2008-07-21 07:04:25.000000000 +0400
c6a6bfc9
ER
5764@@ -0,0 +1,17 @@
5765+
5766+ /* $Id$ */
5767+ /* (c) 2007,2008 Andrei Nigmatulin */
5768+
5769+#ifndef FPM_TRACE_H
5770+#define FPM_TRACE_H 1
5771+
5772+#include <unistd.h>
5773+
5774+int fpm_trace_signal(pid_t pid);
5775+int fpm_trace_ready(pid_t pid);
5776+int fpm_trace_close(pid_t pid);
5777+int fpm_trace_get_long(long addr, long *data);
5778+int fpm_trace_get_strz(char *buf, size_t sz, long addr);
fd1be940
ER
5779+
5780+#endif
5781+
8c0dac15
ER
5782diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_mach.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_mach.c
5783--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_mach.c 1970-01-01 03:00:00.000000000 +0300
5784+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_mach.c 2008-08-26 19:09:15.000000000 +0400
c6a6bfc9
ER
5785@@ -0,0 +1,102 @@
5786+
5787+ /* $Id$ */
5788+ /* (c) 2007,2008 Andrei Nigmatulin */
5789+
5790+#include "fpm_config.h"
5791+
5792+#include <mach/mach.h>
5793+#include <mach/mach_vm.h>
5794+
5795+#include <unistd.h>
5796+
5797+#include "fpm_trace.h"
5798+#include "fpm_process_ctl.h"
5799+#include "fpm_unix.h"
5800+#include "zlog.h"
5801+
5802+
5803+static mach_port_name_t target;
5804+static vm_offset_t target_page_base;
5805+static vm_offset_t local_page;
5806+static mach_msg_type_number_t local_size;
5807+
5808+static void fpm_mach_vm_deallocate()
5809+{
5810+ if (local_page) {
5811+ mach_vm_deallocate(mach_task_self(), local_page, local_size);
5812+ target_page_base = 0;
5813+ local_page = 0;
5814+ local_size = 0;
5815+ }
5816+}
5817+
5818+static int fpm_mach_vm_read_page(vm_offset_t page)
5819+{
5820+ kern_return_t kr;
5821+
5822+ kr = mach_vm_read(target, page, fpm_pagesize, &local_page, &local_size);
5823+
5824+ if (kr != KERN_SUCCESS) {
5825+ zlog(ZLOG_STUFF, ZLOG_ERROR, "mach_vm_read() failed: %s (%d)", mach_error_string(kr), kr);
5826+ return -1;
5827+ }
5828+
5829+ return 0;
5830+}
5831+
5832+int fpm_trace_signal(pid_t pid)
5833+{
5834+ if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) {
5835+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "kill(SIGSTOP) failed");
5836+ return -1;
5837+ }
5838+
5839+ return 0;
5840+}
5841+
5842+int fpm_trace_ready(pid_t pid)
5843+{
5844+ kern_return_t kr;
5845+
5846+ kr = task_for_pid(mach_task_self(), pid, &target);
5847+
5848+ if (kr != KERN_SUCCESS) {
5849+ char *msg = "";
5850+
5851+ if (kr == KERN_FAILURE) {
5852+ msg = " It seems that master process does not have enough privileges to trace processes.";
5853+ }
5854+
5855+ zlog(ZLOG_STUFF, ZLOG_ERROR, "task_for_pid() failed: %s (%d)%s", mach_error_string(kr), kr, msg);
5856+ return -1;
5857+ }
5858+
5859+ return 0;
5860+}
5861+
5862+int fpm_trace_close(pid_t pid)
5863+{
5864+ fpm_mach_vm_deallocate();
5865+
5866+ target = 0;
5867+
5868+ return 0;
5869+}
5870+
5871+int fpm_trace_get_long(long addr, long *data)
5872+{
5873+ size_t offset = ((uintptr_t) (addr) % fpm_pagesize);
5874+ vm_offset_t base = (uintptr_t) (addr) - offset;
5875+
5876+ if (base != target_page_base) {
5877+ fpm_mach_vm_deallocate();
5878+ if (0 > fpm_mach_vm_read_page(base)) {
5879+ return -1;
5880+ }
5881+ }
5882+
5883+ *data = * (long *) (local_page + offset);
5884+
5885+ return 0;
5886+}
5887+
8c0dac15
ER
5888diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_pread.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_pread.c
5889--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_pread.c 1970-01-01 03:00:00.000000000 +0300
5890+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_pread.c 2008-08-26 19:09:15.000000000 +0400
c6a6bfc9 5891@@ -0,0 +1,67 @@
fd1be940
ER
5892+
5893+ /* $Id$ */
c6a6bfc9
ER
5894+ /* (c) 2007,2008 Andrei Nigmatulin */
5895+
5896+#define _GNU_SOURCE
5897+#define _FILE_OFFSET_BITS 64
5898+
5899+#include "fpm_config.h"
5900+
5901+#include <unistd.h>
5902+
5903+#include <fcntl.h>
5904+#include <stdio.h>
5905+#include <stdint.h>
5906+
5907+#include "fpm_trace.h"
5908+#include "fpm_process_ctl.h"
5909+#include "zlog.h"
5910+
5911+
5912+static int mem_file = -1;
5913+
5914+int fpm_trace_signal(pid_t pid)
5915+{
5916+ if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) {
5917+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "kill(SIGSTOP) failed");
5918+ return -1;
5919+ }
5920+
5921+ return 0;
5922+}
5923+
5924+int fpm_trace_ready(pid_t pid)
5925+{
5926+ char buf[128];
5927+
5928+ sprintf(buf, "/proc/%d/" PROC_MEM_FILE, (int) pid);
5929+
5930+ mem_file = open(buf, O_RDONLY);
5931+
5932+ if (0 > mem_file) {
5933+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(%s) failed", buf);
5934+ return -1;
5935+ }
5936+
5937+ return 0;
5938+}
5939+
5940+int fpm_trace_close(pid_t pid)
5941+{
5942+ close(mem_file);
5943+
5944+ mem_file = -1;
5945+
5946+ return 0;
5947+}
5948+
5949+int fpm_trace_get_long(long addr, long *data)
5950+{
5951+ if (sizeof(*data) != pread(mem_file, (void *) data, sizeof(*data), (uintptr_t) addr)) {
5952+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pread() failed");
5953+ return -1;
5954+ }
5955+
5956+ return 0;
5957+}
5958+
8c0dac15
ER
5959diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_ptrace.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_ptrace.c
5960--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_ptrace.c 1970-01-01 03:00:00.000000000 +0300
5961+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_ptrace.c 2008-09-19 03:34:11.000000000 +0400
c6a6bfc9
ER
5962@@ -0,0 +1,85 @@
5963+
5964+ /* $Id$ */
5965+ /* (c) 2007,2008 Andrei Nigmatulin */
5966+
5967+#include "fpm_config.h"
5968+
5969+#include <sys/wait.h>
5970+#include <sys/ptrace.h>
5971+#include <unistd.h>
5972+#include <errno.h>
5973+
5974+#if defined(PT_ATTACH) && !defined(PTRACE_ATTACH)
5975+#define PTRACE_ATTACH PT_ATTACH
5976+#endif
5977+
5978+#if defined(PT_DETACH) && !defined(PTRACE_DETACH)
5979+#define PTRACE_DETACH PT_DETACH
5980+#endif
5981+
5982+#if defined(PT_READ_D) && !defined(PTRACE_PEEKDATA)
5983+#define PTRACE_PEEKDATA PT_READ_D
5984+#endif
5985+
5986+#include "fpm_trace.h"
5987+#include "zlog.h"
5988+
5989+static pid_t traced_pid;
5990+
5991+int fpm_trace_signal(pid_t pid)
5992+{
5993+ if (0 > ptrace(PTRACE_ATTACH, pid, 0, 0)) {
5994+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(ATTACH) failed");
5995+ return -1;
5996+ }
5997+
5998+ return 0;
5999+}
6000+
6001+int fpm_trace_ready(pid_t pid)
6002+{
6003+ traced_pid = pid;
6004+
6005+ return 0;
6006+}
6007+
6008+int fpm_trace_close(pid_t pid)
6009+{
6010+ if (0 > ptrace(PTRACE_DETACH, pid, (void *) 1, 0)) {
6011+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(DETACH) failed");
6012+ return -1;
6013+ }
6014+
6015+ traced_pid = 0;
6016+
6017+ return 0;
6018+}
6019+
6020+int fpm_trace_get_long(long addr, long *data)
6021+{
6022+#ifdef PT_IO
6023+ struct ptrace_io_desc ptio = {
6024+ .piod_op = PIOD_READ_D,
6025+ .piod_offs = (void *) addr,
6026+ .piod_addr = (void *) data,
6027+ .piod_len = sizeof(long)
6028+ };
6029+
6030+ if (0 > ptrace(PT_IO, traced_pid, (void *) &ptio, 0)) {
6031+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(PT_IO) failed");
6032+ return -1;
6033+ }
6034+#else
6035+ errno = 0;
6036+
6037+ *data = ptrace(PTRACE_PEEKDATA, traced_pid, (void *) addr, 0);
6038+
6039+ if (errno) {
6040+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(PEEKDATA) failed");
6041+ return -1;
6042+ }
6043+#endif
6044+
6045+ return 0;
6046+}
6047+
8c0dac15
ER
6048diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_unix.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_unix.c
6049--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_unix.c 1970-01-01 03:00:00.000000000 +0300
6050+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_unix.c 2008-09-19 03:19:59.000000000 +0400
c6a6bfc9
ER
6051@@ -0,0 +1,289 @@
6052+
6053+ /* $Id$ */
6054+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
6055+
6056+#include "fpm_config.h"
6057+
6058+#include <string.h>
6059+#include <sys/time.h>
6060+#include <sys/resource.h>
6061+#include <stdlib.h>
6062+#include <unistd.h>
6063+#include <sys/types.h>
6064+#include <pwd.h>
6065+#include <grp.h>
6066+
c6a6bfc9 6067+#ifdef HAVE_PRCTL
fd1be940
ER
6068+#include <sys/prctl.h>
6069+#endif
6070+
c6a6bfc9 6071+#include "fpm.h"
fd1be940
ER
6072+#include "fpm_conf.h"
6073+#include "fpm_cleanup.h"
c6a6bfc9 6074+#include "fpm_clock.h"
fd1be940
ER
6075+#include "fpm_stdio.h"
6076+#include "fpm_unix.h"
6077+#include "zlog.h"
6078+
c6a6bfc9
ER
6079+size_t fpm_pagesize;
6080+
fd1be940
ER
6081+int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp)
6082+{
6083+ struct fpm_listen_options_s *lo = wp->config->listen_options;
6084+
6085+ /* uninitialized */
6086+ wp->socket_uid = -1;
6087+ wp->socket_gid = -1;
6088+ wp->socket_mode = 0666;
6089+
6090+ if (!lo) return 0;
6091+
6092+ if (lo->owner && *lo->owner) {
6093+ struct passwd *pwd;
6094+
6095+ pwd = getpwnam(lo->owner);
6096+
6097+ if (!pwd) {
6098+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "cannot get uid for user '%s', pool '%s'", lo->owner, wp->config->name);
6099+ return -1;
6100+ }
6101+
6102+ wp->socket_uid = pwd->pw_uid;
6103+ wp->socket_gid = pwd->pw_gid;
6104+ }
6105+
6106+ if (lo->group && *lo->group) {
6107+ struct group *grp;
6108+
6109+ grp = getgrnam(lo->group);
6110+
6111+ if (!grp) {
6112+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "cannot get gid for group '%s', pool '%s'", lo->group, wp->config->name);
6113+ return -1;
6114+ }
6115+
6116+ wp->socket_gid = grp->gr_gid;
6117+ }
6118+
6119+ if (lo->mode && *lo->mode) {
6120+ wp->socket_mode = strtoul(lo->mode, 0, 8);
6121+ }
6122+
6123+ return 0;
6124+}
6125+
6126+static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp)
6127+{
6128+ int is_root = !geteuid();
6129+
6130+ if (is_root) {
6131+ if (wp->config->user && *wp->config->user) {
fd1be940 6132+
c6a6bfc9
ER
6133+ if (strlen(wp->config->user) == strspn(wp->config->user, "0123456789")) {
6134+ wp->set_uid = strtoul(wp->config->user, 0, 10);
fd1be940 6135+ }
c6a6bfc9
ER
6136+ else {
6137+ struct passwd *pwd;
fd1be940 6138+
c6a6bfc9 6139+ pwd = getpwnam(wp->config->user);
fd1be940 6140+
c6a6bfc9
ER
6141+ if (!pwd) {
6142+ zlog(ZLOG_STUFF, ZLOG_ERROR, "cannot get uid for user '%s', pool '%s'", wp->config->user, wp->config->name);
6143+ return -1;
6144+ }
6145+
6146+ wp->set_uid = pwd->pw_uid;
6147+ wp->set_gid = pwd->pw_gid;
6148+
6149+ wp->user = strdup(pwd->pw_name);
6150+ wp->home = strdup(pwd->pw_dir);
6151+ }
fd1be940
ER
6152+ }
6153+
6154+ if (wp->config->group && *wp->config->group) {
fd1be940 6155+
c6a6bfc9
ER
6156+ if (strlen(wp->config->group) == strspn(wp->config->group, "0123456789")) {
6157+ wp->set_gid = strtoul(wp->config->group, 0, 10);
fd1be940 6158+ }
c6a6bfc9
ER
6159+ else {
6160+ struct group *grp;
6161+
6162+ grp = getgrnam(wp->config->group);
fd1be940 6163+
c6a6bfc9
ER
6164+ if (!grp) {
6165+ zlog(ZLOG_STUFF, ZLOG_ERROR, "cannot get gid for group '%s', pool '%s'", wp->config->group, wp->config->name);
6166+ return -1;
6167+ }
6168+
6169+ wp->set_gid = grp->gr_gid;
6170+ }
fd1be940
ER
6171+ }
6172+
6173+#ifndef I_REALLY_WANT_ROOT_PHP
6174+ if (wp->set_uid == 0 || wp->set_gid == 0) {
6175+ zlog(ZLOG_STUFF, ZLOG_ERROR, "please specify user and group other than root, pool '%s'", wp->config->name);
6176+ return -1;
6177+ }
6178+#endif
6179+ }
6180+ else { /* not root */
6181+ if (wp->config->user && *wp->config->user) {
6182+ zlog(ZLOG_STUFF, ZLOG_WARNING, "'user' directive is ignored, pool '%s'", wp->config->name);
6183+ }
6184+ if (wp->config->group && *wp->config->group) {
6185+ zlog(ZLOG_STUFF, ZLOG_WARNING, "'group' directive is ignored, pool '%s'", wp->config->name);
6186+ }
6187+ if (wp->config->chroot && *wp->config->chroot) {
6188+ zlog(ZLOG_STUFF, ZLOG_WARNING, "'chroot' directive is ignored, pool '%s'", wp->config->name);
6189+ }
6190+
6191+ { /* set up HOME and USER anyway */
6192+ struct passwd *pwd;
6193+
6194+ pwd = getpwuid(getuid());
6195+
6196+ if (pwd) {
6197+ wp->user = strdup(pwd->pw_name);
6198+ wp->home = strdup(pwd->pw_dir);
6199+ }
6200+ }
6201+ }
6202+
6203+ return 0;
6204+}
6205+
6206+int fpm_unix_init_child(struct fpm_worker_pool_s *wp)
6207+{
6208+ int is_root = !geteuid();
6209+ int made_chroot = 0;
6210+
6211+ if (wp->config->rlimit_files) {
6212+ struct rlimit r;
6213+
6214+ getrlimit(RLIMIT_NOFILE, &r);
6215+
6216+ r.rlim_cur = (rlim_t) wp->config->rlimit_files;
6217+
6218+ if (0 > setrlimit(RLIMIT_NOFILE, &r)) {
6219+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setrlimit(RLIMIT_NOFILE) failed");
6220+ }
6221+ }
6222+
6223+ if (wp->config->rlimit_core) {
6224+ struct rlimit r;
6225+
6226+ getrlimit(RLIMIT_CORE, &r);
6227+
6228+ r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core;
6229+
6230+ if (0 > setrlimit(RLIMIT_CORE, &r)) {
6231+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setrlimit(RLIMIT_CORE) failed");
6232+ }
6233+ }
6234+
6235+ if (is_root && wp->config->chroot && *wp->config->chroot) {
6236+ if (0 > chroot(wp->config->chroot)) {
6237+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chroot(%s) failed", wp->config->chroot);
6238+ return -1;
6239+ }
6240+ made_chroot = 1;
6241+ }
6242+
6243+ if (wp->config->chdir && *wp->config->chdir) {
6244+ if (0 > chdir(wp->config->chdir)) {
6245+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chdir(%s) failed", wp->config->chdir);
6246+ return -1;
6247+ }
6248+ }
6249+ else if (made_chroot) {
6250+ chdir("/");
6251+ }
6252+
6253+ if (is_root) {
6254+ if (wp->set_gid) {
c6a6bfc9
ER
6255+ if (0 > setgid(wp->set_gid)) {
6256+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setgid(%d) failed", wp->set_gid);
6257+ return -1;
6258+ }
fd1be940
ER
6259+ }
6260+ if (wp->set_uid) {
c6a6bfc9
ER
6261+ if (0 > initgroups(wp->config->user, wp->set_gid)) {
6262+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "initgroups(%s, %d) failed", wp->config->user, wp->set_gid);
6263+ return -1;
6264+ }
6265+ if (0 > setuid(wp->set_uid)) {
6266+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setuid(%d) failed", wp->set_uid);
6267+ return -1;
6268+ }
fd1be940
ER
6269+ }
6270+ }
6271+
c6a6bfc9 6272+#ifdef HAVE_PRCTL
fd1be940
ER
6273+ if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) {
6274+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "prctl(PR_SET_DUMPABLE) failed");
6275+ }
6276+#endif
6277+
c6a6bfc9
ER
6278+ if (0 > fpm_clock_init()) {
6279+ return -1;
6280+ }
6281+
fd1be940
ER
6282+ return 0;
6283+}
6284+
6285+int fpm_unix_init_main()
6286+{
6287+ struct fpm_worker_pool_s *wp;
6288+
c6a6bfc9
ER
6289+ fpm_pagesize = getpagesize();
6290+
fd1be940
ER
6291+ if (fpm_global_options.daemonize) {
6292+
6293+ switch (fork()) {
6294+
6295+ case -1 :
6296+
6297+ zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fork() failed");
6298+ return -1;
6299+
6300+ case 0 :
6301+
6302+ break;
6303+
6304+ default :
6305+
6306+ fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT);
6307+ exit(0);
6308+
6309+ }
6310+
6311+ }
6312+
6313+ setsid();
6314+
c6a6bfc9
ER
6315+ if (0 > fpm_clock_init()) {
6316+ return -1;
6317+ }
6318+
6319+ fpm_globals.parent_pid = getpid();
6320+
fd1be940
ER
6321+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
6322+
6323+ if (0 > fpm_unix_conf_wp(wp)) {
6324+ return -1;
6325+ }
6326+
6327+ }
6328+
6329+ fpm_stdio_init_final();
6330+
c6a6bfc9
ER
6331+ {
6332+ struct rlimit r;
6333+ getrlimit(RLIMIT_NOFILE, &r);
6334+
6335+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "getrlimit(nofile): max:%lld, cur:%lld",
6336+ (long long) r.rlim_max, (long long) r.rlim_cur);
6337+ }
6338+
fd1be940
ER
6339+ return 0;
6340+}
8c0dac15
ER
6341diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_unix.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_unix.h
6342--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_unix.h 1970-01-01 03:00:00.000000000 +0300
6343+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_unix.h 2008-05-25 17:21:13.000000000 +0400
c6a6bfc9 6344@@ -0,0 +1,17 @@
fd1be940
ER
6345+
6346+ /* $Id$ */
c6a6bfc9 6347+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
6348+
6349+#ifndef FPM_UNIX_H
6350+#define FPM_UNIX_H 1
6351+
6352+#include "fpm_worker_pool.h"
6353+
6354+int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp);
6355+int fpm_unix_init_child(struct fpm_worker_pool_s *wp);
6356+int fpm_unix_init_main();
6357+
c6a6bfc9
ER
6358+extern size_t fpm_pagesize;
6359+
fd1be940
ER
6360+#endif
6361+
8c0dac15
ER
6362diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_worker_pool.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_worker_pool.c
6363--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_worker_pool.c 1970-01-01 03:00:00.000000000 +0300
6364+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_worker_pool.c 2008-08-26 19:09:15.000000000 +0400
c6a6bfc9 6365@@ -0,0 +1,67 @@
fd1be940
ER
6366+
6367+ /* $Id$ */
c6a6bfc9 6368+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
6369+
6370+#include "fpm_config.h"
6371+
6372+#include <string.h>
6373+#include <stdlib.h>
6374+#include <unistd.h>
6375+
6376+#include "fpm_worker_pool.h"
6377+#include "fpm_cleanup.h"
6378+#include "fpm_children.h"
c6a6bfc9
ER
6379+#include "fpm_shm.h"
6380+#include "fpm_shm_slots.h"
fd1be940
ER
6381+#include "fpm_conf.h"
6382+
6383+struct fpm_worker_pool_s *fpm_worker_all_pools;
6384+
c6a6bfc9 6385+static void fpm_worker_pool_cleanup(int which, void *arg)
fd1be940
ER
6386+{
6387+ struct fpm_worker_pool_s *wp, *wp_next;
6388+
6389+ for (wp = fpm_worker_all_pools; wp; wp = wp_next) {
6390+ wp_next = wp->next;
6391+ fpm_worker_pool_config_free(wp->config);
6392+ fpm_children_free(wp->children);
c6a6bfc9
ER
6393+ fpm_array_free(&wp->slots_used);
6394+ fpm_array_free(&wp->slots_free);
6395+ fpm_shm_free_list(wp->shm_list, which == FPM_CLEANUP_CHILD ? fpm_shm_slots_mem() : 0);
fd1be940
ER
6396+ free(wp->config);
6397+ free(wp->user);
6398+ free(wp->home);
6399+ free(wp);
6400+ }
6401+
6402+ fpm_worker_all_pools = 0;
6403+}
6404+
6405+struct fpm_worker_pool_s *fpm_worker_pool_alloc()
6406+{
6407+ struct fpm_worker_pool_s *ret;
6408+
6409+ ret = malloc(sizeof(struct fpm_worker_pool_s));
6410+
6411+ if (!ret) {
6412+ return 0;
6413+ }
6414+
6415+ memset(ret, 0, sizeof(struct fpm_worker_pool_s));
6416+
6417+ if (!fpm_worker_all_pools) {
6418+ fpm_worker_all_pools = ret;
6419+ }
6420+
c6a6bfc9
ER
6421+ fpm_array_init(&ret->slots_used, sizeof(struct fpm_shm_slot_ptr_s), 50);
6422+ fpm_array_init(&ret->slots_free, sizeof(struct fpm_shm_slot_ptr_s), 50);
6423+
fd1be940
ER
6424+ return ret;
6425+}
6426+
6427+int fpm_worker_pool_init_main()
6428+{
6429+ fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_worker_pool_cleanup, 0);
6430+
6431+ return 0;
6432+}
8c0dac15
ER
6433diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_worker_pool.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_worker_pool.h
6434--- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_worker_pool.h 1970-01-01 03:00:00.000000000 +0300
6435+++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_worker_pool.h 2008-08-26 19:09:15.000000000 +0400
c6a6bfc9 6436@@ -0,0 +1,46 @@
fd1be940
ER
6437+
6438+ /* $Id$ */
c6a6bfc9 6439+ /* (c) 2007,2008 Andrei Nigmatulin */
fd1be940
ER
6440+
6441+#ifndef FPM_WORKER_POOL_H
6442+#define FPM_WORKER_POOL_H 1
6443+
6444+#include "fpm_conf.h"
c6a6bfc9 6445+#include "fpm_arrays.h"
fd1be940
ER
6446+
6447+struct fpm_worker_pool_s;
6448+struct fpm_child_s;
c6a6bfc9
ER
6449+struct fpm_child_stat_s;
6450+struct fpm_shm_s;
fd1be940
ER
6451+
6452+enum fpm_address_domain {
6453+ FPM_AF_UNIX = 1,
6454+ FPM_AF_INET = 2
6455+};
6456+
6457+struct fpm_worker_pool_s {
6458+ struct fpm_worker_pool_s *next;
6459+ struct fpm_worker_pool_config_s *config;
6460+ char *user, *home; /* for setting env USER and HOME */
6461+ enum fpm_address_domain listen_address_domain;
6462+ int listening_socket;
6463+ int set_uid, set_gid; /* config uid and gid */
c6a6bfc9 6464+ unsigned is_template:1; /* just config template, no processes will be created */
fd1be940
ER
6465+ int socket_uid, socket_gid, socket_mode;
6466+
c6a6bfc9
ER
6467+ struct fpm_shm_s *shm_list;
6468+ struct fpm_array_s slots_used;
6469+ struct fpm_array_s slots_free;
6470+
fd1be940
ER
6471+ /* runtime */
6472+ struct fpm_child_s *children;
fd1be940
ER
6473+ int running_children;
6474+};
6475+
6476+struct fpm_worker_pool_s *fpm_worker_pool_alloc();
6477+int fpm_worker_pool_init_main();
6478+
6479+extern struct fpm_worker_pool_s *fpm_worker_all_pools;
6480+
6481+#endif
6482+
8c0dac15
ER
6483diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/init.d/php-fpm.in php-5.2.6.fpm/sapi/cgi/fpm/init.d/php-fpm.in
6484--- php-5.2.6.vanilla/sapi/cgi/fpm/init.d/php-fpm.in 1970-01-01 03:00:00.000000000 +0300
6485+++ php-5.2.6.fpm/sapi/cgi/fpm/init.d/php-fpm.in 2008-08-05 20:31:27.000000000 +0400
c6a6bfc9
ER
6486@@ -0,0 +1,139 @@
6487+#! /bin/sh
6488+
6489+php_fpm_BIN=@prefix@/bin/php-cgi
6490+php_fpm_CONF=@php_fpm_conf_path@
6491+php_fpm_PID=@php_fpm_pid_path@
6492+
6493+
6494+php_opts="--fpm-config $php_fpm_CONF"
6495+
6496+
6497+wait_for_pid () {
6498+ try=0
6499+
6500+ while test $try -lt 35 ; do
6501+
6502+ case "$1" in
6503+ 'created')
6504+ if [ -f "$2" ] ; then
6505+ try=''
6506+ break
6507+ fi
6508+ ;;
6509+
6510+ 'removed')
6511+ if [ ! -f "$2" ] ; then
6512+ try=''
6513+ break
6514+ fi
6515+ ;;
6516+ esac
6517+
6518+ echo -n .
6519+ try=`expr $try + 1`
6520+ sleep 1
6521+
6522+ done
6523+
6524+}
6525+
6526+case "$1" in
6527+ start)
6528+ echo -n "Starting php_fpm "
6529+
6530+ $php_fpm_BIN --fpm $php_opts
6531+
6532+ if [ "$?" != 0 ] ; then
6533+ echo " failed"
6534+ exit 1
6535+ fi
6536+
6537+ wait_for_pid created $php_fpm_PID
6538+
6539+ if [ -n "$try" ] ; then
6540+ echo " failed"
6541+ exit 1
6542+ else
6543+ echo " done"
6544+ fi
6545+ ;;
6546+
6547+ stop)
6548+ echo -n "Shutting down php_fpm "
6549+
6550+ if [ ! -r $php_fpm_PID ] ; then
6551+ echo "warning, no pid file found - php-fpm is not running ?"
6552+ exit 1
6553+ fi
6554+
6555+ kill -TERM `cat $php_fpm_PID`
6556+
6557+ wait_for_pid removed $php_fpm_PID
6558+
6559+ if [ -n "$try" ] ; then
6560+ echo " failed"
6561+ exit 1
6562+ else
6563+ echo " done"
6564+ fi
6565+ ;;
6566+
6567+ quit)
6568+ echo -n "Gracefully shutting down php_fpm "
fd1be940 6569+
c6a6bfc9
ER
6570+ if [ ! -r $php_fpm_PID ] ; then
6571+ echo "warning, no pid file found - php-fpm is not running ?"
6572+ exit 1
6573+ fi
6574+
6575+ kill -QUIT `cat $php_fpm_PID`
6576+
6577+ wait_for_pid removed $php_fpm_PID
6578+
6579+ if [ -n "$try" ] ; then
6580+ echo " failed"
6581+ exit 1
6582+ else
6583+ echo " done"
6584+ fi
6585+ ;;
6586+
6587+ restart)
6588+ $0 stop
6589+ $0 start
6590+ ;;
6591+
6592+ reload)
6593+
6594+ echo -n "Reload service php-fpm "
6595+
6596+ if [ ! -r $php_fpm_PID ] ; then
6597+ echo "warning, no pid file found - php-fpm is not running ?"
6598+ exit 1
6599+ fi
6600+
6601+ kill -USR2 `cat $php_fpm_PID`
6602+
6603+ echo " done"
6604+ ;;
6605+
6606+ logrotate)
6607+
6608+ echo -n "Re-opening php-fpm log file "
6609+
6610+ if [ ! -r $php_fpm_PID ] ; then
6611+ echo "warning, no pid file found - php-fpm is not running ?"
6612+ exit 1
6613+ fi
6614+
6615+ kill -USR1 `cat $php_fpm_PID`
6616+
6617+ echo " done"
6618+ ;;
6619+
6620+ *)
6621+ echo "Usage: $0 {start|stop|quit|restart|reload|logrotate}"
6622+ exit 1
6623+ ;;
6624+
6625+esac
8c0dac15
ER
6626diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/Makefile.frag php-5.2.6.fpm/sapi/cgi/fpm/Makefile.frag
6627--- php-5.2.6.vanilla/sapi/cgi/fpm/Makefile.frag 1970-01-01 03:00:00.000000000 +0300
6628+++ php-5.2.6.fpm/sapi/cgi/fpm/Makefile.frag 2008-03-28 16:51:22.000000000 +0300
c6a6bfc9
ER
6629@@ -0,0 +1,21 @@
6630+
8c0dac15 6631+install-fpm: sapi/cgi/fpm/php-fpm.conf sapi/cgi/fpm/php-fpm
c6a6bfc9
ER
6632+ @echo "Installing FPM config: $(INSTALL_ROOT)$(php_fpm_conf_path)"
6633+ -@$(mkinstalldirs) \
6634+ $(INSTALL_ROOT)$(prefix)/sbin \
6635+ `dirname "$(INSTALL_ROOT)$(php_fpm_conf_path)"` \
6636+ `dirname "$(INSTALL_ROOT)$(php_fpm_log_path)"` \
6637+ `dirname "$(INSTALL_ROOT)$(php_fpm_pid_path)"`
6638+ -@if test -r "$(INSTALL_ROOT)$(php_fpm_conf_path)" ; then \
6639+ dest=`basename "$(php_fpm_conf_path)"`.default ; \
6640+ echo " (installing as $$dest)" ; \
fd1be940 6641+ else \
c6a6bfc9 6642+ dest=`basename "$(php_fpm_conf_path)"` ; \
fd1be940 6643+ fi ; \
8c0dac15 6644+ $(INSTALL_DATA) $(top_builddir)/sapi/cgi/fpm/php-fpm.conf $(INSTALL_ROOT)`dirname "$(php_fpm_conf_path)"`/$$dest
c6a6bfc9 6645+ @echo "Installing init.d script: $(INSTALL_ROOT)$(prefix)/sbin/php-fpm"
8c0dac15 6646+ -@$(INSTALL) -m 0755 $(top_builddir)/sapi/cgi/fpm/php-fpm $(INSTALL_ROOT)$(prefix)/sbin/php-fpm
fd1be940 6647+
c6a6bfc9
ER
6648+$(top_builddir)/libevent/libevent.a: $(top_builddir)/libevent/Makefile
6649+ cd $(top_builddir)/libevent && $(MAKE) libevent.a
fd1be940 6650+
8c0dac15
ER
6651diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/xml_config.c php-5.2.6.fpm/sapi/cgi/fpm/xml_config.c
6652--- php-5.2.6.vanilla/sapi/cgi/fpm/xml_config.c 1970-01-01 03:00:00.000000000 +0300
6653+++ php-5.2.6.fpm/sapi/cgi/fpm/xml_config.c 2008-08-26 19:09:15.000000000 +0400
fd1be940
ER
6654@@ -0,0 +1,278 @@
6655+
6656+ /* $Id$ */
6657+ /* (c) 2004-2007 Andrei Nigmatulin */
6658+
6659+#include "fpm_config.h"
6660+
6661+#ifdef HAVE_ALLOCA_H
6662+#include <alloca.h>
6663+#endif
6664+#include <string.h>
6665+#include <stdio.h>
6666+#include <stddef.h>
6667+#include <stdlib.h>
6668+
6669+#include <libxml/parser.h>
6670+#include <libxml/tree.h>
6671+
6672+#include "xml_config.h"
6673+
6674+static struct xml_conf_section **xml_conf_sections = 0;
6675+static int xml_conf_sections_allocated = 0;
6676+static int xml_conf_sections_used = 0;
6677+
6678+char *xml_conf_set_slot_boolean(void **conf, char *name, void *vv, intptr_t offset)
6679+{
6680+ char *value = vv;
6681+ long value_y = !strcasecmp(value, "yes") || !strcmp(value, "1") || !strcasecmp(value, "on");
6682+ long value_n = !strcasecmp(value, "no") || !strcmp(value, "0") || !strcasecmp(value, "off");
6683+
6684+ if (!value_y && !value_n) {
6685+ return "xml_conf_set_slot(): invalid boolean value";
6686+ }
6687+
6688+#ifdef XML_CONF_DEBUG
6689+ fprintf(stderr, "setting boolean '%s' => %s\n", name, value_y ? "TRUE" : "FALSE");
6690+#endif
6691+
6692+ * (int *) ((char *) *conf + offset) = value_y ? 1 : 0;
6693+
6694+ return NULL;
6695+}
6696+
6697+char *xml_conf_set_slot_string(void **conf, char *name, void *vv, intptr_t offset)
6698+{
6699+ char *value = vv;
6700+ char *v = strdup(value);
6701+
6702+ if (!v) return "xml_conf_set_slot_string(): strdup() failed";
6703+
6704+#ifdef XML_CONF_DEBUG
6705+ fprintf(stderr, "setting string '%s' => '%s'\n", name, v);
6706+#endif
6707+
6708+ * (char **) ((char *) *conf + offset) = v;
6709+
6710+ return NULL;
6711+}
6712+
6713+char *xml_conf_set_slot_integer(void **conf, char *name, void *vv, intptr_t offset)
6714+{
6715+ char *value = vv;
6716+ int v = atoi(value);
6717+
6718+ * (int *) ((char *) *conf + offset) = v;
6719+
6720+#ifdef XML_CONF_DEBUG
6721+ fprintf(stderr, "setting integer '%s' => %d\n", name, v);
6722+#endif
6723+
6724+ return NULL;
6725+}
6726+
6727+char *xml_conf_set_slot_time(void **conf, char *name, void *vv, intptr_t offset)
6728+{
6729+ char *value = vv;
6730+ int len = strlen(value);
6731+ char suffix;
6732+ int seconds;
6733+
6734+ if (!len) return "xml_conf_set_slot_timeval(): invalid timeval value";
6735+
6736+ suffix = value[len-1];
6737+
6738+ value[len-1] = '\0';
6739+
6740+ switch (suffix) {
6741+ case 's' :
6742+ seconds = atoi(value);
6743+ break;
6744+ case 'm' :
6745+ seconds = 60 * atoi(value);
6746+ break;
6747+ case 'h' :
6748+ seconds = 60 * 60 * atoi(value);
6749+ break;
6750+ case 'd' :
6751+ seconds = 24 * 60 * 60 * atoi(value);
6752+ break;
6753+ default :
6754+ return "xml_conf_set_slot_timeval(): unknown suffix used in timeval value";
6755+ }
6756+
6757+ * (int *) ((char *) *conf + offset) = seconds;
6758+
6759+#ifdef XML_CONF_DEBUG
6760+ fprintf(stderr, "setting time '%s' => %d:%02d:%02d:%02d\n", name, expand_dhms(seconds));
6761+#endif
6762+
6763+ return NULL;
6764+}
6765+
6766+char *xml_conf_parse_section(void **conf, struct xml_conf_section *section, void *xml_node)
6767+{
6768+ xmlNode *element = xml_node;
6769+ char *ret = 0;
6770+
6771+#ifdef XML_CONF_DEBUG
6772+ fprintf(stderr, "processing a section %s\n", section->path);
6773+#endif
6774+
6775+ for ( ; element; element = element->next) {
6776+ if (element->type == XML_ELEMENT_NODE && !strcmp((const char *) element->name, "value") && element->children) {
6777+ xmlChar *name = xmlGetProp(element, (unsigned char *) "name");
6778+
6779+ if (name) {
6780+ int i;
6781+
6782+#ifdef XML_CONF_DEBUG
6783+ fprintf(stderr, "found a value: %s\n", name);
6784+#endif
6785+ for (i = 0; section->parsers[i].parser; i++) {
6786+ if (!section->parsers[i].name || !strcmp(section->parsers[i].name, (char *) name)) {
6787+ break;
6788+ }
6789+ }
6790+
6791+ if (section->parsers[i].parser) {
6792+ if (section->parsers[i].type == XML_CONF_SCALAR) {
6793+ if (element->children->type == XML_TEXT_NODE) {
6794+ ret = section->parsers[i].parser(conf, (char *) name, element->children->content, section->parsers[i].offset);
6795+ }
6796+ else {
6797+ ret = "XML_TEXT_NODE is expected, something different is given";
6798+ }
6799+ }
6800+ else {
6801+ ret = section->parsers[i].parser(conf, (char *) name, element->children, section->parsers[i].offset);
6802+ }
6803+
6804+ xmlFree(name);
6805+ if (ret) return ret;
6806+ else continue;
6807+ }
6808+
c6a6bfc9 6809+ fprintf(stderr, "Warning, unknown setting '%s' in section '%s'\n", (char *) name, section->path);
fd1be940
ER
6810+
6811+ xmlFree(name);
6812+ }
6813+ }
6814+ }
6815+
6816+ return NULL;
6817+}
6818+
6819+static char *xml_conf_parse_file(xmlNode *element)
6820+{
6821+ char *ret = 0;
6822+
6823+ for ( ; element; element = element->next) {
6824+
6825+ if (element->parent && element->type == XML_ELEMENT_NODE && !strcmp((const char *) element->name, "section")) {
6826+ xmlChar *name = xmlGetProp(element, (unsigned char *) "name");
6827+
6828+ if (name) {
6829+ char *parent_name = (char *) xmlGetNodePath(element->parent);
6830+ char *full_name;
6831+ int i;
6832+ struct xml_conf_section *section = NULL;
6833+
6834+#ifdef XML_CONF_DEBUG
6835+ fprintf(stderr, "got a section: %s/%s\n", parent_name, name);
6836+#endif
6837+ full_name = alloca(strlen(parent_name) + strlen((char *) name) + 1 + 1);
6838+
c6a6bfc9 6839+ sprintf(full_name, "%s/%s", parent_name, (char *) name);
fd1be940
ER
6840+
6841+ xmlFree(parent_name);
6842+ xmlFree(name);
6843+
6844+ for (i = 0; i < xml_conf_sections_used; i++) {
6845+ if (!strcmp(xml_conf_sections[i]->path, full_name)) {
6846+ section = xml_conf_sections[i];
6847+ }
6848+ }
6849+
6850+ if (section) { /* found a registered section */
6851+ void *conf = section->conf();
6852+ ret = xml_conf_parse_section(&conf, section, element->children);
6853+ if (ret) break;
6854+ }
6855+
6856+ }
6857+ }
6858+
6859+ if (element->children) {
6860+ ret = xml_conf_parse_file(element->children);
6861+ if (ret) break;
6862+ }
6863+ }
6864+
6865+ return ret;
6866+}
6867+
6868+char *xml_conf_load_file(char *file)
6869+{
6870+ char *ret = 0;
6871+ xmlDoc *doc;
6872+
6873+ LIBXML_TEST_VERSION
6874+
6875+ doc = xmlParseFile(file);
6876+
6877+ if (doc) {
6878+ ret = xml_conf_parse_file(doc->children);
6879+ xmlFreeDoc(doc);
6880+ }
6881+ else {
6882+ ret = "failed to parse conf file";
6883+ }
6884+
6885+ xmlCleanupParser();
6886+ return ret;
6887+}
6888+
6889+int xml_conf_init()
6890+{
6891+ return 0;
6892+}
6893+
6894+void xml_conf_clean()
6895+{
6896+ if (xml_conf_sections) {
6897+ free(xml_conf_sections);
6898+ }
6899+}
6900+
6901+int xml_conf_section_register(struct xml_conf_section *section)
6902+{
6903+ if (xml_conf_sections_allocated == xml_conf_sections_used) {
6904+ int new_size = xml_conf_sections_used + 10;
6905+ void *new_ptr = realloc(xml_conf_sections, sizeof(struct xml_conf_section *) * new_size);
6906+
6907+ if (new_ptr) {
6908+ xml_conf_sections = new_ptr;
6909+ xml_conf_sections_allocated = new_size;
6910+ }
6911+ else {
6912+ fprintf(stderr, "xml_conf_section_register(): out of memory\n");
6913+ return -1;
6914+ }
6915+ }
6916+
6917+ xml_conf_sections[xml_conf_sections_used++] = section;
6918+
6919+ return 0;
6920+}
6921+
6922+int xml_conf_sections_register(struct xml_conf_section *sections[])
6923+{
6924+ for ( ; sections && *sections; sections++) {
6925+ if (0 > xml_conf_section_register(*sections)) {
6926+ return -1;
6927+ }
6928+ }
6929+
6930+ return 0;
6931+}
6932+
8c0dac15
ER
6933diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/xml_config.h php-5.2.6.fpm/sapi/cgi/fpm/xml_config.h
6934--- php-5.2.6.vanilla/sapi/cgi/fpm/xml_config.h 1970-01-01 03:00:00.000000000 +0300
6935+++ php-5.2.6.fpm/sapi/cgi/fpm/xml_config.h 2008-09-19 03:02:58.000000000 +0400
fd1be940
ER
6936@@ -0,0 +1,43 @@
6937+
6938+ /* $Id$ */
6939+ /* (c) 2004-2007 Andrei Nigmatulin */
6940+
6941+#ifndef XML_CONFIG_H
6942+#define XML_CONFIG_H 1
6943+
6944+#include <stdint.h>
6945+
6946+struct xml_value_parser;
6947+
6948+struct xml_value_parser {
6949+ int type;
6950+ char *name;
6951+ char *(*parser)(void **, char *, void *, intptr_t offset);
6952+ intptr_t offset;
6953+};
6954+
6955+struct xml_conf_section {
6956+ void *(*conf)();
6957+ char *path;
c6a6bfc9 6958+ struct xml_value_parser *parsers;
fd1be940
ER
6959+};
6960+
6961+char *xml_conf_set_slot_boolean(void **conf, char *name, void *value, intptr_t offset);
6962+char *xml_conf_set_slot_string(void **conf, char *name, void *value, intptr_t offset);
6963+char *xml_conf_set_slot_integer(void **conf, char *name, void *value, intptr_t offset);
6964+char *xml_conf_set_slot_time(void **conf, char *name, void *value, intptr_t offset);
6965+
6966+int xml_conf_init();
6967+void xml_conf_clean();
6968+char *xml_conf_load_file(char *file);
6969+char *xml_conf_parse_section(void **conf, struct xml_conf_section *section, void *ve);
6970+int xml_conf_section_register(struct xml_conf_section *section);
6971+int xml_conf_sections_register(struct xml_conf_section *sections[]);
6972+
6973+#define expand_hms(value) (value) / 3600, ((value) % 3600) / 60, (value) % 60
6974+
6975+#define expand_dhms(value) (value) / 86400, ((value) % 86400) / 3600, ((value) % 3600) / 60, (value) % 60
6976+
6977+enum { XML_CONF_SCALAR = 1, XML_CONF_SUBSECTION = 2 };
6978+
6979+#endif
8c0dac15
ER
6980diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/zlog.c php-5.2.6.fpm/sapi/cgi/fpm/zlog.c
6981--- php-5.2.6.vanilla/sapi/cgi/fpm/zlog.c 1970-01-01 03:00:00.000000000 +0300
6982+++ php-5.2.6.fpm/sapi/cgi/fpm/zlog.c 2008-05-23 01:08:32.000000000 +0400
c6a6bfc9 6983@@ -0,0 +1,113 @@
fd1be940
ER
6984+
6985+ /* $Id$ */
6986+ /* (c) 2004-2007 Andrei Nigmatulin */
6987+
6988+#include "fpm_config.h"
6989+
6990+#include <stdio.h>
6991+#include <unistd.h>
6992+#include <time.h>
6993+#include <string.h>
6994+#include <stdarg.h>
6995+#include <sys/time.h>
6996+#include <errno.h>
6997+
6998+#include "zlog.h"
6999+
7000+#define MAX_LINE_LENGTH 1024
7001+
7002+static int zlog_fd = -1;
c6a6bfc9 7003+static int zlog_level = ZLOG_NOTICE;
fd1be940
ER
7004+
7005+static const char *level_names[] = {
7006+ [ZLOG_DEBUG] = "DEBUG",
7007+ [ZLOG_NOTICE] = "NOTICE",
7008+ [ZLOG_WARNING] = "WARNING",
7009+ [ZLOG_ERROR] = "ERROR",
7010+ [ZLOG_ALERT] = "ALERT",
7011+};
7012+
c6a6bfc9 7013+size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len)
fd1be940 7014+{
fd1be940
ER
7015+ struct tm t;
7016+ size_t len;
7017+
c6a6bfc9
ER
7018+ len = strftime(timebuf, timebuf_len, "%b %d %H:%M:%S", localtime_r((const time_t *) &tv->tv_sec, &t));
7019+ len += snprintf(timebuf + len, timebuf_len - len, ".%06d", (int) tv->tv_usec);
fd1be940
ER
7020+
7021+ return len;
7022+}
7023+
7024+int zlog_set_fd(int new_fd)
7025+{
7026+ int old_fd = zlog_fd;
7027+ zlog_fd = new_fd;
7028+
7029+ return old_fd;
7030+}
7031+
c6a6bfc9
ER
7032+int zlog_set_level(int new_value)
7033+{
7034+ int old_value = zlog_level;
7035+
7036+ zlog_level = new_value;
7037+
7038+ return old_value;
7039+}
7040+
fd1be940
ER
7041+void zlog(const char *function, int line, int flags, const char *fmt, ...)
7042+{
c6a6bfc9 7043+ struct timeval tv;
fd1be940
ER
7044+ char buf[MAX_LINE_LENGTH];
7045+ const size_t buf_size = MAX_LINE_LENGTH;
7046+ va_list args;
7047+ size_t len;
7048+ int truncated = 0;
c6a6bfc9 7049+ int saved_errno;
fd1be940 7050+
c6a6bfc9
ER
7051+ if ((flags & ZLOG_LEVEL_MASK) < zlog_level) {
7052+ return;
7053+ }
7054+
7055+ saved_errno = errno;
7056+
7057+ gettimeofday(&tv, 0);
7058+
7059+ len = zlog_print_time(&tv, buf, buf_size);
fd1be940
ER
7060+
7061+ len += snprintf(buf + len, buf_size - len, " [%s] %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line);
7062+
7063+ if (len > buf_size - 1) {
7064+ truncated = 1;
7065+ }
7066+
7067+ if (!truncated) {
7068+ va_start(args, fmt);
7069+
7070+ len += vsnprintf(buf + len, buf_size - len, fmt, args);
7071+
7072+ va_end(args);
7073+
7074+ if (len >= buf_size) {
7075+ truncated = 1;
7076+ }
7077+ }
7078+
7079+ if (!truncated) {
7080+ if (flags & ZLOG_HAVE_ERRNO) {
7081+ len += snprintf(buf + len, buf_size - len, ": %s (%d)", strerror(saved_errno), saved_errno);
7082+ if (len >= buf_size) {
7083+ truncated = 1;
7084+ }
7085+ }
7086+ }
7087+
7088+ if (truncated) {
7089+ memcpy(buf + buf_size - sizeof("..."), "...", sizeof("...") - 1);
7090+ len = buf_size - 1;
7091+ }
7092+
7093+ buf[len++] = '\n';
7094+
7095+ write(zlog_fd > -1 ? zlog_fd : STDERR_FILENO, buf, len);
7096+}
8c0dac15
ER
7097diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/zlog.h php-5.2.6.fpm/sapi/cgi/fpm/zlog.h
7098--- php-5.2.6.vanilla/sapi/cgi/fpm/zlog.h 1970-01-01 03:00:00.000000000 +0300
7099+++ php-5.2.6.fpm/sapi/cgi/fpm/zlog.h 2008-05-23 01:08:32.000000000 +0400
c6a6bfc9 7100@@ -0,0 +1,34 @@
fd1be940
ER
7101+
7102+ /* $Id$ */
7103+ /* (c) 2004-2007 Andrei Nigmatulin */
7104+
7105+#ifndef ZLOG_H
7106+#define ZLOG_H 1
7107+
7108+#define ZLOG_STUFF __func__, __LINE__
7109+
c6a6bfc9
ER
7110+struct timeval;
7111+
fd1be940 7112+int zlog_set_fd(int new_fd);
c6a6bfc9
ER
7113+int zlog_set_level(int new_value);
7114+
7115+size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len);
fd1be940
ER
7116+
7117+void zlog(const char *function, int line, int flags, const char *fmt, ...)
7118+ __attribute__ ((format(printf,4,5)));
7119+
7120+enum {
7121+ ZLOG_DEBUG = 1,
7122+ ZLOG_NOTICE = 2,
7123+ ZLOG_WARNING = 3,
7124+ ZLOG_ERROR = 4,
7125+ ZLOG_ALERT = 5,
7126+};
7127+
7128+#define ZLOG_LEVEL_MASK 7
7129+
7130+#define ZLOG_HAVE_ERRNO 0x100
7131+
7132+#define ZLOG_SYSERROR (ZLOG_ERROR | ZLOG_HAVE_ERRNO)
7133+
7134+#endif
75ddaf45
ER
7135--- php-5.2.6/sapi/cgi/Makefile.frag~ 2008-11-03 19:29:12.000000000 +0200
7136+++ php-5.2.6/sapi/cgi/Makefile.frag 2008-11-03 19:31:19.361921087 +0200
fd1be940 7137@@ -1,2 +1,2 @@
75ddaf45
ER
7138-$(SAPI_CGI_PATH): libphp_common.la $(PHP_SAPI_OBJS)
7139+$(SAPI_CGI_PATH): libphp_common.la $(PHP_SAPI_OBJS) $(SAPI_EXTRA_DEPS)
fd1be940 7140 $(BUILD_CGI)
This page took 6.727544 seconds and 4 git commands to generate.