1 diff -Nru php-5.2.6.vanilla/configure php-5.2.6.fpm/configure
2 diff -Nru php-5.2.6.vanilla/configure.in php-5.2.6.fpm/configure.in
3 --- php-5.2.6.vanilla/configure.in 2008-04-30 22:27:55.000000000 +0400
4 +++ php-5.2.6.fpm/configure.in 2008-05-01 20:42:05.000000000 +0400
9 +if test "$PHP_FASTCGI" = "yes" -a "$PHP_FPM" = "yes"; then
10 + PHP_CONFIGURE_PART(Running FastCGI Process Manager checks)
11 + sinclude(sapi/cgi/fpm/acinclude.m4)
12 + sinclude(sapi/cgi/fpm/config.m4)
17 dnl ## In diversion 3 we check for compile-time options to the PHP
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)
36 install_targets="$PHP_INSTALL_CLI_TARGET $install_targets"
39 - install_targets="install-sapi $PHP_INSTALL_CLI_TARGET $install_targets"
40 + install_targets="install-sapi $install_fpm $PHP_INSTALL_CLI_TARGET $install_targets"
44 diff -Nru php-5.2.6.vanilla/libevent/aclocal.m4 php-5.2.6.fpm/libevent/aclocal.m4
45 diff -Nru php-5.2.6.vanilla/libevent/autogen.sh php-5.2.6.fpm/libevent/autogen.sh
46 diff -Nru php-5.2.6.vanilla/libevent/ChangeLog php-5.2.6.fpm/libevent/ChangeLog
47 diff -Nru php-5.2.6.vanilla/libevent/compat/sys/queue.h php-5.2.6.fpm/libevent/compat/sys/queue.h
48 diff -Nru php-5.2.6.vanilla/libevent/compat/sys/_time.h php-5.2.6.fpm/libevent/compat/sys/_time.h
49 diff -Nru php-5.2.6.vanilla/libevent/config.guess php-5.2.6.fpm/libevent/config.guess
50 diff -Nru php-5.2.6.vanilla/libevent/config.h.in php-5.2.6.fpm/libevent/config.h.in
51 diff -Nru php-5.2.6.vanilla/libevent/config.sub php-5.2.6.fpm/libevent/config.sub
52 diff -Nru php-5.2.6.vanilla/libevent/configure php-5.2.6.fpm/libevent/configure
53 diff -Nru php-5.2.6.vanilla/libevent/configure.in php-5.2.6.fpm/libevent/configure.in
54 diff -Nru php-5.2.6.vanilla/libevent/depcomp php-5.2.6.fpm/libevent/depcomp
55 diff -Nru php-5.2.6.vanilla/libevent/devpoll.c php-5.2.6.fpm/libevent/devpoll.c
56 diff -Nru php-5.2.6.vanilla/libevent/epoll.c php-5.2.6.fpm/libevent/epoll.c
57 diff -Nru php-5.2.6.vanilla/libevent/epoll_sub.c php-5.2.6.fpm/libevent/epoll_sub.c
58 diff -Nru php-5.2.6.vanilla/libevent/event.3 php-5.2.6.fpm/libevent/event.3
59 diff -Nru php-5.2.6.vanilla/libevent/event.c php-5.2.6.fpm/libevent/event.c
60 diff -Nru php-5.2.6.vanilla/libevent/event-config.h php-5.2.6.fpm/libevent/event-config.h
61 diff -Nru php-5.2.6.vanilla/libevent/event-fpm.h php-5.2.6.fpm/libevent/event-fpm.h
62 diff -Nru php-5.2.6.vanilla/libevent/event.h php-5.2.6.fpm/libevent/event.h
63 diff -Nru php-5.2.6.vanilla/libevent/event-internal.h php-5.2.6.fpm/libevent/event-internal.h
64 diff -Nru php-5.2.6.vanilla/libevent/evport.c php-5.2.6.fpm/libevent/evport.c
65 diff -Nru php-5.2.6.vanilla/libevent/evsignal.h php-5.2.6.fpm/libevent/evsignal.h
66 diff -Nru php-5.2.6.vanilla/libevent/evutil.c php-5.2.6.fpm/libevent/evutil.c
67 diff -Nru php-5.2.6.vanilla/libevent/evutil.h php-5.2.6.fpm/libevent/evutil.h
68 diff -Nru php-5.2.6.vanilla/libevent/install-sh php-5.2.6.fpm/libevent/install-sh
69 diff -Nru php-5.2.6.vanilla/libevent/kqueue.c php-5.2.6.fpm/libevent/kqueue.c
70 diff -Nru php-5.2.6.vanilla/libevent/log.c php-5.2.6.fpm/libevent/log.c
71 diff -Nru php-5.2.6.vanilla/libevent/log.h php-5.2.6.fpm/libevent/log.h
72 diff -Nru php-5.2.6.vanilla/libevent/Makefile.am php-5.2.6.fpm/libevent/Makefile.am
73 diff -Nru php-5.2.6.vanilla/libevent/Makefile.in php-5.2.6.fpm/libevent/Makefile.in
74 diff -Nru php-5.2.6.vanilla/libevent/min_heap.h php-5.2.6.fpm/libevent/min_heap.h
75 diff -Nru php-5.2.6.vanilla/libevent/missing php-5.2.6.fpm/libevent/missing
76 diff -Nru php-5.2.6.vanilla/libevent/mkinstalldirs php-5.2.6.fpm/libevent/mkinstalldirs
77 diff -Nru php-5.2.6.vanilla/libevent/poll.c php-5.2.6.fpm/libevent/poll.c
78 diff -Nru php-5.2.6.vanilla/libevent/README php-5.2.6.fpm/libevent/README
79 diff -Nru php-5.2.6.vanilla/libevent/select.c php-5.2.6.fpm/libevent/select.c
80 diff -Nru php-5.2.6.vanilla/libevent/signal.c php-5.2.6.fpm/libevent/signal.c
81 diff -Nru php-5.2.6.vanilla/main/php_config.h.in php-5.2.6.fpm/main/php_config.h.in
82 --- php-5.2.6.vanilla/main/php_config.h.in 2008-04-30 22:37:39.000000000 +0400
83 +++ php-5.2.6.fpm/main/php_config.h.in 2008-09-21 17:37:45.000000000 +0400
85 /* Define if you have the chroot function. */
88 +/* Define if you have the clearenv function. */
91 /* Define if you have the crypt function. */
98 +/* Is experimental fastcgi process manager code activated */
99 +#undef PHP_FASTCGI_PM
102 #undef FORCE_CGI_REDIRECT
106 #undef ENABLE_PATHINFO_CHECK
108 +/* do we have libxml? */
111 +/* do we have prctl? */
114 +/* do we have clock_gettime? */
115 +#undef HAVE_CLOCK_GETTIME
117 +/* do we have clock_get_time? */
118 +#undef HAVE_CLOCK_GET_TIME
120 +/* do we have ptrace? */
123 +/* do we have mach_vm_read? */
124 +#undef HAVE_MACH_VM_READ
126 +/* /proc/pid/mem interface */
127 +#undef PROC_MEM_FILE
129 /* Define if system uses EBCDIC */
130 #undef CHARSET_EBCDIC
132 diff -Nru php-5.2.6.vanilla/sapi/cgi/cgi_main.c php-5.2.6.fpm/sapi/cgi/cgi_main.c
133 --- php-5.2.6.vanilla/sapi/cgi/cgi_main.c 2008-04-09 13:16:40.000000000 +0400
134 +++ php-5.2.6.fpm/sapi/cgi/cgi_main.c 2008-07-22 01:50:58.000000000 +0400
137 #include <sys/wait.h>
143 #include "zend_extensions.h"
150 +#include "fpm/fpm.h"
151 +#include "fpm/fpm_request.h"
155 /* XXX this will need to change later when threaded fastcgi is
156 implemented. shane */
161 +static int request_body_fd;
165 +static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC);
167 #define PHP_MODE_STANDARD 1
168 #define PHP_MODE_HIGHLIGHT 2
169 #define PHP_MODE_INDENT 3
172 {'?', 0, "usage"},/* help alias (both '?' and 'usage') */
176 + {'y', 1, "fpm-config"},
178 {'z', 1, "zend-extension"},
182 zend_bool impersonate;
185 + char *error_header;
186 } php_cgi_globals_struct;
191 if (fcgi_is_fastcgi()) {
192 fcgi_request *request = (fcgi_request*) SG(server_context);
193 - tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
195 + if (request_body_fd == -1) {
196 + char *request_body_filename = sapi_cgibin_getenv((char *) "REQUEST_BODY_FILE",
197 + sizeof("REQUEST_BODY_FILE")-1 TSRMLS_CC);
199 + if (request_body_filename && *request_body_filename) {
200 + request_body_fd = open(request_body_filename, O_RDONLY);
202 + if (0 > request_body_fd) {
203 + php_error(E_WARNING, "REQUEST_BODY_FILE: open('%s') failed: %s (%d)",
204 + request_body_filename, strerror(errno), errno);
210 + /* If REQUEST_BODY_FILE variable not available - read post body from fastcgi stream */
211 + if (request_body_fd < 0) {
212 + tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
214 + tmp_read_bytes = read(request_body_fd, buffer + read_bytes, count_bytes - read_bytes);
217 tmp_read_bytes = read(0, buffer + read_bytes, count_bytes - read_bytes);
220 " -s Display colour syntax highlighted source.\n"
221 " -v Version number\n"
222 " -w Display source with stripped comments and whitespace.\n"
223 - " -z <file> Load Zend extension <file>.\n"
225 + " -x, --fpm Run in FastCGI process manager mode.\n"
226 + " -y, --fpm-config <file>\n"
227 + " Specify alternative path to FastCGI process manager config file.\n"
229 + " -z <file> Load Zend extension <file>.\n"
231 " -T <count> Measure execution time of script repeated <count> times.\n"
233 @@ -1173,6 +1216,7 @@
235 STD_PHP_INI_ENTRY("fastcgi.impersonate", "0", PHP_INI_SYSTEM, OnUpdateBool, impersonate, php_cgi_globals_struct, php_cgi_globals)
237 + STD_PHP_INI_ENTRY("fastcgi.error_header", NULL, PHP_INI_SYSTEM, OnUpdateString, error_header, php_cgi_globals_struct, php_cgi_globals)
241 @@ -1195,6 +1239,7 @@
243 php_cgi_globals->impersonate = 0;
245 + php_cgi_globals->error_header = NULL;
249 @@ -1227,9 +1272,47 @@
250 static PHP_MINFO_FUNCTION(cgi)
252 DISPLAY_INI_ENTRIES();
256 +#include "fpm/fpm_autoconf.h"
258 + php_info_print_table_start();
259 + php_info_print_table_row(2, "php-fpm", fpm ? "active" : "inactive");
260 + php_info_print_table_row(2, "php-fpm version", PHP_FPM_VERSION);
261 + php_info_print_table_end();
268 +PHP_FUNCTION(fastcgi_finish_request)
270 + fcgi_request *request = (fcgi_request*) SG(server_context);
272 + if (fcgi_is_fastcgi() && request->fd >= 0) {
274 + php_end_ob_buffers(1 TSRMLS_CC);
275 + php_header(TSRMLS_C);
277 + fcgi_flush(request, 1);
278 + fcgi_close(request, 0, 0);
287 +function_entry cgi_fcgi_sapi_functions[] = {
289 + PHP_FE(fastcgi_finish_request, NULL)
294 static zend_module_entry cgi_module_entry = {
295 STANDARD_MODULE_HEADER,
297 @@ -1237,7 +1320,7 @@
302 + cgi_fcgi_sapi_functions,
306 @@ -1277,6 +1360,7 @@
307 char *bindpath = NULL;
309 fcgi_request request;
310 + char *fpm_config = NULL;
313 #if HAVE_GETTIMEOFDAY
314 @@ -1397,6 +1481,14 @@
315 case 's': /* generate highlighted HTML from source */
316 behavior = PHP_MODE_HIGHLIGHT;
320 + fpm_config = php_optarg;
329 @@ -1459,6 +1551,19 @@
330 #endif /* FORCE_CGI_REDIRECT */
335 + if (0 > fpm_init(argc, argv, fpm_config)) {
339 + fcgi_fd = fpm_run(&max_requests);
341 + fcgi_set_is_fastcgi(fastcgi = 1);
347 fcgi_fd = fcgi_listen(bindpath, 128);
349 @@ -1473,7 +1578,7 @@
352 /* How many times to run PHP scripts before dying */
353 - if (getenv("PHP_FCGI_MAX_REQUESTS")) {
354 + if (!fpm && getenv("PHP_FCGI_MAX_REQUESTS")) {
355 max_requests = atoi(getenv("PHP_FCGI_MAX_REQUESTS"));
356 if (max_requests < 0) {
357 fprintf(stderr, "PHP_FCGI_MAX_REQUESTS is not valid\n");
358 @@ -1490,7 +1595,7 @@
361 /* Pre-fork, if required */
362 - if (getenv("PHP_FCGI_CHILDREN")) {
363 + if (!fpm && getenv("PHP_FCGI_CHILDREN")) {
364 children = atoi(getenv("PHP_FCGI_CHILDREN"));
366 fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
367 @@ -1616,6 +1721,8 @@
371 + request_body_fd = -1;
373 SG(server_context) = (void *) &request;
375 SG(server_context) = (void *) 1; /* avoid server_context==NULL checks */
376 @@ -1623,6 +1730,10 @@
377 init_request_info(TSRMLS_C);
381 + if (fpm) fpm_request_info();
387 @@ -1914,6 +2025,10 @@
392 + if (fpm) fpm_request_executing();
396 case PHP_MODE_STANDARD:
397 php_execute_script(&file_handle TSRMLS_CC);
398 @@ -1966,6 +2081,10 @@
401 fastcgi_request_done:
403 + if (request_body_fd != -1) close(request_body_fd);
405 + request_body_fd = -2;
408 char *path_translated;
409 @@ -1979,6 +2098,16 @@
410 SG(request_info).path_translated = path_translated;
413 + if (EG(exit_status) == 255) {
414 + if (CGIG(error_header) && *CGIG(error_header)) {
415 + sapi_header_line ctr = {0};
417 + ctr.line = CGIG(error_header);
418 + ctr.line_len = strlen(CGIG(error_header));
419 + sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC);
423 php_request_shutdown((void *) 0);
424 if (exit_status == 0) {
425 exit_status = EG(exit_status);
426 @@ -2016,15 +2145,20 @@
430 - if (max_requests != 1) {
431 - /* no need to return exit_status of the last request */
436 /* end of fastcgi loop */
440 + if (fcgi_in_shutdown() || /* graceful shutdown by a signal */
441 + (max_requests && (requests == max_requests)) /* we were told to process max_requests and we are done */
450 if (cgi_sapi_module.php_ini_path_override) {
451 diff -Nru php-5.2.6.vanilla/sapi/cgi/config9.m4 php-5.2.6.fpm/sapi/cgi/config9.m4
452 --- php-5.2.6.vanilla/sapi/cgi/config9.m4 2007-07-12 03:20:36.000000000 +0400
453 +++ php-5.2.6.fpm/sapi/cgi/config9.m4 2008-07-20 20:46:41.000000000 +0400
455 [ --disable-path-info-check CGI: If this is disabled, paths such as
456 /info.php/test?a=b will fail to work], yes, no)
458 +PHP_ARG_ENABLE(fpm,,
459 +[ --enable-fpm FastCGI: If this is enabled, the fastcgi support
460 + will include experimental process manager code], no, no)
466 AC_DEFINE_UNQUOTED(PHP_FASTCGI, $PHP_ENABLE_FASTCGI, [ ])
467 AC_MSG_RESULT($PHP_FASTCGI)
470 + if test "$PHP_FASTCGI" = "yes"; then
471 + AC_MSG_CHECKING(whether to enable FastCGI Process Manager)
472 + if test "$PHP_FPM" = "yes"; then
477 + AC_MSG_RESULT($PHP_FPM)
481 + AC_DEFINE_UNQUOTED(PHP_FASTCGI_PM, $PHP_FASTCGI_PM, [Is experimental fastcgi process manager code activated])
483 dnl --enable-force-cgi-redirect
484 AC_MSG_CHECKING(whether to force Apache CGI redirect)
485 if test "$PHP_FORCE_CGI_REDIRECT" = "yes"; then
487 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)"
490 - 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)"
491 + 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) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
494 - BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
495 + BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_SAPI_OBJS) \$(EXTRA_LIBS) \$(SAPI_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
499 diff -Nru php-5.2.6.vanilla/sapi/cgi/fastcgi.c php-5.2.6.fpm/sapi/cgi/fastcgi.c
500 --- php-5.2.6.vanilla/sapi/cgi/fastcgi.c 2008-04-03 14:24:44.000000000 +0400
501 +++ php-5.2.6.fpm/sapi/cgi/fastcgi.c 2008-05-15 23:37:01.000000000 +0400
507 +#include "fpm/fpm.h"
508 +#include "fpm/fpm_request.h"
516 return is_fastcgi = 0;
519 + fcgi_set_allowed_clients(getenv("FCGI_WEB_SERVER_ADDRS"));
527 +void fcgi_set_is_fastcgi(int new_value)
529 + is_fastcgi = new_value;
532 +void fcgi_set_in_shutdown(int new_value)
534 + in_shutdown = new_value;
537 void fcgi_shutdown(void)
541 + if (allowed_clients) {
542 + free(allowed_clients);
543 + allowed_clients = 0;
552 +void fcgi_set_allowed_clients(char *ip)
562 + if (*cur == ',') n++;
565 + if (allowed_clients) free(allowed_clients);
566 + allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
570 + end = strchr(cur, ',');
575 + allowed_clients[n] = inet_addr(cur);
576 + if (allowed_clients[n] == INADDR_NONE) {
577 + fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur);
582 + allowed_clients[n] = INADDR_NONE;
587 static int is_port_number(const char *bindpath)
595 - char *ip = getenv("FCGI_WEB_SERVER_ADDRS");
604 - if (*cur == ',') n++;
607 - allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
611 - end = strchr(cur, ',');
616 - allowed_clients[n] = inet_addr(cur);
617 - if (allowed_clients[n] == INADDR_NONE) {
618 - fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur);
623 - allowed_clients[n] = INADDR_NONE;
628 if (!is_initialized) {
633 -static inline void fcgi_close(fcgi_request *req, int force, int destroy)
634 +void fcgi_close(fcgi_request *req, int force, int destroy)
637 zend_hash_destroy(&req->env);
644 + if (fpm) fpm_request_finished();
651 socklen_t len = sizeof(sa);
654 + if (fpm) fpm_request_accepting();
657 FCGI_LOCK(req->listen_socket);
658 req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
659 FCGI_UNLOCK(req->listen_socket);
666 + if (fpm) fpm_request_reading_headers();
669 #if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
672 diff -Nru php-5.2.6.vanilla/sapi/cgi/fastcgi.h php-5.2.6.fpm/sapi/cgi/fastcgi.h
673 --- php-5.2.6.vanilla/sapi/cgi/fastcgi.h 2007-12-31 10:20:16.000000000 +0300
674 +++ php-5.2.6.fpm/sapi/cgi/fastcgi.h 2008-05-01 20:42:06.000000000 +0400
677 void fcgi_shutdown(void);
678 int fcgi_is_fastcgi(void);
679 +void fcgi_set_is_fastcgi(int);
680 +void fcgi_set_in_shutdown(int);
681 +void fcgi_set_allowed_clients(char *);
682 int fcgi_in_shutdown(void);
683 int fcgi_listen(const char *path, int backlog);
684 void fcgi_init_request(fcgi_request *req, int listen_socket);
686 int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len);
687 int fcgi_flush(fcgi_request *req, int close);
689 +void fcgi_close(fcgi_request *req, int force, int destroy);
692 void fcgi_impersonate(void);
694 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/acinclude.m4 php-5.2.6.fpm/sapi/cgi/fpm/acinclude.m4
695 --- php-5.2.6.vanilla/sapi/cgi/fpm/acinclude.m4 1970-01-01 03:00:00.000000000 +0300
696 +++ php-5.2.6.fpm/sapi/cgi/fpm/acinclude.m4 2008-07-21 06:39:38.000000000 +0400
699 +AC_DEFUN([AC_FPM_CHECK_FUNC],
701 + SAVED_CFLAGS="$CFLAGS"
702 + CFLAGS="$CFLAGS $2"
706 + AC_CHECK_FUNC([$1],[$4],[$5])
708 + CFLAGS="$SAVED_CFLAGS"
712 +AC_DEFUN([AC_FPM_LIBEVENT],
714 + AC_ARG_WITH([libevent],
715 + [ --with-libevent=DIR FPM: libevent install directory])
718 + LIBEVENT_LIBS="-levent"
719 + LIBEVENT_INCLUDE_PATH=""
721 + if test "$with_libevent" != "no" -a -n "$with_libevent"; then
722 + LIBEVENT_CFLAGS="-I$with_libevent/include"
723 + LIBEVENT_LIBS="-L$with_libevent/lib $LIBEVENT_LIBS"
724 + LIBEVENT_INCLUDE_PATH="$with_libevent/include"
727 + AC_MSG_CHECKING([for event.h])
731 + for dir in "$LIBEVENT_INCLUDE_PATH" /usr/include ; do
732 + if test -r "$dir/event.h" ; then
738 + AC_MSG_RESULT([$found])
740 + AC_FPM_CHECK_FUNC([event_set], [$LIBEVENT_CFLAGS], [$LIBEVENT_LIBS], ,
741 + [AC_MSG_ERROR([Failed to link with libevent. Perhaps --with-libevent=DIR option could help.])])
743 + AC_FPM_CHECK_FUNC([event_base_free], [$LIBEVENT_CFLAGS], [$LIBEVENT_LIBS], ,
744 + [AC_MSG_ERROR([You have too old version. libevent version >= 1.2 is required.])])
748 +AC_DEFUN([AC_FPM_LIBXML],
750 + AC_MSG_RESULT([checking for XML configuration])
752 + AC_ARG_WITH(xml-config,
753 + [ --with-xml-config=PATH FPM: use xml-config in PATH to find libxml],
754 + [XMLCONFIG="$withval"],
755 + [AC_PATH_PROGS(XMLCONFIG, [xml2-config xml-config], "")]
758 + if test "x$XMLCONFIG" = "x"; then
759 + AC_MSG_ERROR([XML configuration could not be found])
761 + AC_MSG_CHECKING([for libxml library])
763 + if test ! -x "$XMLCONFIG"; then
764 + AC_MSG_ERROR([$XMLCONFIG cannot be executed])
767 + LIBXML_LIBS="`$XMLCONFIG --libs`"
768 + LIBXML_CFLAGS="`$XMLCONFIG --cflags`"
769 + LIBXML_VERSION="`$XMLCONFIG --version`"
771 + AC_MSG_RESULT([yes, $LIBXML_VERSION])
773 + AC_FPM_CHECK_FUNC([xmlParseFile], [$LIBXML_CFLAGS], [$LIBXML_LIBS], ,
774 + [AC_MSG_ERROR([Failed to link with libxml])])
776 + AC_DEFINE(HAVE_LIBXML, 1, [do we have libxml?])
780 +AC_DEFUN([AC_FPM_JUDY],
782 + AC_ARG_WITH([Judy],
783 + [ --with-Judy=DIR FPM: Judy install directory])
787 + JUDY_INCLUDE_PATH=""
789 + if test "$with_Judy" != "no" -a -n "$with_Judy"; then
790 + JUDY_INCLUDE_PATH="$with_Judy/include"
791 + JUDY_CFLAGS="-I$with_Judy/include $JUDY_CFLAGS"
792 + JUDY_LIBS="-L$with_Judy/lib $JUDY_LIBS"
795 + AC_MSG_CHECKING([for Judy.h])
799 + for dir in "$JUDY_INCLUDE_PATH" /usr/include ; do
800 + if test -r "$dir/Judy.h" ; then
806 + AC_MSG_RESULT([$found])
808 + AC_FPM_CHECK_FUNC([JudyLCount], [$JUDY_CFLAGS], [$JUDY_LIBS], ,
809 + [AC_MSG_ERROR([Failed to link with Judy])])
813 +AC_DEFUN([AC_FPM_CLOCK],
815 + have_clock_gettime=no
817 + AC_MSG_CHECKING([for clock_gettime])
819 + AC_TRY_COMPILE([ #include <time.h> ], [struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);], [
820 + have_clock_gettime=yes
821 + AC_MSG_RESULT([yes])
823 + AC_MSG_RESULT([no])
826 + if test "$have_clock_gettime" = "no"; then
827 + AC_MSG_CHECKING([for clock_gettime in -lrt])
832 + AC_TRY_COMPILE([ #include <time.h> ], [struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts);], [
833 + have_clock_gettime=yes
834 + AC_MSG_RESULT([yes])
837 + AC_MSG_RESULT([no])
841 + if test "$have_clock_gettime" = "yes"; then
842 + AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [do we have clock_gettime?])
845 + have_clock_get_time=no
847 + if test "$have_clock_gettime" = "no"; then
848 + AC_MSG_CHECKING([for clock_get_time])
850 + AC_TRY_RUN([ #include <mach/mach.h>
851 + #include <mach/clock.h>
852 + #include <mach/mach_error.h>
856 + kern_return_t ret; clock_serv_t aClock; mach_timespec_t aTime;
857 + ret = host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &aClock);
859 + if (ret != KERN_SUCCESS) {
863 + ret = clock_get_time(aClock, &aTime);
864 + if (ret != KERN_SUCCESS) {
871 + have_clock_get_time=yes
872 + AC_MSG_RESULT([yes])
874 + AC_MSG_RESULT([no])
878 + if test "$have_clock_get_time" = "yes"; then
879 + AC_DEFINE([HAVE_CLOCK_GET_TIME], 1, [do we have clock_get_time?])
883 +AC_DEFUN([AC_FPM_TRACE],
886 + have_broken_ptrace=no
888 + AC_MSG_CHECKING([for ptrace])
891 + #include <sys/types.h>
892 + #include <sys/ptrace.h> ], [ptrace(0, 0, (void *) 0, 0);], [
894 + AC_MSG_RESULT([yes])
896 + AC_MSG_RESULT([no])
899 + if test "$have_ptrace" = "yes"; then
900 + AC_MSG_CHECKING([whether ptrace works])
903 + #include <unistd.h>
904 + #include <signal.h>
905 + #include <sys/wait.h>
906 + #include <sys/types.h>
907 + #include <sys/ptrace.h>
910 + #if !defined(PTRACE_ATTACH) && defined(PT_ATTACH)
911 + #define PTRACE_ATTACH PT_ATTACH
914 + #if !defined(PTRACE_DETACH) && defined(PT_DETACH)
915 + #define PTRACE_DETACH PT_DETACH
918 + #if !defined(PTRACE_PEEKDATA) && defined(PT_READ_D)
919 + #define PTRACE_PEEKDATA PT_READ_D
924 + long v1 = (unsigned int) -1; /* copy will fail if sizeof(long) == 8 and we've got "int ptrace()" */
929 + if ( (child = fork()) ) { /* parent */
932 + if (0 > ptrace(PTRACE_ATTACH, child, 0, 0)) {
936 + waitpid(child, &status, 0);
939 + struct ptrace_io_desc ptio = {
940 + .piod_op = PIOD_READ_D,
943 + .piod_len = sizeof(v1)
946 + if (0 > ptrace(PT_IO, child, (void *) &ptio, 0)) {
952 + v2 = ptrace(PTRACE_PEEKDATA, child, (void *) &v1, 0);
958 + ptrace(PTRACE_DETACH, child, (void *) 1, 0);
960 + kill(child, SIGKILL);
962 + return ret ? ret : (v1 != v2);
970 + AC_MSG_RESULT([yes])
973 + have_broken_ptrace=yes
974 + AC_MSG_RESULT([no])
978 + if test "$have_ptrace" = "yes"; then
979 + AC_DEFINE([HAVE_PTRACE], 1, [do we have ptrace?])
982 + have_mach_vm_read=no
984 + if test "$have_broken_ptrace" = "yes"; then
985 + AC_MSG_CHECKING([for mach_vm_read])
987 + AC_TRY_COMPILE([ #include <mach/mach.h>
988 + #include <mach/mach_vm.h>
990 + 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);
992 + have_mach_vm_read=yes
993 + AC_MSG_RESULT([yes])
995 + AC_MSG_RESULT([no])
999 + if test "$have_mach_vm_read" = "yes"; then
1000 + AC_DEFINE([HAVE_MACH_VM_READ], 1, [do we have mach_vm_read?])
1005 + if test -r /proc/$$/mem ; then
1006 + proc_mem_file="mem"
1008 + if test -r /proc/$$/as ; then
1009 + proc_mem_file="as"
1013 + if test -n "$proc_mem_file" ; then
1014 + AC_MSG_CHECKING([for proc mem file])
1017 + #define _GNU_SOURCE
1018 + #define _FILE_OFFSET_BITS 64
1019 + #include <stdint.h>
1020 + #include <unistd.h>
1021 + #include <sys/types.h>
1022 + #include <sys/stat.h>
1023 + #include <fcntl.h>
1024 + #include <stdio.h>
1027 + long v1 = (unsigned int) -1, v2 = 0;
1030 + sprintf(buf, "/proc/%d/$proc_mem_file", getpid());
1031 + fd = open(buf, O_RDONLY);
1035 + if (sizeof(long) != pread(fd, &v2, sizeof(long), (uintptr_t) &v1)) {
1043 + AC_MSG_RESULT([$proc_mem_file])
1046 + AC_MSG_RESULT([no])
1050 + if test -n "$proc_mem_file"; then
1051 + AC_DEFINE_UNQUOTED([PROC_MEM_FILE], "$proc_mem_file", [/proc/pid/mem interface])
1056 + if test "$have_ptrace" = "yes"; then
1057 + FPM_TRACE_SRCS="fpm_trace_ptrace.c"
1058 + elif test -n "$proc_mem_file"; then
1059 + FPM_TRACE_SRCS="fpm_trace_pread.c"
1060 + elif test "$have_mach_vm_read" = "yes" ; then
1061 + FPM_TRACE_SRCS="fpm_trace_mach.c"
1064 + if test -n "$FPM_TRACE_SRCS"; then
1065 + FPM_TRACE_SRCS="fpm_trace.c $FPM_TRACE_SRCS"
1070 +AC_DEFUN([AC_FPM_PRCTL],
1072 + AC_MSG_CHECKING([for prctl])
1074 + AC_TRY_COMPILE([ #include <sys/prctl.h> ], [prctl(0, 0, 0, 0, 0);], [
1075 + AC_DEFINE([HAVE_PRCTL], 1, [do we have prctl?])
1076 + AC_MSG_RESULT([yes])
1078 + AC_MSG_RESULT([no])
1081 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/conf/php-fpm.conf.in php-5.2.6.fpm/sapi/cgi/fpm/conf/php-fpm.conf.in
1082 --- php-5.2.6.vanilla/sapi/cgi/fpm/conf/php-fpm.conf.in 1970-01-01 03:00:00.000000000 +0300
1083 +++ php-5.2.6.fpm/sapi/cgi/fpm/conf/php-fpm.conf.in 2008-05-23 00:53:15.000000000 +0400
1085 +<?xml version="1.0" ?>
1088 + All relative paths in this config are relative to php's install prefix
1090 + <section name="global_options">
1093 + <value name="pid_file">@php_fpm_pid_path@</value>
1096 + <value name="error_log">@php_fpm_log_path@</value>
1099 + <value name="log_level">notice</value>
1101 + When this amount of php processes exited with SIGSEGV or SIGBUS ...
1102 + <value name="emergency_restart_threshold">10</value>
1104 + ... in a less than this interval of time, a graceful restart will be initiated.
1105 + Useful to work around accidental curruptions in accelerator's shared memory.
1106 + <value name="emergency_restart_interval">1m</value>
1108 + Time limit on waiting child's reaction on signals from master
1109 + <value name="process_control_timeout">5s</value>
1111 + Set to 'no' to debug fpm
1112 + <value name="daemonize">yes</value>
1118 + <section name="pool">
1120 + Name of pool. Used in logs and stats.
1121 + <value name="name">default</value>
1123 + Address to accept fastcgi requests on.
1124 + Valid syntax is 'ip.ad.re.ss:port' or just 'port' or '/path/to/unix/socket'
1125 + <value name="listen_address">127.0.0.1:9000</value>
1127 + <value name="listen_options">
1129 + Set listen(2) backlog
1130 + <value name="backlog">-1</value>
1132 + Set permissions for unix socket, if one used.
1133 + In Linux read/write permissions must be set in order to allow connections from web server.
1134 + Many BSD-derrived systems allow connections regardless of permissions.
1135 + <value name="owner"></value>
1136 + <value name="group"></value>
1137 + <value name="mode">0666</value>
1140 + Additional php.ini defines, specific to this pool of workers.
1141 + <value name="php_defines">
1142 + <!-- <value name="sendmail_path">/usr/sbin/sendmail -t -i</value> -->
1143 + <!-- <value name="display_errors">0</value> -->
1146 + Unix user of processes
1147 + <!-- <value name="user">nobody</value> -->
1149 + Unix group of processes
1150 + <!-- <value name="group">@php_fpm_group@</value> -->
1152 + Process manager settings
1155 + Sets style of controling worker process count.
1156 + Valid values are 'static' and 'apache-like'
1157 + <value name="style">static</value>
1159 + Sets the limit on the number of simultaneous requests that will be served.
1160 + Equivalent to Apache MaxClients directive.
1161 + Equivalent to PHP_FCGI_CHILDREN environment in original php.fcgi
1162 + Used with any pm_style.
1163 + <value name="max_children">5</value>
1165 + Settings group for 'apache-like' pm style
1166 + <value name="apache_like">
1168 + Sets the number of server processes created on startup.
1169 + Used only when 'apache-like' pm_style is selected
1170 + <value name="StartServers">20</value>
1172 + Sets the desired minimum number of idle server processes.
1173 + Used only when 'apache-like' pm_style is selected
1174 + <value name="MinSpareServers">5</value>
1176 + Sets the desired maximum number of idle server processes.
1177 + Used only when 'apache-like' pm_style is selected
1178 + <value name="MaxSpareServers">35</value>
1184 + The timeout (in seconds) for serving a single request after which the worker process will be terminated
1185 + Should be used when 'max_execution_time' ini option does not stop script execution for some reason
1187 + <value name="request_terminate_timeout">0s</value>
1189 + The timeout (in seconds) for serving of single request after which a php backtrace will be dumped to slow.log file
1191 + <value name="request_slowlog_timeout">0s</value>
1193 + The log file for slow requests
1194 + <value name="slowlog">logs/slow.log</value>
1196 + Set open file desc rlimit
1197 + <value name="rlimit_files">1024</value>
1199 + Set max core size rlimit
1200 + <value name="rlimit_core">0</value>
1202 + Chroot to this directory at the start, absolute path
1203 + <value name="chroot"></value>
1205 + Chdir to this directory at the start, absolute path
1206 + <value name="chdir"></value>
1208 + Redirect workers' stdout and stderr into main error log.
1209 + If not set, they will be redirected to /dev/null, according to FastCGI specs
1210 + <value name="catch_workers_output">yes</value>
1212 + How much requests each process should execute before respawn.
1213 + Useful to work around memory leaks in 3rd party libraries.
1214 + For endless request processing please specify 0
1215 + Equivalent to PHP_FCGI_MAX_REQUESTS
1216 + <value name="max_requests">500</value>
1218 + Comma separated list of ipv4 addresses of FastCGI clients that allowed to connect.
1219 + Equivalent to FCGI_WEB_SERVER_ADDRS environment in original php.fcgi (5.2.2+)
1220 + Makes sense only with AF_INET listening socket.
1221 + <value name="allowed_clients">127.0.0.1</value>
1223 + Pass environment variables like LD_LIBRARY_PATH
1224 + All $VARIABLEs are taken from current environment
1225 + <value name="environment">
1226 + <value name="HOSTNAME">$HOSTNAME</value>
1227 + <value name="PATH">/usr/local/bin:/usr/bin:/bin</value>
1228 + <value name="TMP">/tmp</value>
1229 + <value name="TMPDIR">/tmp</value>
1230 + <value name="TEMP">/tmp</value>
1231 + <value name="OSTYPE">$OSTYPE</value>
1232 + <value name="MACHTYPE">$MACHTYPE</value>
1233 + <value name="MALLOC_CHECK_">2</value>
1241 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/config.m4 php-5.2.6.fpm/sapi/cgi/fpm/config.m4
1242 --- php-5.2.6.vanilla/sapi/cgi/fpm/config.m4 1970-01-01 03:00:00.000000000 +0300
1243 +++ php-5.2.6.fpm/sapi/cgi/fpm/config.m4 2008-09-19 05:22:37.000000000 +0400
1246 +FPM_VERSION="0.5.9"
1248 +PHP_ARG_WITH(fpm-conf, for php-fpm config file path,
1249 +[ --with-fpm-conf=PATH Set the path for php-fpm configuration file [PREFIX/etc/php-fpm.conf]], \$prefix/etc/php-fpm.conf, no)
1251 +PHP_ARG_WITH(fpm-log, for php-fpm log file path,
1252 +[ --with-fpm-log=PATH Set the path for php-fpm log file [PREFIX/logs/php-fpm.log]], \$prefix/logs/php-fpm.log, no)
1254 +PHP_ARG_WITH(fpm-pid, for php-fpm pid file path,
1255 +[ --with-fpm-pid=PATH Set the path for php-fpm pid file [PREFIX/logs/php-fpm.pid]], \$prefix/logs/php-fpm.pid, no)
1257 +dnl AC_FPM_LIBEVENT
1264 +LIBEVENT_CFLAGS="-I$abs_srcdir/libevent"
1265 +LIBEVENT_LIBS="$abs_builddir/libevent/libevent.a"
1267 +SAPI_EXTRA_DEPS="$LIBEVENT_LIBS"
1269 +FPM_SOURCES="fpm.c \
1273 + fpm_worker_pool.c \
1283 + fpm_process_ctl.c \
1291 +FPM_CFLAGS="$LIBEVENT_CFLAGS $LIBXML_CFLAGS $JUDY_CFLAGS"
1293 +dnl FPM_CFLAGS="$FPM_CFLAGS -DJUDYERROR_NOTEST" # for Judy
1294 +FPM_CFLAGS="$FPM_CFLAGS -I$abs_srcdir/sapi/cgi" # for fastcgi.h
1296 +if test "$ICC" = "yes" ; then
1297 + FPM_ADD_CFLAGS="-Wall -wd279,310,869,810,981"
1298 +elif test "$GCC" = "yes" ; then
1299 + FPM_ADD_CFLAGS="-Wall -Wpointer-arith -Wno-unused-parameter -Wunused-variable -Wunused-value -fno-strict-aliasing"
1302 +if test -n "$FPM_WERROR" ; then
1303 + FPM_ADD_CFLAGS="$FPM_ADD_CFLAGS -Werror"
1306 +FPM_CFLAGS="$FPM_ADD_CFLAGS $FPM_CFLAGS"
1308 +PHP_ADD_MAKEFILE_FRAGMENT($abs_srcdir/sapi/cgi/fpm/Makefile.frag)
1310 +PHP_ADD_SOURCES(sapi/cgi/fpm, $FPM_SOURCES, $FPM_CFLAGS, sapi)
1312 +PHP_ADD_BUILD_DIR(sapi/cgi/fpm)
1314 +install_fpm="install-fpm"
1316 +PHP_CONFIGURE_PART(Configuring libevent)
1318 +test -d "$abs_builddir/libevent" || mkdir -p $abs_builddir/libevent
1320 +dnl this is a bad hack
1322 +chmod +x "$abs_srcdir/libevent/configure" \
1323 + "$abs_srcdir/libevent/config.guess" \
1324 + "$abs_srcdir/libevent/config.sub" \
1325 + "$abs_srcdir/libevent/depcomp" \
1326 + "$abs_srcdir/libevent/install-sh" \
1327 + "$abs_srcdir/libevent/missing" \
1328 + "$abs_srcdir/libevent/mkinstalldirs"
1330 +libevent_configure="cd $abs_builddir/libevent ; CFLAGS=\"$CFLAGS $GCC_CFLAGS\" $abs_srcdir/libevent/configure --disable-shared"
1332 +(eval $libevent_configure)
1334 +if test ! -f "$abs_builddir/libevent/Makefile" ; then
1335 + echo "Failed to configure libevent" >&2
1339 +dnl another hack for stealing libevent dependant library list
1341 +LIBEVENT_LIBS="$LIBEVENT_LIBS `echo "@LIBS@" | $abs_builddir/libevent/config.status --file=-:-`"
1343 +SAPI_EXTRA_LIBS="$LIBEVENT_LIBS $LIBXML_LIBS $JUDY_LIBS"
1346 +if test "$prefix" = "NONE" ; then
1347 + fpm_prefix=/usr/local
1349 + fpm_prefix="$prefix"
1352 +if test "$PHP_FPM_CONF" = "\$prefix/etc/php-fpm.conf" ; then
1353 + php_fpm_conf_path="$fpm_prefix/etc/php-fpm.conf"
1355 + php_fpm_conf_path="$PHP_FPM_CONF"
1358 +if test "$PHP_FPM_LOG" = "\$prefix/logs/php-fpm.log" ; then
1359 + php_fpm_log_path="$fpm_prefix/logs/php-fpm.log"
1361 + php_fpm_log_path="$PHP_FPM_LOG"
1364 +if test "$PHP_FPM_PID" = "\$prefix/logs/php-fpm.pid" ; then
1365 + php_fpm_pid_path="$fpm_prefix/logs/php-fpm.pid"
1367 + php_fpm_pid_path="$PHP_FPM_PID"
1371 +if grep nobody /etc/group >/dev/null 2>&1; then
1372 + php_fpm_group=nobody
1374 + if grep nogroup /etc/group >/dev/null 2>&1; then
1375 + php_fpm_group=nogroup
1377 + php_fpm_group=nobody
1381 +PHP_SUBST_OLD(php_fpm_conf_path)
1382 +PHP_SUBST_OLD(php_fpm_log_path)
1383 +PHP_SUBST_OLD(php_fpm_pid_path)
1384 +PHP_SUBST_OLD(php_fpm_group)
1385 +PHP_SUBST_OLD(FPM_VERSION)
1387 +PHP_OUTPUT(sapi/cgi/fpm/fpm_autoconf.h)
1388 +PHP_OUTPUT(sapi/cgi/fpm/php-fpm.conf:sapi/cgi/fpm/conf/php-fpm.conf.in)
1389 +PHP_OUTPUT(sapi/cgi/fpm/php-fpm:sapi/cgi/fpm/init.d/php-fpm.in)
1390 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_arrays.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_arrays.h
1391 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_arrays.h 1970-01-01 03:00:00.000000000 +0300
1392 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_arrays.h 2008-05-24 21:38:47.000000000 +0400
1396 + /* (c) 2007,2008 Andrei Nigmatulin */
1398 +#ifndef FPM_ARRAYS_H
1399 +#define FPM_ARRAYS_H 1
1401 +#include <stdlib.h>
1402 +#include <string.h>
1404 +struct fpm_array_s {
1411 +static inline struct fpm_array_s *fpm_array_init(struct fpm_array_s *a, unsigned int sz, unsigned int initial_num)
1413 + void *allocated = 0;
1416 + a = malloc(sizeof(struct fpm_array_s));
1427 + a->data = calloc(sz, initial_num);
1434 + a->allocated = initial_num;
1440 +static inline void *fpm_array_item(struct fpm_array_s *a, unsigned int n)
1444 + ret = (char *) a->data + a->sz * n;
1449 +static inline void *fpm_array_item_last(struct fpm_array_s *a)
1451 + return fpm_array_item(a, a->used - 1);
1454 +static inline int fpm_array_item_remove(struct fpm_array_s *a, unsigned int n)
1458 + if (n < a->used - 1) {
1459 + void *last = fpm_array_item(a, a->used - 1);
1460 + void *to_remove = fpm_array_item(a, n);
1462 + memcpy(to_remove, last, a->sz);
1472 +static inline void *fpm_array_push(struct fpm_array_s *a)
1476 + if (a->used == a->allocated) {
1477 + size_t new_allocated = a->allocated ? a->allocated * 2 : 20;
1478 + void *new_ptr = realloc(a->data, a->sz * new_allocated);
1484 + a->data = new_ptr;
1485 + a->allocated = new_allocated;
1488 + ret = fpm_array_item(a, a->used);
1495 +static inline void fpm_array_free(struct fpm_array_s *a)
1500 + a->used = a->allocated = 0;
1504 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_atomic.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_atomic.h
1505 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_atomic.h 1970-01-01 03:00:00.000000000 +0300
1506 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_atomic.h 2008-09-19 03:34:11.000000000 +0400
1510 + /* (c) 2007,2008 Andrei Nigmatulin */
1512 +#ifndef FPM_ATOMIC_H
1513 +#define FPM_ATOMIC_H 1
1515 +#include <stdint.h>
1518 +#if ( __i386__ || __i386 )
1520 +typedef int32_t atomic_int_t;
1521 +typedef uint32_t atomic_uint_t;
1522 +typedef volatile atomic_uint_t atomic_t;
1525 +static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add)
1527 + __asm__ volatile ( "lock;" "xaddl %0, %1;" :
1528 + "+r" (add) : "m" (*value) : "memory");
1533 +static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set)
1535 + unsigned char res;
1537 + __asm__ volatile ( "lock;" "cmpxchgl %3, %1;" "sete %0;" :
1538 + "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory");
1543 +#elif ( __amd64__ || __amd64 )
1545 +typedef int64_t atomic_int_t;
1546 +typedef uint64_t atomic_uint_t;
1547 +typedef volatile atomic_uint_t atomic_t;
1549 +static inline atomic_int_t atomic_fetch_add(atomic_t *value, atomic_int_t add)
1551 + __asm__ volatile ( "lock;" "xaddq %0, %1;" :
1552 + "+r" (add) : "m" (*value) : "memory");
1557 +static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, atomic_uint_t set)
1559 + unsigned char res;
1561 + __asm__ volatile ( "lock;" "cmpxchgq %3, %1;" "sete %0;" :
1562 + "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory");
1569 +#error unsupported processor. please write a patch and send it to me
1573 +static inline int fpm_spinlock(atomic_t *lock, int try_once)
1576 + return atomic_cmp_set(lock, 0, 1) ? 0 : -1;
1581 + if (atomic_cmp_set(lock, 0, 1)) {
1593 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_autoconf.h.in php-5.2.6.fpm/sapi/cgi/fpm/fpm_autoconf.h.in
1594 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_autoconf.h.in 1970-01-01 03:00:00.000000000 +0300
1595 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_autoconf.h.in 2008-05-24 21:38:47.000000000 +0400
1599 + /* (c) 2007,2008 Andrei Nigmatulin */
1601 +#define PHP_FPM_VERSION "@FPM_VERSION@"
1602 +#define PHP_FPM_CONF_PATH "@php_fpm_conf_path@"
1603 +#define PHP_FPM_LOG_PATH "@php_fpm_log_path@"
1604 +#define PHP_FPM_PID_PATH "@php_fpm_pid_path@"
1606 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm.c php-5.2.6.fpm/sapi/cgi/fpm/fpm.c
1607 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm.c 1970-01-01 03:00:00.000000000 +0300
1608 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm.c 2008-07-20 20:38:31.000000000 +0400
1612 + /* (c) 2007,2008 Andrei Nigmatulin */
1614 +#include "fpm_config.h"
1616 +#include <stdlib.h> /* for exit */
1619 +#include "fpm_children.h"
1620 +#include "fpm_signals.h"
1621 +#include "fpm_env.h"
1622 +#include "fpm_events.h"
1623 +#include "fpm_cleanup.h"
1624 +#include "fpm_php.h"
1625 +#include "fpm_sockets.h"
1626 +#include "fpm_unix.h"
1627 +#include "fpm_process_ctl.h"
1628 +#include "fpm_conf.h"
1629 +#include "fpm_worker_pool.h"
1630 +#include "fpm_stdio.h"
1635 +struct fpm_globals_s fpm_globals;
1637 +int fpm_init(int argc, char **argv, char *config)
1639 + fpm_globals.argc = argc;
1640 + fpm_globals.argv = argv;
1641 + fpm_globals.config = config;
1643 + if (0 > fpm_php_init_main() ||
1644 + 0 > fpm_stdio_init_main() ||
1645 + 0 > fpm_conf_init_main() ||
1646 + 0 > fpm_unix_init_main() ||
1647 + 0 > fpm_env_init_main() ||
1648 + 0 > fpm_signals_init_main() ||
1649 + 0 > fpm_pctl_init_main() ||
1650 + 0 > fpm_children_init_main() ||
1651 + 0 > fpm_sockets_init_main() ||
1652 + 0 > fpm_worker_pool_init_main() ||
1653 + 0 > fpm_event_init_main()) {
1657 + if (0 > fpm_conf_write_pid()) {
1661 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "fpm is running, pid %d", (int) fpm_globals.parent_pid);
1666 +/* children: return listening socket
1667 + parent: never return */
1668 +int fpm_run(int *max_requests)
1670 + struct fpm_worker_pool_s *wp;
1672 + /* create initial children in all pools */
1673 + for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
1676 + is_parent = fpm_children_create_initial(wp);
1683 + /* run event loop forever */
1686 +run_child: /* only workers reach this point */
1688 + fpm_cleanups_run(FPM_CLEANUP_CHILD);
1690 + *max_requests = fpm_globals.max_requests;
1691 + return fpm_globals.listening_socket;
1694 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_children.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_children.c
1695 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_children.c 1970-01-01 03:00:00.000000000 +0300
1696 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_children.c 2008-08-26 19:09:15.000000000 +0400
1700 + /* (c) 2007,2008 Andrei Nigmatulin */
1702 +#include "fpm_config.h"
1704 +#include <sys/types.h>
1705 +#include <sys/wait.h>
1707 +#include <unistd.h>
1708 +#include <string.h>
1712 +#include "fpm_children.h"
1713 +#include "fpm_signals.h"
1714 +#include "fpm_worker_pool.h"
1715 +#include "fpm_sockets.h"
1716 +#include "fpm_process_ctl.h"
1717 +#include "fpm_php.h"
1718 +#include "fpm_conf.h"
1719 +#include "fpm_cleanup.h"
1720 +#include "fpm_events.h"
1721 +#include "fpm_clock.h"
1722 +#include "fpm_stdio.h"
1723 +#include "fpm_unix.h"
1724 +#include "fpm_env.h"
1725 +#include "fpm_shm_slots.h"
1729 +static time_t *last_faults;
1732 +static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop);
1734 +static void fpm_children_cleanup(int which, void *arg)
1736 + free(last_faults);
1739 +static struct fpm_child_s *fpm_child_alloc()
1741 + struct fpm_child_s *ret;
1743 + ret = malloc(sizeof(struct fpm_child_s));
1745 + if (!ret) return 0;
1747 + memset(ret, 0, sizeof(*ret));
1752 +static void fpm_child_free(struct fpm_child_s *child)
1757 +static void fpm_child_close(struct fpm_child_s *child, int in_event_loop)
1759 + if (child->fd_stdout != -1) {
1760 + if (in_event_loop) {
1761 + fpm_event_fire(&child->ev_stdout);
1763 + if (child->fd_stdout != -1) {
1764 + close(child->fd_stdout);
1768 + if (child->fd_stderr != -1) {
1769 + if (in_event_loop) {
1770 + fpm_event_fire(&child->ev_stderr);
1772 + if (child->fd_stderr != -1) {
1773 + close(child->fd_stderr);
1777 + fpm_child_free(child);
1780 +static void fpm_child_link(struct fpm_child_s *child)
1782 + struct fpm_worker_pool_s *wp = child->wp;
1784 + ++wp->running_children;
1785 + ++fpm_globals.running_children;
1787 + child->next = wp->children;
1788 + if (child->next) child->next->prev = child;
1790 + wp->children = child;
1793 +static void fpm_child_unlink(struct fpm_child_s *child)
1795 + --child->wp->running_children;
1796 + --fpm_globals.running_children;
1798 + if (child->prev) child->prev->next = child->next;
1799 + else child->wp->children = child->next;
1800 + if (child->next) child->next->prev = child->prev;
1804 +static struct fpm_child_s *fpm_child_find(pid_t pid)
1806 + struct fpm_worker_pool_s *wp;
1807 + struct fpm_child_s *child = 0;
1809 + for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
1811 + for (child = wp->children; child; child = child->next) {
1812 + if (child->pid == pid) {
1827 +static void fpm_child_init(struct fpm_worker_pool_s *wp)
1829 + fpm_globals.max_requests = wp->config->max_requests;
1831 + if (0 > fpm_stdio_init_child(wp) ||
1832 + 0 > fpm_unix_init_child(wp) ||
1833 + 0 > fpm_signals_init_child() ||
1834 + 0 > fpm_env_init_child(wp) ||
1835 + 0 > fpm_php_init_child(wp)) {
1837 + zlog(ZLOG_STUFF, ZLOG_ERROR, "child failed to initialize (pool %s)", wp->config->name);
1842 +int fpm_children_free(struct fpm_child_s *child)
1844 + struct fpm_child_s *next;
1846 + for (; child; child = next) {
1847 + next = child->next;
1848 + fpm_child_close(child, 0 /* in_event_loop */);
1854 +void fpm_children_bury()
1858 + struct fpm_child_s *child;
1860 + while ( (pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
1862 + int severity = ZLOG_NOTICE;
1864 + child = fpm_child_find(pid);
1866 + if (WIFEXITED(status)) {
1868 + snprintf(buf, sizeof(buf), "with code %d", WEXITSTATUS(status));
1870 + if (WEXITSTATUS(status) != 0) {
1871 + severity = ZLOG_WARNING;
1875 + else if (WIFSIGNALED(status)) {
1876 + const char *signame = fpm_signal_names[WTERMSIG(status)];
1877 + const char *have_core = WCOREDUMP(status) ? " (core dumped)" : "";
1879 + if (signame == NULL) {
1883 + snprintf(buf, sizeof(buf), "on signal %d %s%s", WTERMSIG(status), signame, have_core);
1885 + if (WTERMSIG(status) != SIGQUIT) { /* possible request loss */
1886 + severity = ZLOG_WARNING;
1889 + else if (WIFSTOPPED(status)) {
1891 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "child %d stopped for tracing", (int) pid);
1893 + if (child && child->tracer) {
1894 + child->tracer(child);
1901 + struct fpm_worker_pool_s *wp = child->wp;
1902 + struct timeval tv1, tv2;
1904 + fpm_child_unlink(child);
1906 + fpm_shm_slots_discard_slot(child);
1908 + fpm_clock_get(&tv1);
1910 + timersub(&tv1, &child->started, &tv2);
1912 + zlog(ZLOG_STUFF, severity, "child %d (pool %s) exited %s after %ld.%06d seconds from start", (int) pid,
1913 + child->wp->config->name, buf, tv2.tv_sec, (int) tv2.tv_usec);
1915 + fpm_child_close(child, 1 /* in event_loop */);
1917 + fpm_pctl_child_exited();
1919 + if (last_faults && (WTERMSIG(status) == SIGSEGV || WTERMSIG(status) == SIGBUS)) {
1920 + time_t now = tv1.tv_sec;
1921 + int restart_condition = 1;
1924 + last_faults[fault++] = now;
1926 + if (fault == fpm_global_options.emergency_restart_threshold) {
1930 + for (i = 0; i < fpm_global_options.emergency_restart_threshold; i++) {
1931 + if (now - last_faults[i] > fpm_global_options.emergency_restart_interval) {
1932 + restart_condition = 0;
1937 + if (restart_condition) {
1939 + zlog(ZLOG_STUFF, ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload",
1940 + fpm_global_options.emergency_restart_threshold, fpm_global_options.emergency_restart_interval);
1942 + fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET);
1946 + fpm_children_make(wp, 1 /* in event loop */);
1948 + if (fpm_globals.is_child) {
1953 + zlog(ZLOG_STUFF, ZLOG_ALERT, "oops, unknown child exited %s", buf);
1959 +static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp)
1961 + struct fpm_child_s *c;
1963 + c = fpm_child_alloc();
1966 + zlog(ZLOG_STUFF, ZLOG_ERROR, "malloc failed (pool %s)", wp->config->name);
1971 + c->fd_stdout = -1; c->fd_stderr = -1;
1973 + if (0 > fpm_stdio_prepare_pipes(c)) {
1974 + fpm_child_free(c);
1978 + if (0 > fpm_shm_slots_prepare_slot(c)) {
1979 + fpm_stdio_discard_pipes(c);
1980 + fpm_child_free(c);
1987 +static void fpm_resources_discard(struct fpm_child_s *child)
1989 + fpm_shm_slots_discard_slot(child);
1990 + fpm_stdio_discard_pipes(child);
1991 + fpm_child_free(child);
1994 +static void fpm_child_resources_use(struct fpm_child_s *child)
1996 + fpm_shm_slots_child_use_slot(child);
1997 + fpm_stdio_child_use_pipes(child);
1998 + fpm_child_free(child);
2001 +static void fpm_parent_resources_use(struct fpm_child_s *child)
2003 + fpm_shm_slots_parent_use_slot(child);
2004 + fpm_stdio_parent_use_pipes(child);
2005 + fpm_child_link(child);
2008 +static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop)
2012 + struct fpm_child_s *child;
2014 + while (!enough && fpm_pctl_can_spawn_children() && wp->running_children < wp->config->pm->max_children) {
2016 + child = fpm_resources_prepare(wp);
2028 + fpm_child_resources_use(child);
2029 + fpm_globals.is_child = 1;
2030 + if (in_event_loop) {
2031 + fpm_event_exit_loop();
2033 + fpm_child_init(wp);
2037 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fork() failed");
2040 + fpm_resources_discard(child);
2042 + break; /* dont try any more on error */
2046 + fpm_clock_get(&child->started);
2047 + fpm_parent_resources_use(child);
2049 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "child %d (pool %s) started", (int) pid, wp->config->name);
2054 + return 1; /* we are done */
2057 +int fpm_children_create_initial(struct fpm_worker_pool_s *wp)
2059 + return fpm_children_make(wp, 0 /* not in event loop yet */);
2062 +int fpm_children_init_main()
2064 + if (fpm_global_options.emergency_restart_threshold &&
2065 + fpm_global_options.emergency_restart_interval) {
2067 + last_faults = malloc(sizeof(time_t) * fpm_global_options.emergency_restart_threshold);
2069 + if (!last_faults) {
2073 + memset(last_faults, 0, sizeof(time_t) * fpm_global_options.emergency_restart_threshold);
2076 + fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_children_cleanup, 0);
2081 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_children.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_children.h
2082 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_children.h 1970-01-01 03:00:00.000000000 +0300
2083 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_children.h 2008-05-24 21:38:47.000000000 +0400
2087 + /* (c) 2007,2008 Andrei Nigmatulin */
2089 +#ifndef FPM_CHILDREN_H
2090 +#define FPM_CHILDREN_H 1
2092 +#include <sys/time.h>
2093 +#include <sys/types.h>
2096 +#include "fpm_worker_pool.h"
2098 +int fpm_children_create_initial(struct fpm_worker_pool_s *wp);
2099 +int fpm_children_free(struct fpm_child_s *child);
2100 +void fpm_children_bury();
2101 +int fpm_children_init_main();
2103 +struct fpm_child_s;
2105 +struct fpm_child_s {
2106 + struct fpm_child_s *prev, *next;
2107 + struct timeval started;
2108 + struct fpm_worker_pool_s *wp;
2109 + struct event ev_stdout, ev_stderr;
2111 + int fd_stdout, fd_stderr;
2112 + void (*tracer)(struct fpm_child_s *);
2113 + struct timeval slow_logged;
2118 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_cleanup.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_cleanup.c
2119 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_cleanup.c 1970-01-01 03:00:00.000000000 +0300
2120 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_cleanup.c 2008-05-24 21:38:47.000000000 +0400
2124 + /* (c) 2007,2008 Andrei Nigmatulin */
2126 +#include "fpm_config.h"
2128 +#include <stdlib.h>
2130 +#include "fpm_arrays.h"
2131 +#include "fpm_cleanup.h"
2136 + void (*cleanup)(int, void *);
2140 +static struct fpm_array_s cleanups = { .sz = sizeof(struct cleanup_s) };
2142 +int fpm_cleanup_add(int type, void (*cleanup)(int, void *), void *arg)
2144 + struct cleanup_s *c;
2146 + c = fpm_array_push(&cleanups);
2153 + c->cleanup = cleanup;
2159 +void fpm_cleanups_run(int type)
2161 + struct cleanup_s *c = fpm_array_item_last(&cleanups);
2162 + int cl = cleanups.used;
2164 + for ( ; cl--; c--) {
2165 + if (c->type & type) {
2166 + c->cleanup(type, c->arg);
2170 + fpm_array_free(&cleanups);
2173 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_cleanup.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_cleanup.h
2174 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_cleanup.h 1970-01-01 03:00:00.000000000 +0300
2175 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_cleanup.h 2008-05-24 21:38:47.000000000 +0400
2179 + /* (c) 2007,2008 Andrei Nigmatulin */
2181 +#ifndef FPM_CLEANUP_H
2182 +#define FPM_CLEANUP_H 1
2184 +int fpm_cleanup_add(int type, void (*cleanup)(int, void *), void *);
2185 +void fpm_cleanups_run(int type);
2188 + FPM_CLEANUP_CHILD = (1 << 0),
2189 + FPM_CLEANUP_PARENT_EXIT = (1 << 1),
2190 + FPM_CLEANUP_PARENT_EXIT_MAIN = (1 << 2),
2191 + FPM_CLEANUP_PARENT_EXEC = (1 << 3),
2192 + FPM_CLEANUP_PARENT = (1 << 1) | (1 << 2) | (1 << 3),
2193 + FPM_CLEANUP_ALL = ~0,
2198 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_clock.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_clock.c
2199 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_clock.c 1970-01-01 03:00:00.000000000 +0300
2200 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_clock.c 2008-09-19 03:19:59.000000000 +0400
2204 + /* (c) 2007,2008 Andrei Nigmatulin */
2206 +#include "fpm_config.h"
2208 +#if defined(HAVE_CLOCK_GETTIME)
2209 +#include <time.h> /* for CLOCK_MONOTONIC */
2212 +#include "fpm_clock.h"
2216 +/* posix monotonic clock - preferred source of time */
2217 +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
2219 +static int monotonic_works;
2221 +int fpm_clock_init()
2223 + struct timespec ts;
2225 + monotonic_works = 0;
2227 + if (0 == clock_gettime(CLOCK_MONOTONIC, &ts)) {
2228 + monotonic_works = 1;
2234 +int fpm_clock_get(struct timeval *tv)
2236 + if (monotonic_works) {
2237 + struct timespec ts;
2239 + if (0 > clock_gettime(CLOCK_MONOTONIC, &ts)) {
2240 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "clock_gettime() failed");
2244 + tv->tv_sec = ts.tv_sec;
2245 + tv->tv_usec = ts.tv_nsec / 1000;
2249 + return gettimeofday(tv, 0);
2253 +#elif defined(HAVE_CLOCK_GET_TIME)
2255 +#include <mach/mach.h>
2256 +#include <mach/clock.h>
2257 +#include <mach/mach_error.h>
2259 +static clock_serv_t mach_clock;
2261 +/* this code borrowed from here: http://lists.apple.com/archives/Darwin-development/2002/Mar/msg00746.html */
2262 +/* mach_clock also should be re-initialized in child process after fork */
2263 +int fpm_clock_init()
2265 + kern_return_t ret;
2266 + mach_timespec_t aTime;
2268 + ret = host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &mach_clock);
2270 + if (ret != KERN_SUCCESS) {
2271 + zlog(ZLOG_STUFF, ZLOG_ERROR, "host_get_clock_service() failed: %s", mach_error_string(ret));
2275 + /* test if it works */
2276 + ret = clock_get_time(mach_clock, &aTime);
2278 + if (ret != KERN_SUCCESS) {
2279 + zlog(ZLOG_STUFF, ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret));
2286 +int fpm_clock_get(struct timeval *tv)
2288 + kern_return_t ret;
2289 + mach_timespec_t aTime;
2291 + ret = clock_get_time(mach_clock, &aTime);
2293 + if (ret != KERN_SUCCESS) {
2294 + zlog(ZLOG_STUFF, ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret));
2298 + tv->tv_sec = aTime.tv_sec;
2299 + tv->tv_usec = aTime.tv_nsec / 1000;
2304 +#else /* no clock */
2306 +int fpm_clock_init()
2311 +int fpm_clock_get(struct timeval *tv)
2313 + return gettimeofday(tv, 0);
2317 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_clock.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_clock.h
2318 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_clock.h 1970-01-01 03:00:00.000000000 +0300
2319 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_clock.h 2008-05-24 21:38:47.000000000 +0400
2323 + /* (c) 2007,2008 Andrei Nigmatulin */
2325 +#ifndef FPM_CLOCK_H
2326 +#define FPM_CLOCK_H 1
2328 +#include <sys/time.h>
2330 +int fpm_clock_init();
2331 +int fpm_clock_get(struct timeval *tv);
2334 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_conf.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_conf.c
2335 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_conf.c 1970-01-01 03:00:00.000000000 +0300
2336 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_conf.c 2008-09-19 04:54:15.000000000 +0400
2340 + /* (c) 2007,2008 Andrei Nigmatulin */
2342 +#include "fpm_config.h"
2344 +#include <sys/types.h>
2345 +#include <sys/stat.h>
2347 +#include <string.h>
2348 +#include <stdlib.h>
2349 +#include <stddef.h>
2350 +#include <stdint.h>
2352 +#include <unistd.h>
2355 +#include "fpm_conf.h"
2356 +#include "fpm_stdio.h"
2357 +#include "fpm_worker_pool.h"
2358 +#include "fpm_cleanup.h"
2359 +#include "fpm_php.h"
2360 +#include "fpm_sockets.h"
2361 +#include "xml_config.h"
2365 +struct fpm_options_s fpm_global_options;
2367 +static void *fpm_global_options_ptr()
2369 + return &fpm_global_options;
2372 +static char *fpm_conf_set_log_level(void **conf, char *name, void *vv, intptr_t offset)
2376 + if (!strcmp(value, "debug")) {
2377 + fpm_globals.log_level = ZLOG_DEBUG;
2379 + else if (!strcmp(value, "notice")) {
2380 + fpm_globals.log_level = ZLOG_NOTICE;
2382 + else if (!strcmp(value, "warn")) {
2383 + fpm_globals.log_level = ZLOG_WARNING;
2385 + else if (!strcmp(value, "error")) {
2386 + fpm_globals.log_level = ZLOG_ERROR;
2388 + else if (!strcmp(value, "alert")) {
2389 + fpm_globals.log_level = ZLOG_ALERT;
2392 + return "invalid value for 'log_level'";
2398 +static struct xml_conf_section xml_section_fpm_global_options = {
2399 + .conf = &fpm_global_options_ptr,
2400 + .path = "/configuration/global_options",
2401 + .parsers = (struct xml_value_parser []) {
2402 + { XML_CONF_SCALAR, "emergency_restart_threshold", &xml_conf_set_slot_integer, offsetof(struct fpm_options_s, emergency_restart_threshold) },
2403 + { XML_CONF_SCALAR, "emergency_restart_interval", &xml_conf_set_slot_time, offsetof(struct fpm_options_s, emergency_restart_interval) },
2404 + { XML_CONF_SCALAR, "process_control_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_options_s, process_control_timeout) },
2405 + { XML_CONF_SCALAR, "daemonize", &xml_conf_set_slot_boolean, offsetof(struct fpm_options_s, daemonize) },
2406 + { XML_CONF_SCALAR, "pid_file", &xml_conf_set_slot_string, offsetof(struct fpm_options_s, pid_file) },
2407 + { XML_CONF_SCALAR, "error_log", &xml_conf_set_slot_string, offsetof(struct fpm_options_s, error_log) },
2408 + { XML_CONF_SCALAR, "log_level", &fpm_conf_set_log_level, 0 },
2413 +static char *fpm_conf_set_pm_style(void **conf, char *name, void *vv, intptr_t offset)
2416 + struct fpm_pm_s *c = *conf;
2418 + if (!strcmp(value, "static")) {
2419 + c->style = PM_STYLE_STATIC;
2421 + else if (!strcmp(value, "apache-like")) {
2422 + c->style = PM_STYLE_APACHE_LIKE;
2425 + return "invalid value for 'style'";
2431 +static char *fpm_conf_set_rlimit_core(void **conf, char *name, void *vv, intptr_t offset)
2434 + struct fpm_worker_pool_config_s *c = *conf;
2436 + if (!strcmp(value, "unlimited")) {
2437 + c->rlimit_core = -1;
2441 + void *subconf = &int_value;
2444 + error = xml_conf_set_slot_integer(&subconf, name, vv, 0);
2446 + if (error) return error;
2448 + if (int_value < 0) return "invalid value for 'rlimit_core'";
2450 + c->rlimit_core = int_value;
2456 +static char *fpm_conf_set_catch_workers_output(void **conf, char *name, void *vv, intptr_t offset)
2458 + struct fpm_worker_pool_config_s *c = *conf;
2460 + void *subconf = &int_value;
2463 + error = xml_conf_set_slot_boolean(&subconf, name, vv, 0);
2465 + if (error) return error;
2467 + c->catch_workers_output = int_value;
2472 +static struct xml_conf_section fpm_conf_set_apache_like_subsection_conf = {
2473 + .path = "apache_like somewhere", /* fixme */
2474 + .parsers = (struct xml_value_parser []) {
2475 + { XML_CONF_SCALAR, "StartServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.StartServers) },
2476 + { XML_CONF_SCALAR, "MinSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MinSpareServers) },
2477 + { XML_CONF_SCALAR, "MaxSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MaxSpareServers) },
2482 +static char *fpm_conf_set_apache_like_subsection(void **conf, char *name, void *xml_node, intptr_t offset)
2484 + return xml_conf_parse_section(conf, &fpm_conf_set_apache_like_subsection_conf, xml_node);
2487 +static struct xml_conf_section fpm_conf_set_listen_options_subsection_conf = {
2488 + .path = "listen options somewhere", /* fixme */
2489 + .parsers = (struct xml_value_parser []) {
2490 + { XML_CONF_SCALAR, "backlog", &xml_conf_set_slot_integer, offsetof(struct fpm_listen_options_s, backlog) },
2491 + { XML_CONF_SCALAR, "owner", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, owner) },
2492 + { XML_CONF_SCALAR, "group", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, group) },
2493 + { XML_CONF_SCALAR, "mode", &xml_conf_set_slot_string, offsetof(struct fpm_listen_options_s, mode) },
2498 +static char *fpm_conf_set_listen_options_subsection(void **conf, char *name, void *xml_node, intptr_t offset)
2500 + void *subconf = (char *) *conf + offset;
2501 + struct fpm_listen_options_s *lo;
2503 + lo = malloc(sizeof(*lo));
2506 + return "malloc() failed";
2509 + memset(lo, 0, sizeof(*lo));
2513 + * (struct fpm_listen_options_s **) subconf = lo;
2517 + return xml_conf_parse_section(&subconf, &fpm_conf_set_listen_options_subsection_conf, xml_node);
2520 +static struct xml_conf_section fpm_conf_set_pm_subsection_conf = {
2521 + .path = "pm settings somewhere", /* fixme */
2522 + .parsers = (struct xml_value_parser []) {
2523 + { XML_CONF_SCALAR, "style", &fpm_conf_set_pm_style, 0 },
2524 + { XML_CONF_SCALAR, "max_children", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, max_children) },
2525 + { XML_CONF_SUBSECTION, "apache_like", &fpm_conf_set_apache_like_subsection, offsetof(struct fpm_pm_s, options_apache_like) },
2530 +static char *fpm_conf_set_pm_subsection(void **conf, char *name, void *xml_node, intptr_t offset)
2532 + void *subconf = (char *) *conf + offset;
2533 + struct fpm_pm_s *pm;
2535 + pm = malloc(sizeof(*pm));
2538 + return "fpm_conf_set_pm_subsection(): malloc failed";
2541 + memset(pm, 0, sizeof(*pm));
2543 + * (struct fpm_pm_s **) subconf = pm;
2547 + return xml_conf_parse_section(&subconf, &fpm_conf_set_pm_subsection_conf, xml_node);
2550 +static char *xml_conf_set_slot_key_value_pair(void **conf, char *name, void *vv, intptr_t offset)
2553 + struct key_value_s *kv;
2554 + struct key_value_s ***parent = (struct key_value_s ***) conf;
2556 + kv = malloc(sizeof(*kv));
2559 + return "malloc() failed";
2562 + memset(kv, 0, sizeof(*kv));
2564 + kv->key = strdup(name);
2565 + kv->value = strdup(value);
2567 + if (!kv->key || !kv->value) {
2568 + return "xml_conf_set_slot_key_value_pair(): strdup() failed";
2573 + *parent = &kv->next;
2578 +static struct xml_conf_section fpm_conf_set_key_value_pairs_subsection_conf = {
2579 + .path = "key_value_pairs somewhere", /* fixme */
2580 + .parsers = (struct xml_value_parser []) {
2581 + { XML_CONF_SCALAR, 0, &xml_conf_set_slot_key_value_pair, 0 },
2586 +static char *fpm_conf_set_key_value_pairs_subsection(void **conf, char *name, void *xml_node, intptr_t offset)
2588 + void *next_kv = (char *) *conf + offset;
2590 + return xml_conf_parse_section(&next_kv, &fpm_conf_set_key_value_pairs_subsection_conf, xml_node);
2593 +static void *fpm_worker_pool_config_alloc()
2595 + static struct fpm_worker_pool_s *current_wp = 0;
2596 + struct fpm_worker_pool_s *wp;
2598 + wp = fpm_worker_pool_alloc();
2600 + if (!wp) return 0;
2602 + wp->config = malloc(sizeof(struct fpm_worker_pool_config_s));
2604 + if (!wp->config) return 0;
2606 + memset(wp->config, 0, sizeof(struct fpm_worker_pool_config_s));
2608 + if (current_wp) current_wp->next = wp;
2612 + return wp->config;
2615 +int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc)
2617 + struct key_value_s *kv, *kv_next;
2620 + free(wpc->listen_address);
2621 + if (wpc->listen_options) {
2622 + free(wpc->listen_options->owner);
2623 + free(wpc->listen_options->group);
2624 + free(wpc->listen_options->mode);
2625 + free(wpc->listen_options);
2627 + for (kv = wpc->php_defines; kv; kv = kv_next) {
2628 + kv_next = kv->next;
2633 + for (kv = wpc->environment; kv; kv = kv_next) {
2634 + kv_next = kv->next;
2642 + free(wpc->chroot);
2644 + free(wpc->allowed_clients);
2645 + free(wpc->slowlog);
2650 +static struct xml_conf_section xml_section_fpm_worker_pool_config = {
2651 + .conf = &fpm_worker_pool_config_alloc,
2652 + .path = "/configuration/workers/pool",
2653 + .parsers = (struct xml_value_parser []) {
2654 + { XML_CONF_SCALAR, "name", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, name) },
2655 + { XML_CONF_SCALAR, "listen_address", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, listen_address) },
2656 + { XML_CONF_SUBSECTION, "listen_options", &fpm_conf_set_listen_options_subsection, offsetof(struct fpm_worker_pool_config_s, listen_options) },
2657 + { XML_CONF_SUBSECTION, "php_defines", &fpm_conf_set_key_value_pairs_subsection, offsetof(struct fpm_worker_pool_config_s, php_defines) },
2658 + { XML_CONF_SCALAR, "user", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, user) },
2659 + { XML_CONF_SCALAR, "group", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, group) },
2660 + { XML_CONF_SCALAR, "chroot", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, chroot) },
2661 + { XML_CONF_SCALAR, "chdir", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, chdir) },
2662 + { XML_CONF_SCALAR, "allowed_clients", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, allowed_clients) },
2663 + { XML_CONF_SUBSECTION, "environment", &fpm_conf_set_key_value_pairs_subsection, offsetof(struct fpm_worker_pool_config_s, environment) },
2664 + { XML_CONF_SCALAR, "request_terminate_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_worker_pool_config_s, request_terminate_timeout) },
2665 + { XML_CONF_SCALAR, "request_slowlog_timeout", &xml_conf_set_slot_time, offsetof(struct fpm_worker_pool_config_s, request_slowlog_timeout) },
2666 + { XML_CONF_SCALAR, "slowlog", &xml_conf_set_slot_string, offsetof(struct fpm_worker_pool_config_s, slowlog) },
2667 + { XML_CONF_SCALAR, "rlimit_files", &xml_conf_set_slot_integer, offsetof(struct fpm_worker_pool_config_s, rlimit_files) },
2668 + { XML_CONF_SCALAR, "rlimit_core", &fpm_conf_set_rlimit_core, 0 },
2669 + { XML_CONF_SCALAR, "max_requests", &xml_conf_set_slot_integer, offsetof(struct fpm_worker_pool_config_s, max_requests) },
2670 + { XML_CONF_SCALAR, "catch_workers_output", &fpm_conf_set_catch_workers_output, 0 },
2671 + { XML_CONF_SUBSECTION, "pm", &fpm_conf_set_pm_subsection, offsetof(struct fpm_worker_pool_config_s, pm) },
2676 +static struct xml_conf_section *fpm_conf_all_sections[] = {
2677 + &xml_section_fpm_global_options,
2678 + &xml_section_fpm_worker_pool_config,
2682 +static int fpm_evaluate_full_path(char **path)
2684 + if (**path != '/') {
2687 + full_path = malloc(sizeof(PHP_PREFIX) + strlen(*path) + 1);
2689 + if (!full_path) return -1;
2691 + sprintf(full_path, "%s/%s", PHP_PREFIX, *path);
2695 + *path = full_path;
2701 +static int fpm_conf_process_all_pools()
2703 + struct fpm_worker_pool_s *wp;
2705 + if (!fpm_worker_all_pools) {
2706 + zlog(ZLOG_STUFF, ZLOG_ERROR, "at least one pool section must be specified in config file");
2710 + for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
2712 + if (wp->config->listen_address && *wp->config->listen_address) {
2714 + wp->listen_address_domain = fpm_sockets_domain_from_address(wp->config->listen_address);
2716 + if (wp->listen_address_domain == FPM_AF_UNIX && *wp->config->listen_address != '/') {
2717 + fpm_evaluate_full_path(&wp->config->listen_address);
2723 + wp->is_template = 1;
2727 + if (wp->config->request_slowlog_timeout) {
2729 + if (! (wp->config->slowlog && *wp->config->slowlog)) {
2730 + zlog(ZLOG_STUFF, ZLOG_ERROR, "pool %s: 'slowlog' must be specified for use with 'request_slowlog_timeout'",
2731 + wp->config->name);
2735 + static int warned = 0;
2738 + zlog(ZLOG_STUFF, ZLOG_WARNING, "pool %s: 'request_slowlog_timeout' is not supported on your system",
2739 + wp->config->name);
2743 + wp->config->request_slowlog_timeout = 0;
2747 + if (wp->config->request_slowlog_timeout && wp->config->slowlog && *wp->config->slowlog) {
2750 + fpm_evaluate_full_path(&wp->config->slowlog);
2752 + if (wp->config->request_slowlog_timeout) {
2753 + fd = open(wp->config->slowlog, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
2756 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(%s) failed", wp->config->slowlog);
2767 +int fpm_conf_unlink_pid()
2769 + if (fpm_global_options.pid_file) {
2771 + if (0 > unlink(fpm_global_options.pid_file)) {
2772 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "unlink(\"%s\") failed", fpm_global_options.pid_file);
2781 +int fpm_conf_write_pid()
2785 + if (fpm_global_options.pid_file) {
2789 + unlink(fpm_global_options.pid_file);
2791 + fd = creat(fpm_global_options.pid_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
2794 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "creat(\"%s\") failed", fpm_global_options.pid_file);
2798 + len = sprintf(buf, "%d", (int) fpm_globals.parent_pid);
2800 + if (len != write(fd, buf, len)) {
2801 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "write() failed");
2811 +static int fpm_conf_post_process()
2813 + if (fpm_global_options.pid_file) {
2814 + fpm_evaluate_full_path(&fpm_global_options.pid_file);
2817 + if (!fpm_global_options.error_log) {
2818 + fpm_global_options.error_log = strdup(PHP_FPM_LOG_PATH);
2821 + fpm_evaluate_full_path(&fpm_global_options.error_log);
2823 + if (0 > fpm_stdio_open_error_log(0)) {
2827 + return fpm_conf_process_all_pools();
2830 +static void fpm_conf_cleanup(int which, void *arg)
2832 + free(fpm_global_options.pid_file);
2833 + free(fpm_global_options.error_log);
2834 + fpm_global_options.pid_file = 0;
2835 + fpm_global_options.error_log = 0;
2838 +int fpm_conf_init_main()
2840 + char *filename = fpm_globals.config;
2843 + if (0 > xml_conf_sections_register(fpm_conf_all_sections)) {
2847 + if (filename == NULL) {
2848 + filename = PHP_FPM_CONF_PATH;
2851 + err = xml_conf_load_file(filename);
2854 + zlog(ZLOG_STUFF, ZLOG_ERROR, "failed to load configuration file: %s", err);
2858 + if (0 > fpm_conf_post_process()) {
2864 + fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_conf_cleanup, 0);
2868 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_conf.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_conf.h
2869 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_conf.h 1970-01-01 03:00:00.000000000 +0300
2870 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_conf.h 2008-08-26 19:09:15.000000000 +0400
2874 + /* (c) 2007,2008 Andrei Nigmatulin */
2877 +#define FPM_CONF_H 1
2879 +struct key_value_s;
2881 +struct key_value_s {
2882 + struct key_value_s *next;
2887 +struct fpm_options_s {
2888 + int emergency_restart_threshold;
2889 + int emergency_restart_interval;
2890 + int process_control_timeout;
2896 +extern struct fpm_options_s fpm_global_options;
2903 + int MinSpareServers;
2904 + int MaxSpareServers;
2905 + } options_apache_like;
2908 +struct fpm_listen_options_s {
2915 +struct fpm_worker_pool_config_s {
2917 + char *listen_address;
2918 + struct fpm_listen_options_s *listen_options;
2919 + struct key_value_s *php_defines;
2924 + char *allowed_clients;
2925 + struct key_value_s *environment;
2926 + struct fpm_pm_s *pm;
2927 + int request_terminate_timeout;
2928 + int request_slowlog_timeout;
2933 + unsigned catch_workers_output:1;
2936 +enum { PM_STYLE_STATIC = 1, PM_STYLE_APACHE_LIKE = 2 };
2938 +int fpm_conf_init_main();
2939 +int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc);
2940 +int fpm_conf_write_pid();
2941 +int fpm_conf_unlink_pid();
2945 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_config.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_config.h
2946 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_config.h 1970-01-01 03:00:00.000000000 +0300
2947 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_config.h 2008-05-25 04:30:43.000000000 +0400
2951 + /* (c) 2007,2008 Andrei Nigmatulin */
2953 +#include "php_config.h"
2954 +#include "fpm_autoconf.h"
2957 +/* Solaris does not have it */
2958 +#ifndef INADDR_NONE
2959 +#define INADDR_NONE (-1)
2963 +/* If we're not using GNU C, elide __attribute__ */
2965 +# define __attribute__(x) /*NOTHING*/
2969 +/* Solaris does not have it */
2971 +#define timersub(tvp, uvp, vvp) \
2973 + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
2974 + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
2975 + if ((vvp)->tv_usec < 0) { \
2976 + (vvp)->tv_sec--; \
2977 + (vvp)->tv_usec += 1000000; \
2982 +#if defined(HAVE_PTRACE) || defined(PROC_MEM_FILE) || defined(HAVE_MACH_VM_READ)
2983 +#define HAVE_FPM_TRACE 1
2985 +#define HAVE_FPM_TRACE 0
2988 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_env.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_env.c
2989 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_env.c 1970-01-01 03:00:00.000000000 +0300
2990 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_env.c 2008-09-19 03:19:59.000000000 +0400
2994 + /* (c) 2007,2008 Andrei Nigmatulin */
2996 +#include "fpm_config.h"
2998 +#ifdef HAVE_ALLOCA_H
2999 +#include <alloca.h>
3002 +#include <stdlib.h>
3003 +#include <string.h>
3005 +#include "fpm_env.h"
3008 +#ifndef HAVE_SETENV
3009 +int setenv(char *name, char *value, int overwrite)
3011 + int name_len = strlen(name);
3012 + int value_len = strlen(value);
3013 + char *var = alloca(name_len + 1 + value_len + 1);
3015 + memcpy(var, name, name_len);
3017 + var[name_len] = '=';
3019 + memcpy(var + name_len + 1, value, value_len);
3021 + var[name_len + 1 + value_len] = '\0';
3023 + return putenv(var);
3027 +#ifndef HAVE_CLEARENV
3033 + /* this algo is the only one known to me
3034 + that works well on all systems */
3035 + while (*(envp = environ)) {
3036 + char *eq = strchr(*envp, '=');
3038 + s = strdup(*envp);
3040 + if (eq) s[eq - *envp] = '\0';
3050 +int fpm_env_init_child(struct fpm_worker_pool_s *wp)
3052 + struct key_value_s *kv;
3056 + for (kv = wp->config->environment; kv; kv = kv->next) {
3057 + setenv(kv->key, kv->value, 1);
3061 + setenv("USER", wp->user, 1);
3065 + setenv("HOME", wp->home, 1);
3071 +static int fpm_env_conf_wp(struct fpm_worker_pool_s *wp)
3073 + struct key_value_s *kv;
3075 + kv = wp->config->environment;
3077 + for (kv = wp->config->environment; kv; kv = kv->next) {
3078 + if (*kv->value == '$') {
3079 + char *value = getenv(kv->value + 1);
3081 + if (!value) value = "";
3084 + kv->value = strdup(value);
3087 + /* autodetected values should be removed
3088 + if these vars specified in config */
3089 + if (!strcmp(kv->key, "USER")) {
3094 + if (!strcmp(kv->key, "HOME")) {
3103 +int fpm_env_init_main()
3105 + struct fpm_worker_pool_s *wp;
3107 + for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
3109 + if (0 > fpm_env_conf_wp(wp)) {
3117 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_env.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_env.h
3118 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_env.h 1970-01-01 03:00:00.000000000 +0300
3119 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_env.h 2008-09-19 03:19:59.000000000 +0400
3123 + /* (c) 2007,2008 Andrei Nigmatulin */
3126 +#define FPM_ENV_H 1
3128 +#include "fpm_worker_pool.h"
3130 +int fpm_env_init_child(struct fpm_worker_pool_s *wp);
3131 +int fpm_env_init_main();
3133 +extern char **environ;
3135 +#ifndef HAVE_SETENV
3136 +int setenv(char *name, char *value, int overwrite);
3139 +#ifndef HAVE_CLEARENV
3145 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_events.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_events.c
3146 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_events.c 1970-01-01 03:00:00.000000000 +0300
3147 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_events.c 2008-08-26 19:09:15.000000000 +0400
3151 + /* (c) 2007,2008 Andrei Nigmatulin */
3153 +#include "fpm_config.h"
3155 +#include <unistd.h>
3157 +#include <stdlib.h> /* for putenv */
3158 +#include <string.h>
3159 +#include <sys/types.h> /* for event.h below */
3163 +#include "fpm_process_ctl.h"
3164 +#include "fpm_events.h"
3165 +#include "fpm_cleanup.h"
3166 +#include "fpm_stdio.h"
3167 +#include "fpm_signals.h"
3168 +#include "fpm_children.h"
3171 +static void fpm_event_cleanup(int which, void *arg)
3173 + event_base_free(0);
3176 +static void fpm_got_signal(int fd, short ev, void *arg)
3184 + res = read(fd, &c, 1);
3185 + } while (res == -1 && errno == EINTR);
3188 + if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
3189 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed");
3195 + case 'C' : /* SIGCHLD */
3196 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGCHLD");
3197 + fpm_children_bury();
3199 + case 'I' : /* SIGINT */
3200 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGINT");
3201 + fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET);
3203 + case 'T' : /* SIGTERM */
3204 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGTERM");
3205 + fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET);
3207 + case 'Q' : /* SIGQUIT */
3208 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGQUIT");
3209 + fpm_pctl(FPM_PCTL_STATE_FINISHING, FPM_PCTL_ACTION_SET);
3211 + case '1' : /* SIGUSR1 */
3212 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGUSR1");
3213 + if (0 == fpm_stdio_open_error_log(1)) {
3214 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "log file re-opened");
3217 + case '2' : /* SIGUSR2 */
3218 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "received SIGUSR2");
3219 + fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET);
3223 + if (fpm_globals.is_child) {
3232 +int fpm_event_init_main()
3236 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "libevent: using %s", event_get_method());
3238 + fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_event_cleanup, 0);
3243 +int fpm_event_loop()
3245 + static struct event signal_fd_event;
3247 + event_set(&signal_fd_event, fpm_signals_get_fd(), EV_PERSIST | EV_READ, &fpm_got_signal, 0);
3249 + event_add(&signal_fd_event, 0);
3251 + fpm_pctl_heartbeat(-1, 0, 0);
3253 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "libevent: entering main loop");
3260 +int fpm_event_add(int fd, struct event *ev, void (*callback)(int, short, void *), void *arg)
3262 + event_set(ev, fd, EV_PERSIST | EV_READ, callback, arg);
3264 + return event_add(ev, 0);
3267 +int fpm_event_del(struct event *ev)
3269 + return event_del(ev);
3272 +void fpm_event_exit_loop()
3274 + event_loopexit(0);
3277 +void fpm_event_fire(struct event *ev)
3279 + (*ev->ev_callback)( (int) ev->ev_fd, (short) ev->ev_res, ev->ev_arg);
3282 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_events.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_events.h
3283 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_events.h 1970-01-01 03:00:00.000000000 +0300
3284 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_events.h 2008-05-24 21:38:47.000000000 +0400
3288 + /* (c) 2007,2008 Andrei Nigmatulin */
3290 +#ifndef FPM_EVENTS_H
3291 +#define FPM_EVENTS_H 1
3293 +void fpm_event_exit_loop();
3294 +int fpm_event_loop();
3295 +int fpm_event_add(int fd, struct event *ev, void (*callback)(int, short, void *), void *arg);
3296 +int fpm_event_del(struct event *ev);
3297 +void fpm_event_fire(struct event *ev);
3298 +int fpm_event_init_main();
3302 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm.h php-5.2.6.fpm/sapi/cgi/fpm/fpm.h
3303 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm.h 1970-01-01 03:00:00.000000000 +0300
3304 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm.h 2008-05-24 21:38:47.000000000 +0400
3308 + /* (c) 2007,2008 Andrei Nigmatulin */
3313 +#include <unistd.h>
3315 +int fpm_run(int *max_requests);
3316 +int fpm_init(int argc, char **argv, char *config);
3318 +struct fpm_globals_s {
3323 + int running_children;
3326 + int listening_socket; /* for this child */
3327 + int max_requests; /* for this child */
3331 +extern struct fpm_globals_s fpm_globals;
3336 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_php.c
3337 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php.c 1970-01-01 03:00:00.000000000 +0300
3338 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_php.c 2008-07-20 20:16:28.000000000 +0400
3342 + /* (c) 2007,2008 Andrei Nigmatulin */
3344 +#include "fpm_config.h"
3346 +#include <stdlib.h>
3347 +#include <string.h>
3350 +#include "php_main.h"
3351 +#include "php_ini.h"
3352 +#include "ext/standard/dl.h"
3354 +#include "fastcgi.h"
3357 +#include "fpm_php.h"
3358 +#include "fpm_cleanup.h"
3359 +#include "fpm_worker_pool.h"
3361 +static int zend_ini_alter_master(char *name, int name_length, char *new_value, int new_value_length, int stage)
3363 + zend_ini_entry *ini_entry;
3366 + if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == FAILURE) {
3370 + duplicate = strdup(new_value);
3372 + if (!ini_entry->on_modify
3373 + || ini_entry->on_modify(ini_entry, duplicate, new_value_length,
3374 + ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage) == SUCCESS) {
3375 + ini_entry->value = duplicate;
3376 + ini_entry->value_length = new_value_length;
3384 +static void fpm_php_disable(char *value, int (*zend_disable)(char *, uint))
3386 + char *s = 0, *e = value;
3394 + zend_disable(s, e - s);
3408 + zend_disable(s, e - s);
3412 +static int fpm_php_apply_defines(struct fpm_worker_pool_s *wp)
3414 + struct key_value_s *kv;
3416 + for (kv = wp->config->php_defines; kv; kv = kv->next) {
3417 + char *name = kv->key;
3418 + char *value = kv->value;
3419 + int name_len = strlen(name);
3420 + int value_len = strlen(value);
3422 + if (!strcmp(name, "extension") && *value) {
3425 +#if defined(PHP_VERSION_ID) && (PHP_VERSION_ID >= 50300)
3426 + php_dl(value, MODULE_PERSISTENT, &zv, 1);
3429 + ZVAL_STRINGL(&filename, value, value_len, 0);
3430 +#if (PHP_MAJOR_VERSION >= 5)
3431 + php_dl(&filename, MODULE_PERSISTENT, &zv, 1);
3433 + php_dl(&filename, MODULE_PERSISTENT, &zv);
3439 + zend_ini_alter_master(name, name_len + 1, value, value_len, PHP_INI_STAGE_ACTIVATE);
3441 + if (!strcmp(name, "disable_functions") && *value) {
3442 + char *v = strdup(value);
3443 +#if (PHP_MAJOR_VERSION >= 5)
3444 + PG(disable_functions) = v;
3446 + fpm_php_disable(v, zend_disable_function);
3448 + else if (!strcmp(name, "disable_classes") && *value) {
3449 + char *v = strdup(value);
3450 +#if (PHP_MAJOR_VERSION >= 5)
3451 + PG(disable_classes) = v;
3453 + fpm_php_disable(v, zend_disable_class);
3460 +static int fpm_php_set_allowed_clients(struct fpm_worker_pool_s *wp)
3462 + if (wp->listen_address_domain == FPM_AF_INET) {
3463 + fcgi_set_allowed_clients(wp->config->allowed_clients);
3469 +char *fpm_php_script_filename()
3471 + return SG(request_info).path_translated;
3474 +char *fpm_php_request_method()
3476 + return (char *) SG(request_info).request_method;
3479 +size_t fpm_php_content_length()
3481 + return SG(request_info).content_length;
3484 +static void fpm_php_cleanup(int which, void *arg)
3486 + php_module_shutdown();
3490 +void fpm_php_soft_quit()
3492 + fcgi_set_in_shutdown(1);
3495 +int fpm_php_init_main()
3497 + fpm_cleanup_add(FPM_CLEANUP_PARENT, fpm_php_cleanup, 0);
3502 +int fpm_php_init_child(struct fpm_worker_pool_s *wp)
3504 + if (0 > fpm_php_apply_defines(wp) ||
3505 + 0 > fpm_php_set_allowed_clients(wp)) {
3511 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_php.h
3512 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php.h 1970-01-01 03:00:00.000000000 +0300
3513 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_php.h 2008-05-24 21:38:47.000000000 +0400
3517 + /* (c) 2007,2008 Andrei Nigmatulin */
3520 +#define FPM_PHP_H 1
3522 +#include "fpm_worker_pool.h"
3524 +#include "build-defs.h" /* for PHP_ defines */
3526 +int fpm_php_init_child(struct fpm_worker_pool_s *wp);
3527 +char *fpm_php_script_filename();
3528 +char *fpm_php_request_method();
3529 +size_t fpm_php_content_length();
3530 +void fpm_php_soft_quit();
3531 +int fpm_php_init_main();
3535 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php_trace.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_php_trace.c
3536 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php_trace.c 1970-01-01 03:00:00.000000000 +0300
3537 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_php_trace.c 2008-08-26 19:09:15.000000000 +0400
3541 + /* (c) 2007,2008 Andrei Nigmatulin */
3543 +#include "fpm_config.h"
3548 +#include "php_main.h"
3551 +#include <stddef.h>
3552 +#include <stdint.h>
3553 +#include <unistd.h>
3554 +#include <sys/time.h>
3555 +#include <sys/types.h>
3558 +#include "fpm_trace.h"
3559 +#include "fpm_php_trace.h"
3560 +#include "fpm_children.h"
3561 +#include "fpm_worker_pool.h"
3562 +#include "fpm_process_ctl.h"
3567 +#define valid_ptr(p) ((p) && 0 == ((p) & (sizeof(long) - 1)))
3569 +#if SIZEOF_LONG == 4
3570 +#define PTR_FMT "08"
3571 +#elif SIZEOF_LONG == 8
3572 +#define PTR_FMT "016"
3576 +static int fpm_php_trace_dump(struct fpm_child_s *child, FILE *slowlog)
3578 + int callers_limit = 20;
3579 + pid_t pid = child->pid;
3580 + struct timeval tv;
3581 + static const int buf_size = 1024;
3582 + char buf[buf_size];
3583 + long execute_data;
3586 + gettimeofday(&tv, 0);
3588 + zlog_print_time(&tv, buf, buf_size);
3590 + fprintf(slowlog, "\n%s pid %d (pool %s)\n", buf, (int) pid, child->wp->config->name);
3592 + if (0 > fpm_trace_get_strz(buf, buf_size, (long) &SG(request_info).path_translated)) {
3596 + fprintf(slowlog, "script_filename = %s\n", buf);
3598 + if (0 > fpm_trace_get_long((long) &EG(current_execute_data), &l)) {
3604 + while (execute_data) {
3608 + fprintf(slowlog, "[0x%" PTR_FMT "lx] ", execute_data);
3610 + if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, function_state.function), &l)) {
3616 + if (valid_ptr(function)) {
3617 + if (0 > fpm_trace_get_strz(buf, buf_size, function + offsetof(zend_function, common.function_name))) {
3621 + fprintf(slowlog, "%s()", buf);
3624 + fprintf(slowlog, "???");
3627 + if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, op_array), &l)) {
3633 + if (valid_ptr(l)) {
3634 + long op_array = l;
3636 + if (0 > fpm_trace_get_strz(buf, buf_size, op_array + offsetof(zend_op_array, filename))) {
3641 + if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, opline), &l)) {
3645 + if (valid_ptr(l)) {
3647 + uint *lu = (uint *) &l;
3649 + if (0 > fpm_trace_get_long(opline + offsetof(struct _zend_op, lineno), &l)) {
3656 + fprintf(slowlog, " %s:%u\n", *buf ? buf : "unknown", lineno);
3658 + if (0 > fpm_trace_get_long(execute_data + offsetof(zend_execute_data, prev_execute_data), &l)) {
3664 + if (0 == --callers_limit) {
3672 +void fpm_php_trace(struct fpm_child_s *child)
3676 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "about to trace %d", (int) child->pid);
3678 + slowlog = fopen(child->wp->config->slowlog, "a+");
3681 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fopen(%s) failed", child->wp->config->slowlog);
3685 + if (0 > fpm_trace_ready(child->pid)) {
3689 + if (0 > fpm_php_trace_dump(child, slowlog)) {
3690 + fprintf(slowlog, "+++ dump failed\n");
3693 + if (0 > fpm_trace_close(child->pid)) {
3701 + fpm_pctl_kill(child->pid, FPM_PCTL_CONT);
3702 + child->tracer = 0;
3704 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "finished trace of %d", (int) child->pid);
3709 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php_trace.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_php_trace.h
3710 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_php_trace.h 1970-01-01 03:00:00.000000000 +0300
3711 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_php_trace.h 2008-05-24 21:38:47.000000000 +0400
3715 + /* (c) 2007,2008 Andrei Nigmatulin */
3717 +#ifndef FPM_PHP_TRACE_H
3718 +#define FPM_PHP_TRACE_H 1
3720 +struct fpm_child_s;
3722 +void fpm_php_trace(struct fpm_child_s *);
3726 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_process_ctl.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_process_ctl.c
3727 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_process_ctl.c 1970-01-01 03:00:00.000000000 +0300
3728 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_process_ctl.c 2008-07-21 17:13:44.000000000 +0400
3732 + /* (c) 2007,2008 Andrei Nigmatulin */
3734 +#include "fpm_config.h"
3736 +#include <sys/types.h>
3737 +#include <signal.h>
3738 +#include <unistd.h>
3739 +#include <stdlib.h>
3742 +#include "fpm_clock.h"
3743 +#include "fpm_children.h"
3744 +#include "fpm_signals.h"
3745 +#include "fpm_events.h"
3746 +#include "fpm_process_ctl.h"
3747 +#include "fpm_cleanup.h"
3748 +#include "fpm_request.h"
3749 +#include "fpm_worker_pool.h"
3753 +static int fpm_state = FPM_PCTL_STATE_NORMAL;
3754 +static int fpm_signal_sent = 0;
3757 +static const char *fpm_state_names[] = {
3758 + [FPM_PCTL_STATE_NORMAL] = "normal",
3759 + [FPM_PCTL_STATE_RELOADING] = "reloading",
3760 + [FPM_PCTL_STATE_TERMINATING] = "terminating",
3761 + [FPM_PCTL_STATE_FINISHING] = "finishing"
3764 +static int saved_argc;
3765 +static char **saved_argv;
3767 +static void fpm_pctl_cleanup(int which, void *arg)
3771 + if (which != FPM_CLEANUP_PARENT_EXEC) {
3773 + for (i = 0; i < saved_argc; i++) {
3774 + free(saved_argv[i]);
3782 +static struct event pctl_event;
3784 +static void fpm_pctl_action(int fd, short which, void *arg)
3786 + evtimer_del(&pctl_event);
3788 + memset(&pctl_event, 0, sizeof(pctl_event));
3790 + fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_TIMEOUT);
3793 +static int fpm_pctl_timeout_set(int sec)
3795 + struct timeval tv = { .tv_sec = sec, .tv_usec = 0 };
3797 + if (evtimer_initialized(&pctl_event)) {
3798 + evtimer_del(&pctl_event);
3801 + evtimer_set(&pctl_event, &fpm_pctl_action, 0);
3803 + evtimer_add(&pctl_event, &tv);
3808 +static void fpm_pctl_exit()
3810 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "exiting, bye-bye!");
3812 + fpm_conf_unlink_pid();
3814 + fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT_MAIN);
3819 +#define optional_arg(c) (saved_argc > c ? ", \"" : ""), (saved_argc > c ? saved_argv[c] : ""), (saved_argc > c ? "\"" : "")
3821 +static void fpm_pctl_exec()
3824 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "reloading: execvp(\"%s\", {\"%s\""
3825 + "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s"
3826 + "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s"
3828 + saved_argv[0], saved_argv[0],
3841 + fpm_cleanups_run(FPM_CLEANUP_PARENT_EXEC);
3843 + execvp(saved_argv[0], saved_argv);
3845 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "execvp() failed");
3850 +static void fpm_pctl_action_last()
3852 + switch (fpm_state) {
3854 + case FPM_PCTL_STATE_RELOADING :
3859 + case FPM_PCTL_STATE_FINISHING :
3861 + case FPM_PCTL_STATE_TERMINATING :
3868 +int fpm_pctl_kill(pid_t pid, int how)
3873 + case FPM_PCTL_TERM :
3876 + case FPM_PCTL_STOP :
3879 + case FPM_PCTL_CONT :
3886 + return kill(pid, s);
3889 +static void fpm_pctl_kill_all(int signo)
3891 + struct fpm_worker_pool_s *wp;
3892 + int alive_children = 0;
3894 + for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
3895 + struct fpm_child_s *child;
3897 + for (child = wp->children; child; child = child->next) {
3899 + int res = kill(child->pid, signo);
3901 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "sending signal %d %s to child %d (pool %s)", signo,
3902 + fpm_signal_names[signo] ? fpm_signal_names[signo] : "",
3903 + (int) child->pid, child->wp->config->name);
3905 + if (res == 0) ++alive_children;
3909 + if (alive_children) {
3910 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "%d %s still alive", alive_children, alive_children == 1 ? "child is" : "children are");
3914 +static void fpm_pctl_action_next()
3918 + if (!fpm_globals.running_children) fpm_pctl_action_last();
3920 + if (fpm_signal_sent == 0) {
3921 + if (fpm_state == FPM_PCTL_STATE_TERMINATING) {
3927 + timeout = fpm_global_options.process_control_timeout;
3930 + if (fpm_signal_sent == SIGQUIT) {
3939 + fpm_pctl_kill_all(sig);
3941 + fpm_signal_sent = sig;
3943 + fpm_pctl_timeout_set(timeout);
3946 +void fpm_pctl(int new_state, int action)
3950 + case FPM_PCTL_ACTION_SET :
3952 + if (fpm_state == new_state) { /* already in progress - just ignore duplicate signal */
3956 + switch (fpm_state) { /* check which states can be overridden */
3958 + case FPM_PCTL_STATE_NORMAL :
3960 + /* 'normal' can be overridden by any other state */
3963 + case FPM_PCTL_STATE_RELOADING :
3965 + /* 'reloading' can be overridden by 'finishing' */
3966 + if (new_state == FPM_PCTL_STATE_FINISHING) break;
3968 + case FPM_PCTL_STATE_FINISHING :
3970 + /* 'reloading' and 'finishing' can be overridden by 'terminating' */
3971 + if (new_state == FPM_PCTL_STATE_TERMINATING) break;
3973 + case FPM_PCTL_STATE_TERMINATING :
3975 + /* nothing can override 'terminating' state */
3976 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "not switching to '%s' state, because already in '%s' state",
3977 + fpm_state_names[new_state], fpm_state_names[fpm_state]);
3982 + fpm_signal_sent = 0;
3983 + fpm_state = new_state;
3985 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "switching to '%s' state", fpm_state_names[fpm_state]);
3989 + case FPM_PCTL_ACTION_TIMEOUT :
3991 + fpm_pctl_action_next();
3995 + case FPM_PCTL_ACTION_LAST_CHILD_EXITED :
3997 + fpm_pctl_action_last();
4004 +int fpm_pctl_can_spawn_children()
4006 + return fpm_state == FPM_PCTL_STATE_NORMAL;
4009 +int fpm_pctl_child_exited()
4011 + if (fpm_state == FPM_PCTL_STATE_NORMAL) return 0;
4013 + if (!fpm_globals.running_children) {
4014 + fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_LAST_CHILD_EXITED);
4020 +int fpm_pctl_init_main()
4024 + saved_argc = fpm_globals.argc;
4026 + saved_argv = malloc(sizeof(char *) * (saved_argc + 1));
4028 + if (!saved_argv) {
4032 + for (i = 0; i < saved_argc; i++) {
4033 + saved_argv[i] = strdup(fpm_globals.argv[i]);
4035 + if (!saved_argv[i]) {
4040 + saved_argv[i] = 0;
4042 + fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_pctl_cleanup, 0);
4047 +static void fpm_pctl_check_request_timeout(struct timeval *now)
4049 + struct fpm_worker_pool_s *wp;
4051 + for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
4052 + int terminate_timeout = wp->config->request_terminate_timeout;
4053 + int slowlog_timeout = wp->config->request_slowlog_timeout;
4054 + struct fpm_child_s *child;
4056 + if (terminate_timeout || slowlog_timeout) {
4057 + for (child = wp->children; child; child = child->next) {
4058 + fpm_request_check_timed_out(child, now, terminate_timeout, slowlog_timeout);
4065 +void fpm_pctl_heartbeat(int fd, short which, void *arg)
4067 + static struct event heartbeat;
4068 + struct timeval tv = { .tv_sec = 0, .tv_usec = 130000 };
4069 + struct timeval now;
4071 + if (which == EV_TIMEOUT) {
4072 + evtimer_del(&heartbeat);
4073 + fpm_clock_get(&now);
4074 + fpm_pctl_check_request_timeout(&now);
4077 + evtimer_set(&heartbeat, &fpm_pctl_heartbeat, 0);
4079 + evtimer_add(&heartbeat, &tv);
4082 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_process_ctl.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_process_ctl.h
4083 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_process_ctl.h 1970-01-01 03:00:00.000000000 +0300
4084 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_process_ctl.h 2008-07-21 01:33:10.000000000 +0400
4088 + /* (c) 2007,2008 Andrei Nigmatulin */
4090 +#ifndef FPM_PROCESS_CTL_H
4091 +#define FPM_PROCESS_CTL_H 1
4093 +struct fpm_child_s;
4095 +void fpm_pctl(int new_state, int action);
4096 +int fpm_pctl_can_spawn_children();
4097 +int fpm_pctl_kill(pid_t pid, int how);
4098 +void fpm_pctl_heartbeat(int fd, short which, void *arg);
4099 +int fpm_pctl_child_exited();
4100 +int fpm_pctl_init_main();
4104 + FPM_PCTL_STATE_UNSPECIFIED,
4105 + FPM_PCTL_STATE_NORMAL,
4106 + FPM_PCTL_STATE_RELOADING,
4107 + FPM_PCTL_STATE_TERMINATING,
4108 + FPM_PCTL_STATE_FINISHING
4112 + FPM_PCTL_ACTION_SET,
4113 + FPM_PCTL_ACTION_TIMEOUT,
4114 + FPM_PCTL_ACTION_LAST_CHILD_EXITED
4125 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_request.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_request.c
4126 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_request.c 1970-01-01 03:00:00.000000000 +0300
4127 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_request.c 2008-09-01 03:34:36.000000000 +0400
4131 + /* (c) 2007,2008 Andrei Nigmatulin */
4133 +#include "fpm_config.h"
4135 +#include "fpm_php.h"
4136 +#include "fpm_str.h"
4137 +#include "fpm_clock.h"
4138 +#include "fpm_conf.h"
4139 +#include "fpm_trace.h"
4140 +#include "fpm_php_trace.h"
4141 +#include "fpm_process_ctl.h"
4142 +#include "fpm_children.h"
4143 +#include "fpm_shm_slots.h"
4144 +#include "fpm_request.h"
4148 +void fpm_request_accepting()
4150 + struct fpm_shm_slot_s *slot;
4152 + slot = fpm_shm_slots_acquire(0, 0);
4154 + slot->request_stage = FPM_REQUEST_ACCEPTING;
4156 + fpm_clock_get(&slot->tv);
4157 + memset(slot->request_method, 0, sizeof(slot->request_method));
4158 + slot->content_length = 0;
4159 + memset(slot->script_filename, 0, sizeof(slot->script_filename));
4161 + fpm_shm_slots_release(slot);
4164 +void fpm_request_reading_headers()
4166 + struct fpm_shm_slot_s *slot;
4168 + slot = fpm_shm_slots_acquire(0, 0);
4170 + slot->request_stage = FPM_REQUEST_READING_HEADERS;
4172 + fpm_clock_get(&slot->tv);
4173 + slot->accepted = slot->tv;
4175 + fpm_shm_slots_release(slot);
4178 +void fpm_request_info()
4180 + struct fpm_shm_slot_s *slot;
4181 + char *request_method = fpm_php_request_method();
4182 + char *script_filename = fpm_php_script_filename();
4184 + slot = fpm_shm_slots_acquire(0, 0);
4186 + slot->request_stage = FPM_REQUEST_INFO;
4188 + fpm_clock_get(&slot->tv);
4190 + if (request_method) {
4191 + cpystrn(slot->request_method, request_method, sizeof(slot->request_method));
4194 + slot->content_length = fpm_php_content_length();
4196 + /* if cgi.fix_pathinfo is set to "1" and script cannot be found (404)
4197 + the sapi_globals.request_info.path_translated is set to NULL */
4198 + if (script_filename) {
4199 + cpystrn(slot->script_filename, script_filename, sizeof(slot->script_filename));
4202 + fpm_shm_slots_release(slot);
4205 +void fpm_request_executing()
4207 + struct fpm_shm_slot_s *slot;
4209 + slot = fpm_shm_slots_acquire(0, 0);
4211 + slot->request_stage = FPM_REQUEST_EXECUTING;
4213 + fpm_clock_get(&slot->tv);
4215 + fpm_shm_slots_release(slot);
4218 +void fpm_request_finished()
4220 + struct fpm_shm_slot_s *slot;
4222 + slot = fpm_shm_slots_acquire(0, 0);
4224 + slot->request_stage = FPM_REQUEST_FINISHED;
4226 + fpm_clock_get(&slot->tv);
4227 + memset(&slot->accepted, 0, sizeof(slot->accepted));
4229 + fpm_shm_slots_release(slot);
4232 +void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, int terminate_timeout, int slowlog_timeout)
4234 + struct fpm_shm_slot_s *slot;
4235 + struct fpm_shm_slot_s slot_c;
4237 + slot = fpm_shm_slot(child);
4239 + if (!fpm_shm_slots_acquire(slot, 1)) {
4245 + fpm_shm_slots_release(slot);
4248 + if (child->slow_logged.tv_sec) {
4249 + if (child->slow_logged.tv_sec != slot_c.accepted.tv_sec || child->slow_logged.tv_usec != slot_c.accepted.tv_usec) {
4250 + child->slow_logged.tv_sec = 0;
4251 + child->slow_logged.tv_usec = 0;
4256 + if (slot_c.request_stage > FPM_REQUEST_ACCEPTING && slot_c.request_stage < FPM_REQUEST_FINISHED) {
4257 + char purified_script_filename[sizeof(slot_c.script_filename)];
4258 + struct timeval tv;
4260 + timersub(now, &slot_c.accepted, &tv);
4263 + if (child->slow_logged.tv_sec == 0 && slowlog_timeout &&
4264 + slot_c.request_stage == FPM_REQUEST_EXECUTING && tv.tv_sec >= slowlog_timeout) {
4266 + str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename));
4268 + child->slow_logged = slot_c.accepted;
4269 + child->tracer = fpm_php_trace;
4271 + fpm_trace_signal(child->pid);
4273 + zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d, script '%s' (pool %s) executing too slow (%d.%06d sec), logging",
4274 + (int) child->pid, purified_script_filename, child->wp->config->name, (int) tv.tv_sec, (int) tv.tv_usec);
4279 + if (terminate_timeout && tv.tv_sec >= terminate_timeout) {
4281 + str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename));
4283 + fpm_pctl_kill(child->pid, FPM_PCTL_TERM);
4285 + zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d, script '%s' (pool %s) execution timed out (%d.%06d sec), terminating",
4286 + (int) child->pid, purified_script_filename, child->wp->config->name, (int) tv.tv_sec, (int) tv.tv_usec);
4292 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_request.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_request.h
4293 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_request.h 1970-01-01 03:00:00.000000000 +0300
4294 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_request.h 2008-07-20 05:47:16.000000000 +0400
4298 + /* (c) 2007,2008 Andrei Nigmatulin */
4300 +#ifndef FPM_REQUEST_H
4301 +#define FPM_REQUEST_H 1
4303 +void fpm_request_accepting(); /* hanging in accept() */
4304 +void fpm_request_reading_headers(); /* start reading fastcgi request from very first byte */
4305 +void fpm_request_info(); /* not a stage really but a point in the php code, where all request params have become known to sapi */
4306 +void fpm_request_executing(); /* the script is executing */
4307 +void fpm_request_finished(); /* request processed: script response have been sent to web server */
4309 +struct fpm_child_s;
4312 +void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *tv, int terminate_timeout, int slowlog_timeout);
4314 +enum fpm_request_stage_e {
4315 + FPM_REQUEST_ACCEPTING = 1,
4316 + FPM_REQUEST_READING_HEADERS,
4318 + FPM_REQUEST_EXECUTING,
4319 + FPM_REQUEST_FINISHED
4323 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm.c
4324 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm.c 1970-01-01 03:00:00.000000000 +0300
4325 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm.c 2008-05-24 21:38:47.000000000 +0400
4329 + /* (c) 2007,2008 Andrei Nigmatulin */
4331 +#include "fpm_config.h"
4333 +#include <unistd.h>
4334 +#include <sys/mman.h>
4335 +#include <stdlib.h>
4337 +#include "fpm_shm.h"
4341 +/* MAP_ANON is depricated, but not in macosx */
4342 +#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
4343 +#define MAP_ANONYMOUS MAP_ANON
4347 +struct fpm_shm_s *fpm_shm_alloc(size_t sz)
4349 + struct fpm_shm_s *shm;
4351 + shm = malloc(sizeof(*shm));
4357 + shm->mem = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
4360 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "mmap(MAP_ANONYMOUS | MAP_SHARED) failed");
4371 +static void fpm_shm_free(struct fpm_shm_s *shm, int do_unmap)
4374 + munmap(shm->mem, shm->sz);
4380 +void fpm_shm_free_list(struct fpm_shm_s *shm, void *mem)
4382 + struct fpm_shm_s *next;
4384 + for (; shm; shm = next) {
4387 + fpm_shm_free(shm, mem != shm->mem);
4391 +void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem)
4393 + size_t pagesize = getpagesize();
4394 + static const size_t cache_line_size = 16;
4395 + size_t aligned_sz;
4396 + struct fpm_shm_s *shm;
4399 + sz = (sz + cache_line_size - 1) & -cache_line_size;
4403 + if (0 == shm || shm->sz - shm->used < sz) {
4404 + /* allocate one more shm segment */
4406 + aligned_sz = (sz + pagesize - 1) & -pagesize;
4408 + shm = fpm_shm_alloc(aligned_sz);
4414 + shm->next = *head;
4415 + if (shm->next) shm->next->prev = shm;
4421 + ret = (char *) shm->mem + shm->used;
4427 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm.h
4428 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm.h 1970-01-01 03:00:00.000000000 +0300
4429 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm.h 2008-05-24 21:38:47.000000000 +0400
4433 + /* (c) 2007,2008 Andrei Nigmatulin */
4436 +#define FPM_SHM_H 1
4441 + struct fpm_shm_s *prev, *next;
4447 +struct fpm_shm_s *fpm_shm_alloc(size_t sz);
4448 +void fpm_shm_free_list(struct fpm_shm_s *, void *);
4449 +void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem);
4453 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm_slots.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm_slots.c
4454 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm_slots.c 1970-01-01 03:00:00.000000000 +0300
4455 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm_slots.c 2008-05-24 21:38:47.000000000 +0400
4459 + /* (c) 2007,2008 Andrei Nigmatulin */
4461 +#include "fpm_config.h"
4463 +#include "fpm_atomic.h"
4464 +#include "fpm_worker_pool.h"
4465 +#include "fpm_children.h"
4466 +#include "fpm_shm.h"
4467 +#include "fpm_shm_slots.h"
4470 +static void *shm_mem;
4471 +static struct fpm_shm_slot_s *shm_slot;
4473 +int fpm_shm_slots_prepare_slot(struct fpm_child_s *child)
4475 + struct fpm_worker_pool_s *wp = child->wp;
4476 + struct fpm_shm_slot_ptr_s *shm_slot_ptr;
4478 + child->shm_slot_i = wp->slots_used.used;
4480 + shm_slot_ptr = fpm_array_push(&wp->slots_used);
4482 + if (0 == shm_slot_ptr) {
4486 + if (0 == wp->slots_free.used) {
4487 + shm_slot_ptr->shm_slot = fpm_shm_alloc_chunk(&wp->shm_list, sizeof(struct fpm_shm_slot_s), &shm_slot_ptr->mem);
4489 + if (!shm_slot_ptr->shm_slot) {
4494 + *shm_slot_ptr = *(struct fpm_shm_slot_ptr_s *) fpm_array_item_last(&wp->slots_free);
4496 + --wp->slots_free.used;
4499 + memset(shm_slot_ptr->shm_slot, 0, sizeof(struct fpm_shm_slot_s));
4501 + shm_slot_ptr->child = child;
4506 +void fpm_shm_slots_discard_slot(struct fpm_child_s *child)
4508 + struct fpm_shm_slot_ptr_s *shm_slot_ptr;
4509 + struct fpm_worker_pool_s *wp = child->wp;
4512 + shm_slot_ptr = fpm_array_push(&wp->slots_free);
4514 + if (shm_slot_ptr) {
4516 + struct fpm_shm_slot_ptr_s *shm_slot_ptr_used;
4518 + shm_slot_ptr_used = fpm_array_item(&wp->slots_used, child->shm_slot_i);
4520 + *shm_slot_ptr = *shm_slot_ptr_used;
4522 + shm_slot_ptr->child = 0;
4526 + n = fpm_array_item_remove(&wp->slots_used, child->shm_slot_i);
4529 + shm_slot_ptr = fpm_array_item(&wp->slots_used, n);
4531 + shm_slot_ptr->child->shm_slot_i = n;
4535 +void fpm_shm_slots_child_use_slot(struct fpm_child_s *child)
4537 + struct fpm_shm_slot_ptr_s *shm_slot_ptr;
4538 + struct fpm_worker_pool_s *wp = child->wp;
4540 + shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i);
4542 + shm_slot = shm_slot_ptr->shm_slot;
4543 + shm_mem = shm_slot_ptr->mem;
4546 +void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child)
4548 + /* nothing to do */
4551 +void *fpm_shm_slots_mem()
4556 +struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child)
4558 + struct fpm_shm_slot_ptr_s *shm_slot_ptr;
4559 + struct fpm_worker_pool_s *wp = child->wp;
4561 + shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i);
4563 + return shm_slot_ptr->shm_slot;
4566 +struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *s, int nohang)
4572 + if (0 > fpm_spinlock(&s->lock, nohang)) {
4579 +void fpm_shm_slots_release(struct fpm_shm_slot_s *s)
4584 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm_slots.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm_slots.h
4585 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_shm_slots.h 1970-01-01 03:00:00.000000000 +0300
4586 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_shm_slots.h 2008-05-24 21:38:47.000000000 +0400
4590 + /* (c) 2007,2008 Andrei Nigmatulin */
4592 +#ifndef FPM_SHM_SLOTS_H
4593 +#define FPM_SHM_SLOTS_H 1
4595 +#include "fpm_atomic.h"
4596 +#include "fpm_worker_pool.h"
4597 +#include "fpm_request.h"
4599 +struct fpm_child_s;
4601 +struct fpm_shm_slot_s {
4606 + enum fpm_request_stage_e request_stage;
4607 + struct timeval accepted;
4608 + struct timeval tv;
4609 + char request_method[16];
4610 + size_t content_length; /* used with POST only */
4611 + char script_filename[256];
4614 +struct fpm_shm_slot_ptr_s {
4616 + struct fpm_shm_slot_s *shm_slot;
4617 + struct fpm_child_s *child;
4620 +int fpm_shm_slots_prepare_slot(struct fpm_child_s *child);
4621 +void fpm_shm_slots_discard_slot(struct fpm_child_s *child);
4622 +void fpm_shm_slots_child_use_slot(struct fpm_child_s *child);
4623 +void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child);
4624 +void *fpm_shm_slots_mem();
4625 +struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child);
4626 +struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *, int nohang);
4627 +void fpm_shm_slots_release(struct fpm_shm_slot_s *);
4631 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_signals.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_signals.c
4632 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_signals.c 1970-01-01 03:00:00.000000000 +0300
4633 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_signals.c 2008-08-26 19:09:15.000000000 +0400
4637 + /* (c) 2007,2008 Andrei Nigmatulin */
4639 +#include "fpm_config.h"
4641 +#include <signal.h>
4643 +#include <sys/types.h>
4644 +#include <sys/socket.h>
4645 +#include <stdlib.h>
4646 +#include <string.h>
4648 +#include <unistd.h>
4652 +#include "fpm_signals.h"
4653 +#include "fpm_sockets.h"
4654 +#include "fpm_php.h"
4659 +const char *fpm_signal_names[NSIG + 1] = {
4661 + [SIGHUP] = "SIGHUP",
4664 + [SIGINT] = "SIGINT",
4667 + [SIGQUIT] = "SIGQUIT",
4670 + [SIGILL] = "SIGILL",
4673 + [SIGTRAP] = "SIGTRAP",
4676 + [SIGABRT] = "SIGABRT",
4679 + [SIGEMT] = "SIGEMT",
4682 + [SIGBUS] = "SIGBUS",
4685 + [SIGFPE] = "SIGFPE",
4688 + [SIGKILL] = "SIGKILL",
4691 + [SIGUSR1] = "SIGUSR1",
4694 + [SIGSEGV] = "SIGSEGV",
4697 + [SIGUSR2] = "SIGUSR2",
4700 + [SIGPIPE] = "SIGPIPE",
4703 + [SIGALRM] = "SIGALRM",
4706 + [SIGTERM] = "SIGTERM",
4709 + [SIGCHLD] = "SIGCHLD",
4712 + [SIGCONT] = "SIGCONT",
4715 + [SIGSTOP] = "SIGSTOP",
4718 + [SIGTSTP] = "SIGTSTP",
4721 + [SIGTTIN] = "SIGTTIN",
4724 + [SIGTTOU] = "SIGTTOU",
4727 + [SIGURG] = "SIGURG",
4730 + [SIGXCPU] = "SIGXCPU",
4733 + [SIGXFSZ] = "SIGXFSZ",
4736 + [SIGVTALRM] = "SIGVTALRM",
4739 + [SIGPROF] = "SIGPROF",
4742 + [SIGWINCH] = "SIGWINCH",
4745 + [SIGINFO] = "SIGINFO",
4748 + [SIGIO] = "SIGIO",
4751 + [SIGPWR] = "SIGPWR",
4754 + [SIGSYS] = "SIGSYS",
4757 + [SIGWAITING] = "SIGWAITING",
4760 + [SIGLWP] = "SIGLWP",
4763 + [SIGFREEZE] = "SIGFREEZE",
4766 + [SIGTHAW] = "SIGTHAW",
4769 + [SIGCANCEL] = "SIGCANCEL",
4772 + [SIGLOST] = "SIGLOST",
4776 +static void sig_soft_quit(int signo)
4778 + int saved_errno = errno;
4780 + /* closing fastcgi listening socket will force fcgi_accept() exit immediately */
4782 + socket(AF_UNIX, SOCK_STREAM, 0);
4784 + fpm_php_soft_quit();
4786 + errno = saved_errno;
4789 +static void sig_handler(int signo)
4791 + static const char sig_chars[NSIG + 1] = {
4802 + if (fpm_globals.parent_pid != getpid()) {
4803 + /* prevent a signal race condition when child process
4804 + have not set up it's own signal handler yet */
4808 + saved_errno = errno;
4810 + s = sig_chars[signo];
4812 + write(sp[1], &s, sizeof(s));
4814 + errno = saved_errno;
4817 +int fpm_signals_init_main()
4819 + struct sigaction act;
4821 + if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) {
4822 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "socketpair() failed");
4826 + if (0 > fd_set_blocked(sp[0], 0) || 0 > fd_set_blocked(sp[1], 0)) {
4827 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fd_set_blocked() failed");
4831 + if (0 > fcntl(sp[0], F_SETFD, FD_CLOEXEC) || 0 > fcntl(sp[1], F_SETFD, FD_CLOEXEC)) {
4832 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fcntl(F_SETFD, FD_CLOEXEC) failed");
4836 + memset(&act, 0, sizeof(act));
4837 + act.sa_handler = sig_handler;
4838 + sigfillset(&act.sa_mask);
4840 + if (0 > sigaction(SIGTERM, &act, 0) ||
4841 + 0 > sigaction(SIGINT, &act, 0) ||
4842 + 0 > sigaction(SIGUSR1, &act, 0) ||
4843 + 0 > sigaction(SIGUSR2, &act, 0) ||
4844 + 0 > sigaction(SIGCHLD, &act, 0) ||
4845 + 0 > sigaction(SIGQUIT, &act, 0)) {
4847 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed");
4854 +int fpm_signals_init_child()
4856 + struct sigaction act, act_dfl;
4858 + memset(&act, 0, sizeof(act));
4859 + memset(&act_dfl, 0, sizeof(act_dfl));
4861 + act.sa_handler = &sig_soft_quit;
4862 + act.sa_flags |= SA_RESTART;
4864 + act_dfl.sa_handler = SIG_DFL;
4869 + if (0 > sigaction(SIGTERM, &act_dfl, 0) ||
4870 + 0 > sigaction(SIGINT, &act_dfl, 0) ||
4871 + 0 > sigaction(SIGUSR1, &act_dfl, 0) ||
4872 + 0 > sigaction(SIGUSR2, &act_dfl, 0) ||
4873 + 0 > sigaction(SIGCHLD, &act_dfl, 0) ||
4874 + 0 > sigaction(SIGQUIT, &act, 0)) {
4876 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed");
4883 +int fpm_signals_get_fd()
4887 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_signals.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_signals.h
4888 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_signals.h 1970-01-01 03:00:00.000000000 +0300
4889 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_signals.h 2008-05-24 21:38:47.000000000 +0400
4893 + /* (c) 2007,2008 Andrei Nigmatulin */
4895 +#ifndef FPM_SIGNALS_H
4896 +#define FPM_SIGNALS_H 1
4898 +#include <signal.h>
4900 +int fpm_signals_init_main();
4901 +int fpm_signals_init_child();
4902 +int fpm_signals_get_fd();
4904 +extern const char *fpm_signal_names[NSIG + 1];
4907 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_sockets.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_sockets.c
4908 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_sockets.c 1970-01-01 03:00:00.000000000 +0300
4909 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_sockets.c 2008-08-26 19:09:15.000000000 +0400
4913 + /* (c) 2007,2008 Andrei Nigmatulin */
4915 +#include "fpm_config.h"
4917 +#ifdef HAVE_ALLOCA_H
4918 +#include <alloca.h>
4920 +#include <sys/types.h>
4921 +#include <sys/stat.h> /* for chmod(2) */
4922 +#include <sys/socket.h>
4923 +#include <netinet/in.h>
4924 +#include <arpa/inet.h>
4925 +#include <sys/un.h>
4928 +#include <stdlib.h>
4929 +#include <string.h>
4931 +#include <unistd.h>
4934 +#include "fpm_arrays.h"
4935 +#include "fpm_sockets.h"
4936 +#include "fpm_worker_pool.h"
4937 +#include "fpm_unix.h"
4938 +#include "fpm_str.h"
4939 +#include "fpm_env.h"
4940 +#include "fpm_cleanup.h"
4942 +struct listening_socket_s {
4949 +static struct fpm_array_s sockets_list;
4951 +static int fpm_sockets_resolve_af_inet(char *node, char *service, struct sockaddr_in *addr)
4953 + struct addrinfo *res;
4954 + struct addrinfo hints;
4957 + memset(&hints, 0, sizeof(hints));
4959 + hints.ai_family = AF_INET;
4961 + ret = getaddrinfo(node, service, &hints, &res);
4964 + zlog(ZLOG_STUFF, ZLOG_ERROR, "can't resolve hostname '%s%s%s': getaddrinfo said: %s%s%s\n",
4965 + node, service ? ":" : "", service ? service : "",
4966 + gai_strerror(ret), ret == EAI_SYSTEM ? ", system error: " : "", ret == EAI_SYSTEM ? strerror(errno) : "");
4970 + *addr = *(struct sockaddr_in *) res->ai_addr;
4972 + freeaddrinfo(res);
4977 +enum { FPM_GET_USE_SOCKET = 1, FPM_STORE_SOCKET = 2, FPM_STORE_USE_SOCKET = 3 };
4979 +static void fpm_sockets_cleanup(int which, void *arg)
4982 + char *env_value = 0;
4984 + struct listening_socket_s *ls = sockets_list.data;
4986 + for (i = 0; i < sockets_list.used; i++, ls++) {
4988 + if (which != FPM_CLEANUP_PARENT_EXEC) {
4993 + else { /* on PARENT EXEC we want socket fds to be inherited through environment variable */
4995 + sprintf(fd, "%d", ls->sock);
4996 + env_value = realloc(env_value, p + (p ? 1 : 0) + strlen(ls->key) + 1 + strlen(fd) + 1);
4997 + p += sprintf(env_value + p, "%s%s=%s", p ? "," : "", ls->key, fd);
5000 + if (which == FPM_CLEANUP_PARENT_EXIT_MAIN) {
5002 + if (ls->type == FPM_AF_UNIX) {
5012 + setenv("FPM_SOCKETS", env_value, 1);
5016 + fpm_array_free(&sockets_list);
5019 +static int fpm_sockets_hash_op(int sock, struct sockaddr *sa, char *key, int type, int op)
5022 + if (key == NULL) {
5026 + case FPM_AF_INET : {
5027 + struct sockaddr_in *sa_in = (struct sockaddr_in *) sa;
5029 + key = alloca(sizeof("xxx.xxx.xxx.xxx:ppppp"));
5031 + sprintf(key, "%u.%u.%u.%u:%u", IPQUAD(&sa_in->sin_addr), (unsigned int) ntohs(sa_in->sin_port));
5036 + case FPM_AF_UNIX : {
5037 + struct sockaddr_un *sa_un = (struct sockaddr_un *) sa;
5039 + key = alloca(strlen(sa_un->sun_path) + 1);
5041 + strcpy(key, sa_un->sun_path);
5055 + case FPM_GET_USE_SOCKET :
5059 + struct listening_socket_s *ls = sockets_list.data;
5061 + for (i = 0; i < sockets_list.used; i++, ls++) {
5063 + if (!strcmp(ls->key, key)) {
5072 + case FPM_STORE_SOCKET : /* inherited socket */
5073 + case FPM_STORE_USE_SOCKET : /* just created */
5076 + struct listening_socket_s *ls;
5078 + ls = fpm_array_push(&sockets_list);
5084 + if (op == FPM_STORE_SOCKET) {
5092 + ls->key = strdup(key);
5103 +static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct sockaddr *sa, int socklen)
5108 + mode_t saved_umask;
5110 + /* we have custom backlog value */
5111 + if (wp->config->listen_options) {
5112 + backlog = wp->config->listen_options->backlog;
5115 + sock = socket(sa->sa_family, SOCK_STREAM, 0);
5118 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "socket() failed");
5122 + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags));
5124 + if (wp->listen_address_domain == FPM_AF_UNIX) {
5125 + unlink( ((struct sockaddr_un *) sa)->sun_path);
5128 + saved_umask = umask(0777 ^ wp->socket_mode);
5130 + if (0 > bind(sock, sa, socklen)) {
5131 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "bind() for address '%s' failed", wp->config->listen_address);
5135 + if (wp->listen_address_domain == FPM_AF_UNIX) {
5137 + char *path = ((struct sockaddr_un *) sa)->sun_path;
5139 + if (wp->socket_uid != -1 || wp->socket_gid != -1) {
5141 + if (0 > chown(path, wp->socket_uid, wp->socket_gid)) {
5142 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chown() for address '%s' failed", wp->config->listen_address);
5150 + umask(saved_umask);
5152 + if (0 > listen(sock, backlog)) {
5153 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "listen() for address '%s' failed", wp->config->listen_address);
5160 +static int fpm_sockets_get_listening_socket(struct fpm_worker_pool_s *wp, struct sockaddr *sa, int socklen)
5164 + sock = fpm_sockets_hash_op(0, sa, 0, wp->listen_address_domain, FPM_GET_USE_SOCKET);
5166 + if (sock >= 0) return sock;
5168 + sock = fpm_sockets_new_listening_socket(wp, sa, socklen);
5170 + fpm_sockets_hash_op(sock, sa, 0, wp->listen_address_domain, FPM_STORE_USE_SOCKET);
5175 +enum fpm_address_domain fpm_sockets_domain_from_address(char *address)
5177 + if (strchr(address, ':')) return FPM_AF_INET;
5179 + if (strlen(address) == strspn(address, "0123456789")) return FPM_AF_INET;
5181 + return FPM_AF_UNIX;
5184 +static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp)
5186 + struct sockaddr_in sa_in;
5187 + char *dup_address = strdup(wp->config->listen_address);
5188 + char *port_str = strchr(dup_address, ':');
5189 + char *addr = NULL;
5192 + if (port_str) { /* this is host:port pair */
5193 + *port_str++ = '\0';
5194 + port = atoi(port_str);
5195 + addr = dup_address;
5197 + else if (strlen(dup_address) == strspn(dup_address, "0123456789")) { /* this is port */
5198 + port = atoi(dup_address);
5199 + port_str = dup_address;
5203 + zlog(ZLOG_STUFF, ZLOG_ERROR, "invalid port value '%s'", port_str);
5207 + memset(&sa_in, 0, sizeof(sa_in));
5211 + sa_in.sin_addr.s_addr = inet_addr(addr);
5213 + if (sa_in.sin_addr.s_addr == INADDR_NONE) { /* do resolve */
5214 + if (0 > fpm_sockets_resolve_af_inet(addr, NULL, &sa_in)) {
5217 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "address '%s' resolved as %u.%u.%u.%u", addr, IPQUAD(&sa_in.sin_addr));
5222 + sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
5226 + sa_in.sin_family = AF_INET;
5227 + sa_in.sin_port = htons(port);
5229 + free(dup_address);
5231 + return fpm_sockets_get_listening_socket(wp, (struct sockaddr *) &sa_in, sizeof(struct sockaddr_in));
5234 +static int fpm_socket_af_unix_listening_socket(struct fpm_worker_pool_s *wp)
5236 + struct sockaddr_un sa_un;
5238 + memset(&sa_un, 0, sizeof(sa_un));
5240 + cpystrn(sa_un.sun_path, wp->config->listen_address, sizeof(sa_un.sun_path));
5241 + sa_un.sun_family = AF_UNIX;
5243 + return fpm_sockets_get_listening_socket(wp, (struct sockaddr *) &sa_un, sizeof(struct sockaddr_un));
5246 +int fpm_sockets_init_main()
5249 + struct fpm_worker_pool_s *wp;
5250 + char *inherited = getenv("FPM_SOCKETS");
5251 + struct listening_socket_s *ls;
5253 + if (0 == fpm_array_init(&sockets_list, sizeof(struct listening_socket_s), 10)) {
5257 + /* import inherited sockets */
5258 + while (inherited && *inherited) {
5259 + char *comma = strchr(inherited, ',');
5263 + if (comma) *comma = '\0';
5265 + eq = strchr(inherited, '=');
5270 + fd_no = atoi(eq + 1);
5272 + type = fpm_sockets_domain_from_address(inherited);
5274 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "using inherited socket fd=%d, \"%s\"", fd_no, inherited);
5276 + fpm_sockets_hash_op(fd_no, 0, inherited, type, FPM_STORE_SOCKET);
5279 + if (comma) inherited = comma + 1;
5280 + else inherited = 0;
5283 + /* create all required sockets */
5284 + for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
5286 + if (!wp->is_template) {
5288 + switch (wp->listen_address_domain) {
5290 + case FPM_AF_INET :
5292 + wp->listening_socket = fpm_socket_af_inet_listening_socket(wp);
5295 + case FPM_AF_UNIX :
5297 + if (0 > fpm_unix_resolve_socket_premissions(wp)) {
5301 + wp->listening_socket = fpm_socket_af_unix_listening_socket(wp);
5306 + if (wp->listening_socket == -1) {
5313 + /* close unused sockets that was inherited */
5314 + ls = sockets_list.data;
5316 + for (i = 0; i < sockets_list.used; ) {
5318 + if (ls->refcount == 0) {
5320 + if (ls->type == FPM_AF_UNIX) {
5324 + fpm_array_item_remove(&sockets_list, i);
5332 + fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_sockets_cleanup, 0);
5336 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_sockets.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_sockets.h
5337 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_sockets.h 1970-01-01 03:00:00.000000000 +0300
5338 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_sockets.h 2008-08-26 19:09:15.000000000 +0400
5342 + /* (c) 2007,2008 Andrei Nigmatulin */
5345 +#define FPM_MISC_H 1
5347 +#include <unistd.h>
5350 +#include "fpm_worker_pool.h"
5352 +enum fpm_address_domain fpm_sockets_domain_from_address(char *addr);
5353 +int fpm_sockets_init_main();
5356 +static inline int fd_set_blocked(int fd, int blocked)
5358 + int flags = fcntl(fd, F_GETFL);
5360 + if (flags < 0) return -1;
5363 + flags &= ~O_NONBLOCK;
5365 + flags |= O_NONBLOCK;
5367 + return fcntl(fd, F_SETFL, flags);
5370 +#define IPQUAD(sin_addr) \
5371 + (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[0], \
5372 + (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[1], \
5373 + (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[2], \
5374 + (unsigned int) ((unsigned char *) &(sin_addr)->s_addr)[3]
5377 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_stdio.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_stdio.c
5378 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_stdio.c 1970-01-01 03:00:00.000000000 +0300
5379 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_stdio.c 2008-05-24 21:38:47.000000000 +0400
5383 + /* (c) 2007,2008 Andrei Nigmatulin */
5385 +#include "fpm_config.h"
5387 +#include <sys/types.h>
5388 +#include <sys/stat.h>
5389 +#include <string.h>
5391 +#include <unistd.h>
5395 +#include "fpm_children.h"
5396 +#include "fpm_events.h"
5397 +#include "fpm_sockets.h"
5398 +#include "fpm_stdio.h"
5401 +static int fd_stdout[2];
5402 +static int fd_stderr[2];
5404 +int fpm_stdio_init_main()
5406 + int fd = open("/dev/null", O_RDWR);
5409 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(\"/dev/null\") failed");
5413 + dup2(fd, STDIN_FILENO);
5414 + dup2(fd, STDOUT_FILENO);
5420 +int fpm_stdio_init_final()
5422 + if (fpm_global_options.daemonize) {
5424 + if (fpm_globals.error_log_fd != STDERR_FILENO) {
5425 + /* there might be messages to stderr from libevent, we need to log them all */
5426 + dup2(fpm_globals.error_log_fd, STDERR_FILENO);
5429 + zlog_set_level(fpm_globals.log_level);
5431 + zlog_set_fd(fpm_globals.error_log_fd);
5437 +int fpm_stdio_init_child(struct fpm_worker_pool_s *wp)
5439 + close(fpm_globals.error_log_fd);
5440 + fpm_globals.error_log_fd = -1;
5443 + if (wp->listening_socket != STDIN_FILENO) {
5444 + dup2(wp->listening_socket, STDIN_FILENO);
5450 +static void fpm_stdio_child_said(int fd, short which, void *arg)
5452 + static const int max_buf_size = 1024;
5453 + char buf[max_buf_size];
5454 + struct fpm_child_s *child = arg;
5455 + int is_stdout = fd == child->fd_stdout;
5456 + struct event *ev = is_stdout ? &child->ev_stdout : &child->ev_stderr;
5457 + int fifo_in = 1, fifo_out = 1;
5458 + int is_last_message = 0;
5463 + zlog(ZLOG_STUFF, ZLOG_DEBUG, "child %d said %s", (int) child->pid, is_stdout ? "stdout" : "stderr");
5466 + while (fifo_in || fifo_out) {
5470 + res = read(fd, buf + in_buf, max_buf_size - 1 - in_buf);
5472 + if (res <= 0) { /* no data */
5475 + if (res < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
5476 + /* just no more data ready */
5478 + else { /* error or pipe is closed */
5480 + if (res < 0) { /* error */
5481 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed");
5484 + fpm_event_del(ev);
5485 + is_last_message = 1;
5488 + close(child->fd_stdout);
5489 + child->fd_stdout = -1;
5492 + close(child->fd_stderr);
5493 + child->fd_stderr = -1;
5497 + if (in_buf == 0 && !fpm_globals.is_child) {
5498 + zlog(ZLOG_STUFF, ZLOG_DEBUG, "child %d (pool %s) %s pipe is closed", (int) child->pid,
5499 + child->wp->config->name, is_stdout ? "stdout" : "stderr");
5510 + if (in_buf == 0) {
5515 + int should_print = 0;
5516 + buf[in_buf] = '\0';
5518 + /* FIXME: there might be binary data */
5520 + /* we should print if no more space in the buffer */
5521 + if (in_buf == max_buf_size - 1) {
5525 + /* we should print if no more data to come */
5530 + nl = strchr(buf, '\n');
5532 + if (nl || should_print) {
5538 + zlog(ZLOG_STUFF, ZLOG_WARNING, "child %d (pool %s) said into %s: \"%s\"%s", (int) child->pid,
5539 + child->wp->config->name, is_stdout ? "stdout" : "stderr", buf, is_last_message ? ", pipe is closed" : "");
5542 + int out_buf = 1 + nl - buf;
5543 + memmove(buf, buf + out_buf, in_buf - out_buf);
5544 + in_buf -= out_buf;
5556 +int fpm_stdio_prepare_pipes(struct fpm_child_s *child)
5558 + if (0 == child->wp->config->catch_workers_output) { /* not required */
5562 + if (0 > pipe(fd_stdout)) {
5563 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pipe() failed");
5567 + if (0 > pipe(fd_stderr)) {
5568 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pipe() failed");
5569 + close(fd_stdout[0]); close(fd_stdout[1]);
5573 + if (0 > fd_set_blocked(fd_stdout[0], 0) || 0 > fd_set_blocked(fd_stderr[0], 0)) {
5574 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fd_set_blocked() failed");
5575 + close(fd_stdout[0]); close(fd_stdout[1]);
5576 + close(fd_stderr[0]); close(fd_stderr[1]);
5583 +int fpm_stdio_parent_use_pipes(struct fpm_child_s *child)
5585 + if (0 == child->wp->config->catch_workers_output) { /* not required */
5589 + close(fd_stdout[1]);
5590 + close(fd_stderr[1]);
5592 + child->fd_stdout = fd_stdout[0];
5593 + child->fd_stderr = fd_stderr[0];
5595 + fpm_event_add(child->fd_stdout, &child->ev_stdout, fpm_stdio_child_said, child);
5596 + fpm_event_add(child->fd_stderr, &child->ev_stderr, fpm_stdio_child_said, child);
5601 +int fpm_stdio_discard_pipes(struct fpm_child_s *child)
5603 + if (0 == child->wp->config->catch_workers_output) { /* not required */
5607 + close(fd_stdout[1]);
5608 + close(fd_stderr[1]);
5610 + close(fd_stdout[0]);
5611 + close(fd_stderr[0]);
5616 +void fpm_stdio_child_use_pipes(struct fpm_child_s *child)
5618 + if (child->wp->config->catch_workers_output) {
5619 + dup2(fd_stdout[1], STDOUT_FILENO);
5620 + dup2(fd_stderr[1], STDERR_FILENO);
5621 + close(fd_stdout[0]); close(fd_stdout[1]);
5622 + close(fd_stderr[0]); close(fd_stderr[1]);
5625 + /* stdout of parent is always /dev/null */
5626 + dup2(STDOUT_FILENO, STDERR_FILENO);
5630 +int fpm_stdio_open_error_log(int reopen)
5634 + fd = open(fpm_global_options.error_log, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
5637 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(\"%s\") failed", fpm_global_options.error_log);
5642 + if (fpm_global_options.daemonize) {
5643 + dup2(fd, STDERR_FILENO);
5646 + dup2(fd, fpm_globals.error_log_fd);
5648 + fd = fpm_globals.error_log_fd; /* for FD_CLOSEXEC to work */
5651 + fpm_globals.error_log_fd = fd;
5654 + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
5658 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_stdio.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_stdio.h
5659 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_stdio.h 1970-01-01 03:00:00.000000000 +0300
5660 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_stdio.h 2008-05-24 21:38:47.000000000 +0400
5664 + /* (c) 2007,2008 Andrei Nigmatulin */
5666 +#ifndef FPM_STDIO_H
5667 +#define FPM_STDIO_H 1
5669 +#include "fpm_worker_pool.h"
5671 +int fpm_stdio_init_main();
5672 +int fpm_stdio_init_final();
5673 +int fpm_stdio_init_child(struct fpm_worker_pool_s *wp);
5674 +int fpm_stdio_prepare_pipes(struct fpm_child_s *child);
5675 +void fpm_stdio_child_use_pipes(struct fpm_child_s *child);
5676 +int fpm_stdio_parent_use_pipes(struct fpm_child_s *child);
5677 +int fpm_stdio_discard_pipes(struct fpm_child_s *child);
5678 +int fpm_stdio_open_error_log(int reopen);
5682 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_str.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_str.h
5683 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_str.h 1970-01-01 03:00:00.000000000 +0300
5684 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_str.h 2008-05-24 21:38:47.000000000 +0400
5688 + /* (c) 2007,2008 Andrei Nigmatulin */
5691 +#define FPM_STR_H 1
5693 +static inline char *cpystrn(char *dst, const char *src, size_t dst_size)
5697 + if (!dst_size) return dst;
5700 + end = dst + dst_size - 1;
5702 + for (; d < end; ++d, ++src) {
5703 + if (!(*d = *src)) {
5713 +static inline char *str_purify_filename(char *dst, char *src, size_t size)
5718 + end = dst + size - 1;
5720 + for (; d < end && *src; ++d, ++src) {
5721 + if (* (unsigned char *) src < ' ' || * (unsigned char *) src > '\x7f') {
5735 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace.c
5736 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace.c 1970-01-01 03:00:00.000000000 +0300
5737 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace.c 2008-07-21 00:59:00.000000000 +0400
5741 + /* (c) 2007,2008 Andrei Nigmatulin */
5743 +#include "fpm_config.h"
5745 +#include <sys/types.h>
5747 +#include "fpm_trace.h"
5749 +int fpm_trace_get_strz(char *buf, size_t sz, long addr)
5753 + char *lc = (char *) &l;
5755 + if (0 > fpm_trace_get_long(addr, &l)) {
5759 + i = l % SIZEOF_LONG;
5763 + for (addr = l; ; addr += SIZEOF_LONG) {
5765 + if (0 > fpm_trace_get_long(addr, &l)) {
5769 + for ( ; i < SIZEOF_LONG; i++) {
5772 + if (sz && lc[i]) {
5785 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace.h
5786 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace.h 1970-01-01 03:00:00.000000000 +0300
5787 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace.h 2008-07-21 07:04:25.000000000 +0400
5791 + /* (c) 2007,2008 Andrei Nigmatulin */
5793 +#ifndef FPM_TRACE_H
5794 +#define FPM_TRACE_H 1
5796 +#include <unistd.h>
5798 +int fpm_trace_signal(pid_t pid);
5799 +int fpm_trace_ready(pid_t pid);
5800 +int fpm_trace_close(pid_t pid);
5801 +int fpm_trace_get_long(long addr, long *data);
5802 +int fpm_trace_get_strz(char *buf, size_t sz, long addr);
5806 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_mach.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_mach.c
5807 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_mach.c 1970-01-01 03:00:00.000000000 +0300
5808 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_mach.c 2008-08-26 19:09:15.000000000 +0400
5812 + /* (c) 2007,2008 Andrei Nigmatulin */
5814 +#include "fpm_config.h"
5816 +#include <mach/mach.h>
5817 +#include <mach/mach_vm.h>
5819 +#include <unistd.h>
5821 +#include "fpm_trace.h"
5822 +#include "fpm_process_ctl.h"
5823 +#include "fpm_unix.h"
5827 +static mach_port_name_t target;
5828 +static vm_offset_t target_page_base;
5829 +static vm_offset_t local_page;
5830 +static mach_msg_type_number_t local_size;
5832 +static void fpm_mach_vm_deallocate()
5835 + mach_vm_deallocate(mach_task_self(), local_page, local_size);
5836 + target_page_base = 0;
5842 +static int fpm_mach_vm_read_page(vm_offset_t page)
5846 + kr = mach_vm_read(target, page, fpm_pagesize, &local_page, &local_size);
5848 + if (kr != KERN_SUCCESS) {
5849 + zlog(ZLOG_STUFF, ZLOG_ERROR, "mach_vm_read() failed: %s (%d)", mach_error_string(kr), kr);
5856 +int fpm_trace_signal(pid_t pid)
5858 + if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) {
5859 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "kill(SIGSTOP) failed");
5866 +int fpm_trace_ready(pid_t pid)
5870 + kr = task_for_pid(mach_task_self(), pid, &target);
5872 + if (kr != KERN_SUCCESS) {
5875 + if (kr == KERN_FAILURE) {
5876 + msg = " It seems that master process does not have enough privileges to trace processes.";
5879 + zlog(ZLOG_STUFF, ZLOG_ERROR, "task_for_pid() failed: %s (%d)%s", mach_error_string(kr), kr, msg);
5886 +int fpm_trace_close(pid_t pid)
5888 + fpm_mach_vm_deallocate();
5895 +int fpm_trace_get_long(long addr, long *data)
5897 + size_t offset = ((uintptr_t) (addr) % fpm_pagesize);
5898 + vm_offset_t base = (uintptr_t) (addr) - offset;
5900 + if (base != target_page_base) {
5901 + fpm_mach_vm_deallocate();
5902 + if (0 > fpm_mach_vm_read_page(base)) {
5907 + *data = * (long *) (local_page + offset);
5912 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_pread.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_pread.c
5913 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_pread.c 1970-01-01 03:00:00.000000000 +0300
5914 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_pread.c 2008-08-26 19:09:15.000000000 +0400
5918 + /* (c) 2007,2008 Andrei Nigmatulin */
5920 +#define _GNU_SOURCE
5921 +#define _FILE_OFFSET_BITS 64
5923 +#include "fpm_config.h"
5925 +#include <unistd.h>
5929 +#include <stdint.h>
5931 +#include "fpm_trace.h"
5932 +#include "fpm_process_ctl.h"
5936 +static int mem_file = -1;
5938 +int fpm_trace_signal(pid_t pid)
5940 + if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) {
5941 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "kill(SIGSTOP) failed");
5948 +int fpm_trace_ready(pid_t pid)
5952 + sprintf(buf, "/proc/%d/" PROC_MEM_FILE, (int) pid);
5954 + mem_file = open(buf, O_RDONLY);
5956 + if (0 > mem_file) {
5957 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(%s) failed", buf);
5964 +int fpm_trace_close(pid_t pid)
5973 +int fpm_trace_get_long(long addr, long *data)
5975 + if (sizeof(*data) != pread(mem_file, (void *) data, sizeof(*data), (uintptr_t) addr)) {
5976 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pread() failed");
5983 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_ptrace.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_ptrace.c
5984 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_trace_ptrace.c 1970-01-01 03:00:00.000000000 +0300
5985 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_trace_ptrace.c 2008-09-19 03:34:11.000000000 +0400
5989 + /* (c) 2007,2008 Andrei Nigmatulin */
5991 +#include "fpm_config.h"
5993 +#include <sys/wait.h>
5994 +#include <sys/ptrace.h>
5995 +#include <unistd.h>
5998 +#if defined(PT_ATTACH) && !defined(PTRACE_ATTACH)
5999 +#define PTRACE_ATTACH PT_ATTACH
6002 +#if defined(PT_DETACH) && !defined(PTRACE_DETACH)
6003 +#define PTRACE_DETACH PT_DETACH
6006 +#if defined(PT_READ_D) && !defined(PTRACE_PEEKDATA)
6007 +#define PTRACE_PEEKDATA PT_READ_D
6010 +#include "fpm_trace.h"
6013 +static pid_t traced_pid;
6015 +int fpm_trace_signal(pid_t pid)
6017 + if (0 > ptrace(PTRACE_ATTACH, pid, 0, 0)) {
6018 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(ATTACH) failed");
6025 +int fpm_trace_ready(pid_t pid)
6032 +int fpm_trace_close(pid_t pid)
6034 + if (0 > ptrace(PTRACE_DETACH, pid, (void *) 1, 0)) {
6035 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(DETACH) failed");
6044 +int fpm_trace_get_long(long addr, long *data)
6047 + struct ptrace_io_desc ptio = {
6048 + .piod_op = PIOD_READ_D,
6049 + .piod_offs = (void *) addr,
6050 + .piod_addr = (void *) data,
6051 + .piod_len = sizeof(long)
6054 + if (0 > ptrace(PT_IO, traced_pid, (void *) &ptio, 0)) {
6055 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(PT_IO) failed");
6061 + *data = ptrace(PTRACE_PEEKDATA, traced_pid, (void *) addr, 0);
6064 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(PEEKDATA) failed");
6072 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_unix.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_unix.c
6073 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_unix.c 1970-01-01 03:00:00.000000000 +0300
6074 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_unix.c 2008-09-19 03:19:59.000000000 +0400
6078 + /* (c) 2007,2008 Andrei Nigmatulin */
6080 +#include "fpm_config.h"
6082 +#include <string.h>
6083 +#include <sys/time.h>
6084 +#include <sys/resource.h>
6085 +#include <stdlib.h>
6086 +#include <unistd.h>
6087 +#include <sys/types.h>
6092 +#include <sys/prctl.h>
6096 +#include "fpm_conf.h"
6097 +#include "fpm_cleanup.h"
6098 +#include "fpm_clock.h"
6099 +#include "fpm_stdio.h"
6100 +#include "fpm_unix.h"
6103 +size_t fpm_pagesize;
6105 +int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp)
6107 + struct fpm_listen_options_s *lo = wp->config->listen_options;
6109 + /* uninitialized */
6110 + wp->socket_uid = -1;
6111 + wp->socket_gid = -1;
6112 + wp->socket_mode = 0666;
6114 + if (!lo) return 0;
6116 + if (lo->owner && *lo->owner) {
6117 + struct passwd *pwd;
6119 + pwd = getpwnam(lo->owner);
6122 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "cannot get uid for user '%s', pool '%s'", lo->owner, wp->config->name);
6126 + wp->socket_uid = pwd->pw_uid;
6127 + wp->socket_gid = pwd->pw_gid;
6130 + if (lo->group && *lo->group) {
6131 + struct group *grp;
6133 + grp = getgrnam(lo->group);
6136 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "cannot get gid for group '%s', pool '%s'", lo->group, wp->config->name);
6140 + wp->socket_gid = grp->gr_gid;
6143 + if (lo->mode && *lo->mode) {
6144 + wp->socket_mode = strtoul(lo->mode, 0, 8);
6150 +static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp)
6152 + int is_root = !geteuid();
6155 + if (wp->config->user && *wp->config->user) {
6157 + if (strlen(wp->config->user) == strspn(wp->config->user, "0123456789")) {
6158 + wp->set_uid = strtoul(wp->config->user, 0, 10);
6161 + struct passwd *pwd;
6163 + pwd = getpwnam(wp->config->user);
6166 + zlog(ZLOG_STUFF, ZLOG_ERROR, "cannot get uid for user '%s', pool '%s'", wp->config->user, wp->config->name);
6170 + wp->set_uid = pwd->pw_uid;
6171 + wp->set_gid = pwd->pw_gid;
6173 + wp->user = strdup(pwd->pw_name);
6174 + wp->home = strdup(pwd->pw_dir);
6178 + if (wp->config->group && *wp->config->group) {
6180 + if (strlen(wp->config->group) == strspn(wp->config->group, "0123456789")) {
6181 + wp->set_gid = strtoul(wp->config->group, 0, 10);
6184 + struct group *grp;
6186 + grp = getgrnam(wp->config->group);
6189 + zlog(ZLOG_STUFF, ZLOG_ERROR, "cannot get gid for group '%s', pool '%s'", wp->config->group, wp->config->name);
6193 + wp->set_gid = grp->gr_gid;
6197 +#ifndef I_REALLY_WANT_ROOT_PHP
6198 + if (wp->set_uid == 0 || wp->set_gid == 0) {
6199 + zlog(ZLOG_STUFF, ZLOG_ERROR, "please specify user and group other than root, pool '%s'", wp->config->name);
6204 + else { /* not root */
6205 + if (wp->config->user && *wp->config->user) {
6206 + zlog(ZLOG_STUFF, ZLOG_WARNING, "'user' directive is ignored, pool '%s'", wp->config->name);
6208 + if (wp->config->group && *wp->config->group) {
6209 + zlog(ZLOG_STUFF, ZLOG_WARNING, "'group' directive is ignored, pool '%s'", wp->config->name);
6211 + if (wp->config->chroot && *wp->config->chroot) {
6212 + zlog(ZLOG_STUFF, ZLOG_WARNING, "'chroot' directive is ignored, pool '%s'", wp->config->name);
6215 + { /* set up HOME and USER anyway */
6216 + struct passwd *pwd;
6218 + pwd = getpwuid(getuid());
6221 + wp->user = strdup(pwd->pw_name);
6222 + wp->home = strdup(pwd->pw_dir);
6230 +int fpm_unix_init_child(struct fpm_worker_pool_s *wp)
6232 + int is_root = !geteuid();
6233 + int made_chroot = 0;
6235 + if (wp->config->rlimit_files) {
6238 + getrlimit(RLIMIT_NOFILE, &r);
6240 + r.rlim_cur = (rlim_t) wp->config->rlimit_files;
6242 + if (0 > setrlimit(RLIMIT_NOFILE, &r)) {
6243 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setrlimit(RLIMIT_NOFILE) failed");
6247 + if (wp->config->rlimit_core) {
6250 + getrlimit(RLIMIT_CORE, &r);
6252 + r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core;
6254 + if (0 > setrlimit(RLIMIT_CORE, &r)) {
6255 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setrlimit(RLIMIT_CORE) failed");
6259 + if (is_root && wp->config->chroot && *wp->config->chroot) {
6260 + if (0 > chroot(wp->config->chroot)) {
6261 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chroot(%s) failed", wp->config->chroot);
6267 + if (wp->config->chdir && *wp->config->chdir) {
6268 + if (0 > chdir(wp->config->chdir)) {
6269 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chdir(%s) failed", wp->config->chdir);
6273 + else if (made_chroot) {
6278 + if (wp->set_gid) {
6279 + if (0 > setgid(wp->set_gid)) {
6280 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setgid(%d) failed", wp->set_gid);
6284 + if (wp->set_uid) {
6285 + if (0 > initgroups(wp->config->user, wp->set_gid)) {
6286 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "initgroups(%s, %d) failed", wp->config->user, wp->set_gid);
6289 + if (0 > setuid(wp->set_uid)) {
6290 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "setuid(%d) failed", wp->set_uid);
6297 + if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) {
6298 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "prctl(PR_SET_DUMPABLE) failed");
6302 + if (0 > fpm_clock_init()) {
6309 +int fpm_unix_init_main()
6311 + struct fpm_worker_pool_s *wp;
6313 + fpm_pagesize = getpagesize();
6315 + if (fpm_global_options.daemonize) {
6321 + zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fork() failed");
6330 + fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT);
6339 + if (0 > fpm_clock_init()) {
6343 + fpm_globals.parent_pid = getpid();
6345 + for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
6347 + if (0 > fpm_unix_conf_wp(wp)) {
6353 + fpm_stdio_init_final();
6357 + getrlimit(RLIMIT_NOFILE, &r);
6359 + zlog(ZLOG_STUFF, ZLOG_NOTICE, "getrlimit(nofile): max:%lld, cur:%lld",
6360 + (long long) r.rlim_max, (long long) r.rlim_cur);
6365 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_unix.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_unix.h
6366 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_unix.h 1970-01-01 03:00:00.000000000 +0300
6367 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_unix.h 2008-05-25 17:21:13.000000000 +0400
6371 + /* (c) 2007,2008 Andrei Nigmatulin */
6374 +#define FPM_UNIX_H 1
6376 +#include "fpm_worker_pool.h"
6378 +int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp);
6379 +int fpm_unix_init_child(struct fpm_worker_pool_s *wp);
6380 +int fpm_unix_init_main();
6382 +extern size_t fpm_pagesize;
6386 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_worker_pool.c php-5.2.6.fpm/sapi/cgi/fpm/fpm_worker_pool.c
6387 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_worker_pool.c 1970-01-01 03:00:00.000000000 +0300
6388 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_worker_pool.c 2008-08-26 19:09:15.000000000 +0400
6392 + /* (c) 2007,2008 Andrei Nigmatulin */
6394 +#include "fpm_config.h"
6396 +#include <string.h>
6397 +#include <stdlib.h>
6398 +#include <unistd.h>
6400 +#include "fpm_worker_pool.h"
6401 +#include "fpm_cleanup.h"
6402 +#include "fpm_children.h"
6403 +#include "fpm_shm.h"
6404 +#include "fpm_shm_slots.h"
6405 +#include "fpm_conf.h"
6407 +struct fpm_worker_pool_s *fpm_worker_all_pools;
6409 +static void fpm_worker_pool_cleanup(int which, void *arg)
6411 + struct fpm_worker_pool_s *wp, *wp_next;
6413 + for (wp = fpm_worker_all_pools; wp; wp = wp_next) {
6414 + wp_next = wp->next;
6415 + fpm_worker_pool_config_free(wp->config);
6416 + fpm_children_free(wp->children);
6417 + fpm_array_free(&wp->slots_used);
6418 + fpm_array_free(&wp->slots_free);
6419 + fpm_shm_free_list(wp->shm_list, which == FPM_CLEANUP_CHILD ? fpm_shm_slots_mem() : 0);
6426 + fpm_worker_all_pools = 0;
6429 +struct fpm_worker_pool_s *fpm_worker_pool_alloc()
6431 + struct fpm_worker_pool_s *ret;
6433 + ret = malloc(sizeof(struct fpm_worker_pool_s));
6439 + memset(ret, 0, sizeof(struct fpm_worker_pool_s));
6441 + if (!fpm_worker_all_pools) {
6442 + fpm_worker_all_pools = ret;
6445 + fpm_array_init(&ret->slots_used, sizeof(struct fpm_shm_slot_ptr_s), 50);
6446 + fpm_array_init(&ret->slots_free, sizeof(struct fpm_shm_slot_ptr_s), 50);
6451 +int fpm_worker_pool_init_main()
6453 + fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_worker_pool_cleanup, 0);
6457 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/fpm_worker_pool.h php-5.2.6.fpm/sapi/cgi/fpm/fpm_worker_pool.h
6458 --- php-5.2.6.vanilla/sapi/cgi/fpm/fpm_worker_pool.h 1970-01-01 03:00:00.000000000 +0300
6459 +++ php-5.2.6.fpm/sapi/cgi/fpm/fpm_worker_pool.h 2008-08-26 19:09:15.000000000 +0400
6463 + /* (c) 2007,2008 Andrei Nigmatulin */
6465 +#ifndef FPM_WORKER_POOL_H
6466 +#define FPM_WORKER_POOL_H 1
6468 +#include "fpm_conf.h"
6469 +#include "fpm_arrays.h"
6471 +struct fpm_worker_pool_s;
6472 +struct fpm_child_s;
6473 +struct fpm_child_stat_s;
6476 +enum fpm_address_domain {
6481 +struct fpm_worker_pool_s {
6482 + struct fpm_worker_pool_s *next;
6483 + struct fpm_worker_pool_config_s *config;
6484 + char *user, *home; /* for setting env USER and HOME */
6485 + enum fpm_address_domain listen_address_domain;
6486 + int listening_socket;
6487 + int set_uid, set_gid; /* config uid and gid */
6488 + unsigned is_template:1; /* just config template, no processes will be created */
6489 + int socket_uid, socket_gid, socket_mode;
6491 + struct fpm_shm_s *shm_list;
6492 + struct fpm_array_s slots_used;
6493 + struct fpm_array_s slots_free;
6496 + struct fpm_child_s *children;
6497 + int running_children;
6500 +struct fpm_worker_pool_s *fpm_worker_pool_alloc();
6501 +int fpm_worker_pool_init_main();
6503 +extern struct fpm_worker_pool_s *fpm_worker_all_pools;
6507 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/init.d/php-fpm.in php-5.2.6.fpm/sapi/cgi/fpm/init.d/php-fpm.in
6508 --- php-5.2.6.vanilla/sapi/cgi/fpm/init.d/php-fpm.in 1970-01-01 03:00:00.000000000 +0300
6509 +++ php-5.2.6.fpm/sapi/cgi/fpm/init.d/php-fpm.in 2008-08-05 20:31:27.000000000 +0400
6513 +php_fpm_BIN=@prefix@/bin/php-cgi
6514 +php_fpm_CONF=@php_fpm_conf_path@
6515 +php_fpm_PID=@php_fpm_pid_path@
6518 +php_opts="--fpm-config $php_fpm_CONF"
6524 + while test $try -lt 35 ; do
6528 + if [ -f "$2" ] ; then
6535 + if [ ! -f "$2" ] ; then
6543 + try=`expr $try + 1`
6552 + echo -n "Starting php_fpm "
6554 + $php_fpm_BIN --fpm $php_opts
6556 + if [ "$?" != 0 ] ; then
6561 + wait_for_pid created $php_fpm_PID
6563 + if [ -n "$try" ] ; then
6572 + echo -n "Shutting down php_fpm "
6574 + if [ ! -r $php_fpm_PID ] ; then
6575 + echo "warning, no pid file found - php-fpm is not running ?"
6579 + kill -TERM `cat $php_fpm_PID`
6581 + wait_for_pid removed $php_fpm_PID
6583 + if [ -n "$try" ] ; then
6592 + echo -n "Gracefully shutting down php_fpm "
6594 + if [ ! -r $php_fpm_PID ] ; then
6595 + echo "warning, no pid file found - php-fpm is not running ?"
6599 + kill -QUIT `cat $php_fpm_PID`
6601 + wait_for_pid removed $php_fpm_PID
6603 + if [ -n "$try" ] ; then
6618 + echo -n "Reload service php-fpm "
6620 + if [ ! -r $php_fpm_PID ] ; then
6621 + echo "warning, no pid file found - php-fpm is not running ?"
6625 + kill -USR2 `cat $php_fpm_PID`
6632 + echo -n "Re-opening php-fpm log file "
6634 + if [ ! -r $php_fpm_PID ] ; then
6635 + echo "warning, no pid file found - php-fpm is not running ?"
6639 + kill -USR1 `cat $php_fpm_PID`
6645 + echo "Usage: $0 {start|stop|quit|restart|reload|logrotate}"
6650 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/Makefile.frag php-5.2.6.fpm/sapi/cgi/fpm/Makefile.frag
6651 --- php-5.2.6.vanilla/sapi/cgi/fpm/Makefile.frag 1970-01-01 03:00:00.000000000 +0300
6652 +++ php-5.2.6.fpm/sapi/cgi/fpm/Makefile.frag 2008-03-28 16:51:22.000000000 +0300
6655 +install-fpm: sapi/cgi/fpm/php-fpm.conf sapi/cgi/fpm/php-fpm
6656 + @echo "Installing FPM config: $(INSTALL_ROOT)$(php_fpm_conf_path)"
6657 + -@$(mkinstalldirs) \
6658 + $(INSTALL_ROOT)$(prefix)/sbin \
6659 + `dirname "$(INSTALL_ROOT)$(php_fpm_conf_path)"` \
6660 + `dirname "$(INSTALL_ROOT)$(php_fpm_log_path)"` \
6661 + `dirname "$(INSTALL_ROOT)$(php_fpm_pid_path)"`
6662 + -@if test -r "$(INSTALL_ROOT)$(php_fpm_conf_path)" ; then \
6663 + dest=`basename "$(php_fpm_conf_path)"`.default ; \
6664 + echo " (installing as $$dest)" ; \
6666 + dest=`basename "$(php_fpm_conf_path)"` ; \
6668 + $(INSTALL_DATA) $(top_builddir)/sapi/cgi/fpm/php-fpm.conf $(INSTALL_ROOT)`dirname "$(php_fpm_conf_path)"`/$$dest
6669 + @echo "Installing init.d script: $(INSTALL_ROOT)$(prefix)/sbin/php-fpm"
6670 + -@$(INSTALL) -m 0755 $(top_builddir)/sapi/cgi/fpm/php-fpm $(INSTALL_ROOT)$(prefix)/sbin/php-fpm
6672 +$(top_builddir)/libevent/libevent.a: $(top_builddir)/libevent/Makefile
6673 + cd $(top_builddir)/libevent && $(MAKE) libevent.a
6675 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/xml_config.c php-5.2.6.fpm/sapi/cgi/fpm/xml_config.c
6676 --- php-5.2.6.vanilla/sapi/cgi/fpm/xml_config.c 1970-01-01 03:00:00.000000000 +0300
6677 +++ php-5.2.6.fpm/sapi/cgi/fpm/xml_config.c 2008-08-26 19:09:15.000000000 +0400
6681 + /* (c) 2004-2007 Andrei Nigmatulin */
6683 +#include "fpm_config.h"
6685 +#ifdef HAVE_ALLOCA_H
6686 +#include <alloca.h>
6688 +#include <string.h>
6690 +#include <stddef.h>
6691 +#include <stdlib.h>
6693 +#include <libxml/parser.h>
6694 +#include <libxml/tree.h>
6696 +#include "xml_config.h"
6698 +static struct xml_conf_section **xml_conf_sections = 0;
6699 +static int xml_conf_sections_allocated = 0;
6700 +static int xml_conf_sections_used = 0;
6702 +char *xml_conf_set_slot_boolean(void **conf, char *name, void *vv, intptr_t offset)
6705 + long value_y = !strcasecmp(value, "yes") || !strcmp(value, "1") || !strcasecmp(value, "on");
6706 + long value_n = !strcasecmp(value, "no") || !strcmp(value, "0") || !strcasecmp(value, "off");
6708 + if (!value_y && !value_n) {
6709 + return "xml_conf_set_slot(): invalid boolean value";
6712 +#ifdef XML_CONF_DEBUG
6713 + fprintf(stderr, "setting boolean '%s' => %s\n", name, value_y ? "TRUE" : "FALSE");
6716 + * (int *) ((char *) *conf + offset) = value_y ? 1 : 0;
6721 +char *xml_conf_set_slot_string(void **conf, char *name, void *vv, intptr_t offset)
6724 + char *v = strdup(value);
6726 + if (!v) return "xml_conf_set_slot_string(): strdup() failed";
6728 +#ifdef XML_CONF_DEBUG
6729 + fprintf(stderr, "setting string '%s' => '%s'\n", name, v);
6732 + * (char **) ((char *) *conf + offset) = v;
6737 +char *xml_conf_set_slot_integer(void **conf, char *name, void *vv, intptr_t offset)
6740 + int v = atoi(value);
6742 + * (int *) ((char *) *conf + offset) = v;
6744 +#ifdef XML_CONF_DEBUG
6745 + fprintf(stderr, "setting integer '%s' => %d\n", name, v);
6751 +char *xml_conf_set_slot_time(void **conf, char *name, void *vv, intptr_t offset)
6754 + int len = strlen(value);
6758 + if (!len) return "xml_conf_set_slot_timeval(): invalid timeval value";
6760 + suffix = value[len-1];
6762 + value[len-1] = '\0';
6766 + seconds = atoi(value);
6769 + seconds = 60 * atoi(value);
6772 + seconds = 60 * 60 * atoi(value);
6775 + seconds = 24 * 60 * 60 * atoi(value);
6778 + return "xml_conf_set_slot_timeval(): unknown suffix used in timeval value";
6781 + * (int *) ((char *) *conf + offset) = seconds;
6783 +#ifdef XML_CONF_DEBUG
6784 + fprintf(stderr, "setting time '%s' => %d:%02d:%02d:%02d\n", name, expand_dhms(seconds));
6790 +char *xml_conf_parse_section(void **conf, struct xml_conf_section *section, void *xml_node)
6792 + xmlNode *element = xml_node;
6795 +#ifdef XML_CONF_DEBUG
6796 + fprintf(stderr, "processing a section %s\n", section->path);
6799 + for ( ; element; element = element->next) {
6800 + if (element->type == XML_ELEMENT_NODE && !strcmp((const char *) element->name, "value") && element->children) {
6801 + xmlChar *name = xmlGetProp(element, (unsigned char *) "name");
6806 +#ifdef XML_CONF_DEBUG
6807 + fprintf(stderr, "found a value: %s\n", name);
6809 + for (i = 0; section->parsers[i].parser; i++) {
6810 + if (!section->parsers[i].name || !strcmp(section->parsers[i].name, (char *) name)) {
6815 + if (section->parsers[i].parser) {
6816 + if (section->parsers[i].type == XML_CONF_SCALAR) {
6817 + if (element->children->type == XML_TEXT_NODE) {
6818 + ret = section->parsers[i].parser(conf, (char *) name, element->children->content, section->parsers[i].offset);
6821 + ret = "XML_TEXT_NODE is expected, something different is given";
6825 + ret = section->parsers[i].parser(conf, (char *) name, element->children, section->parsers[i].offset);
6829 + if (ret) return ret;
6833 + fprintf(stderr, "Warning, unknown setting '%s' in section '%s'\n", (char *) name, section->path);
6843 +static char *xml_conf_parse_file(xmlNode *element)
6847 + for ( ; element; element = element->next) {
6849 + if (element->parent && element->type == XML_ELEMENT_NODE && !strcmp((const char *) element->name, "section")) {
6850 + xmlChar *name = xmlGetProp(element, (unsigned char *) "name");
6853 + char *parent_name = (char *) xmlGetNodePath(element->parent);
6856 + struct xml_conf_section *section = NULL;
6858 +#ifdef XML_CONF_DEBUG
6859 + fprintf(stderr, "got a section: %s/%s\n", parent_name, name);
6861 + full_name = alloca(strlen(parent_name) + strlen((char *) name) + 1 + 1);
6863 + sprintf(full_name, "%s/%s", parent_name, (char *) name);
6865 + xmlFree(parent_name);
6868 + for (i = 0; i < xml_conf_sections_used; i++) {
6869 + if (!strcmp(xml_conf_sections[i]->path, full_name)) {
6870 + section = xml_conf_sections[i];
6874 + if (section) { /* found a registered section */
6875 + void *conf = section->conf();
6876 + ret = xml_conf_parse_section(&conf, section, element->children);
6883 + if (element->children) {
6884 + ret = xml_conf_parse_file(element->children);
6892 +char *xml_conf_load_file(char *file)
6897 + LIBXML_TEST_VERSION
6899 + doc = xmlParseFile(file);
6902 + ret = xml_conf_parse_file(doc->children);
6906 + ret = "failed to parse conf file";
6909 + xmlCleanupParser();
6913 +int xml_conf_init()
6918 +void xml_conf_clean()
6920 + if (xml_conf_sections) {
6921 + free(xml_conf_sections);
6925 +int xml_conf_section_register(struct xml_conf_section *section)
6927 + if (xml_conf_sections_allocated == xml_conf_sections_used) {
6928 + int new_size = xml_conf_sections_used + 10;
6929 + void *new_ptr = realloc(xml_conf_sections, sizeof(struct xml_conf_section *) * new_size);
6932 + xml_conf_sections = new_ptr;
6933 + xml_conf_sections_allocated = new_size;
6936 + fprintf(stderr, "xml_conf_section_register(): out of memory\n");
6941 + xml_conf_sections[xml_conf_sections_used++] = section;
6946 +int xml_conf_sections_register(struct xml_conf_section *sections[])
6948 + for ( ; sections && *sections; sections++) {
6949 + if (0 > xml_conf_section_register(*sections)) {
6957 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/xml_config.h php-5.2.6.fpm/sapi/cgi/fpm/xml_config.h
6958 --- php-5.2.6.vanilla/sapi/cgi/fpm/xml_config.h 1970-01-01 03:00:00.000000000 +0300
6959 +++ php-5.2.6.fpm/sapi/cgi/fpm/xml_config.h 2008-09-19 03:02:58.000000000 +0400
6963 + /* (c) 2004-2007 Andrei Nigmatulin */
6965 +#ifndef XML_CONFIG_H
6966 +#define XML_CONFIG_H 1
6968 +#include <stdint.h>
6970 +struct xml_value_parser;
6972 +struct xml_value_parser {
6975 + char *(*parser)(void **, char *, void *, intptr_t offset);
6979 +struct xml_conf_section {
6982 + struct xml_value_parser *parsers;
6985 +char *xml_conf_set_slot_boolean(void **conf, char *name, void *value, intptr_t offset);
6986 +char *xml_conf_set_slot_string(void **conf, char *name, void *value, intptr_t offset);
6987 +char *xml_conf_set_slot_integer(void **conf, char *name, void *value, intptr_t offset);
6988 +char *xml_conf_set_slot_time(void **conf, char *name, void *value, intptr_t offset);
6990 +int xml_conf_init();
6991 +void xml_conf_clean();
6992 +char *xml_conf_load_file(char *file);
6993 +char *xml_conf_parse_section(void **conf, struct xml_conf_section *section, void *ve);
6994 +int xml_conf_section_register(struct xml_conf_section *section);
6995 +int xml_conf_sections_register(struct xml_conf_section *sections[]);
6997 +#define expand_hms(value) (value) / 3600, ((value) % 3600) / 60, (value) % 60
6999 +#define expand_dhms(value) (value) / 86400, ((value) % 86400) / 3600, ((value) % 3600) / 60, (value) % 60
7001 +enum { XML_CONF_SCALAR = 1, XML_CONF_SUBSECTION = 2 };
7004 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/zlog.c php-5.2.6.fpm/sapi/cgi/fpm/zlog.c
7005 --- php-5.2.6.vanilla/sapi/cgi/fpm/zlog.c 1970-01-01 03:00:00.000000000 +0300
7006 +++ php-5.2.6.fpm/sapi/cgi/fpm/zlog.c 2008-05-23 01:08:32.000000000 +0400
7010 + /* (c) 2004-2007 Andrei Nigmatulin */
7012 +#include "fpm_config.h"
7015 +#include <unistd.h>
7017 +#include <string.h>
7018 +#include <stdarg.h>
7019 +#include <sys/time.h>
7024 +#define MAX_LINE_LENGTH 1024
7026 +static int zlog_fd = -1;
7027 +static int zlog_level = ZLOG_NOTICE;
7029 +static const char *level_names[] = {
7030 + [ZLOG_DEBUG] = "DEBUG",
7031 + [ZLOG_NOTICE] = "NOTICE",
7032 + [ZLOG_WARNING] = "WARNING",
7033 + [ZLOG_ERROR] = "ERROR",
7034 + [ZLOG_ALERT] = "ALERT",
7037 +size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len)
7042 + len = strftime(timebuf, timebuf_len, "%b %d %H:%M:%S", localtime_r((const time_t *) &tv->tv_sec, &t));
7043 + len += snprintf(timebuf + len, timebuf_len - len, ".%06d", (int) tv->tv_usec);
7048 +int zlog_set_fd(int new_fd)
7050 + int old_fd = zlog_fd;
7056 +int zlog_set_level(int new_value)
7058 + int old_value = zlog_level;
7060 + zlog_level = new_value;
7065 +void zlog(const char *function, int line, int flags, const char *fmt, ...)
7067 + struct timeval tv;
7068 + char buf[MAX_LINE_LENGTH];
7069 + const size_t buf_size = MAX_LINE_LENGTH;
7072 + int truncated = 0;
7075 + if ((flags & ZLOG_LEVEL_MASK) < zlog_level) {
7079 + saved_errno = errno;
7081 + gettimeofday(&tv, 0);
7083 + len = zlog_print_time(&tv, buf, buf_size);
7085 + len += snprintf(buf + len, buf_size - len, " [%s] %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line);
7087 + if (len > buf_size - 1) {
7092 + va_start(args, fmt);
7094 + len += vsnprintf(buf + len, buf_size - len, fmt, args);
7098 + if (len >= buf_size) {
7104 + if (flags & ZLOG_HAVE_ERRNO) {
7105 + len += snprintf(buf + len, buf_size - len, ": %s (%d)", strerror(saved_errno), saved_errno);
7106 + if (len >= buf_size) {
7113 + memcpy(buf + buf_size - sizeof("..."), "...", sizeof("...") - 1);
7114 + len = buf_size - 1;
7117 + buf[len++] = '\n';
7119 + write(zlog_fd > -1 ? zlog_fd : STDERR_FILENO, buf, len);
7121 diff -Nru php-5.2.6.vanilla/sapi/cgi/fpm/zlog.h php-5.2.6.fpm/sapi/cgi/fpm/zlog.h
7122 --- php-5.2.6.vanilla/sapi/cgi/fpm/zlog.h 1970-01-01 03:00:00.000000000 +0300
7123 +++ php-5.2.6.fpm/sapi/cgi/fpm/zlog.h 2008-05-23 01:08:32.000000000 +0400
7127 + /* (c) 2004-2007 Andrei Nigmatulin */
7132 +#define ZLOG_STUFF __func__, __LINE__
7136 +int zlog_set_fd(int new_fd);
7137 +int zlog_set_level(int new_value);
7139 +size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len);
7141 +void zlog(const char *function, int line, int flags, const char *fmt, ...)
7142 + __attribute__ ((format(printf,4,5)));
7152 +#define ZLOG_LEVEL_MASK 7
7154 +#define ZLOG_HAVE_ERRNO 0x100
7156 +#define ZLOG_SYSERROR (ZLOG_ERROR | ZLOG_HAVE_ERRNO)
7159 diff -Nru php-5.2.6.vanilla/sapi/cgi/Makefile.frag php-5.2.6.fpm/sapi/cgi/Makefile.frag
7160 --- php-5.2.6.vanilla/sapi/cgi/Makefile.frag 2003-07-02 05:08:26.000000000 +0400
7161 +++ php-5.2.6.fpm/sapi/cgi/Makefile.frag 2008-05-01 20:42:06.000000000 +0400
7163 -$(SAPI_CGI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
7164 +$(SAPI_CGI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(SAPI_EXTRA_DEPS)