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