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