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