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