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