summaryrefslogtreecommitdiff
path: root/sapi
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2012-01-11 15:43:42 +0100
committerOndřej Surý <ondrej@sury.org>2012-01-11 15:43:42 +0100
commit8f1428d29ef91d74b4d272af171675f2971eb15b (patch)
treea1f4f4d7dc5bfe8096806dd5c5266634e19fa07a /sapi
parentc6e4182351e0173fe58de141e143aac2eacf5efe (diff)
downloadphp-upstream/5.3.9.tar.gz
Imported Upstream version 5.3.9upstream/5.3.9
Diffstat (limited to 'sapi')
-rw-r--r--sapi/aolserver/aolserver.c6
-rw-r--r--sapi/apache/libpre.c4
-rw-r--r--sapi/apache/mod_php5.c6
-rw-r--r--sapi/apache/mod_php5.h4
-rw-r--r--sapi/apache/php_apache.c4
-rw-r--r--sapi/apache/php_apache_http.h4
-rw-r--r--sapi/apache/sapi_apache.c4
-rw-r--r--sapi/apache2filter/apache_config.c4
-rw-r--r--sapi/apache2filter/php_apache.h4
-rw-r--r--sapi/apache2filter/php_functions.c4
-rw-r--r--sapi/apache2filter/sapi_apache2.c6
-rw-r--r--sapi/apache2handler/apache_config.c4
-rw-r--r--sapi/apache2handler/mod_php5.c4
-rw-r--r--sapi/apache2handler/php_apache.h4
-rw-r--r--sapi/apache2handler/php_functions.c4
-rw-r--r--sapi/apache2handler/sapi_apache2.c6
-rw-r--r--sapi/apache_hooks/mod_php5.c6
-rw-r--r--sapi/apache_hooks/mod_php5.h4
-rw-r--r--sapi/apache_hooks/php_apache.c4
-rw-r--r--sapi/apache_hooks/sapi_apache.c4
-rw-r--r--sapi/caudium/caudium.c6
-rw-r--r--sapi/cgi/cgi_main.c10
-rw-r--r--sapi/cgi/fastcgi.c4
-rw-r--r--sapi/cgi/fastcgi.h4
-rw-r--r--sapi/cli/php_cli.c6
-rw-r--r--sapi/cli/php_cli_readline.c4
-rw-r--r--sapi/cli/php_cli_readline.h4
-rw-r--r--sapi/cli/tests/016.phpt34
-rw-r--r--sapi/cli/tests/021.phpt4
-rw-r--r--sapi/cli/tests/022.phpt2
-rw-r--r--sapi/continuity/capi.c4
-rw-r--r--sapi/embed/php_embed.c4
-rw-r--r--sapi/embed/php_embed.h4
-rw-r--r--sapi/fpm/Makefile.frag4
-rw-r--r--sapi/fpm/config.m4179
-rw-r--r--sapi/fpm/fpm/events/devpoll.c248
-rw-r--r--sapi/fpm/fpm/events/devpoll.h29
-rw-r--r--sapi/fpm/fpm/events/epoll.c211
-rw-r--r--sapi/fpm/fpm/events/epoll.h29
-rw-r--r--sapi/fpm/fpm/events/kqueue.c208
-rw-r--r--sapi/fpm/fpm/events/kqueue.h29
-rw-r--r--sapi/fpm/fpm/events/poll.c276
-rw-r--r--sapi/fpm/fpm/events/poll.h29
-rw-r--r--sapi/fpm/fpm/events/port.c185
-rw-r--r--sapi/fpm/fpm/events/port.h29
-rw-r--r--sapi/fpm/fpm/events/select.c175
-rw-r--r--sapi/fpm/fpm/events/select.h29
-rw-r--r--sapi/fpm/fpm/fastcgi.c54
-rw-r--r--sapi/fpm/fpm/fastcgi.h4
-rw-r--r--sapi/fpm/fpm/fpm.c6
-rw-r--r--sapi/fpm/fpm/fpm.h1
-rw-r--r--sapi/fpm/fpm/fpm_children.c58
-rw-r--r--sapi/fpm/fpm/fpm_cleanup.c1
-rw-r--r--sapi/fpm/fpm/fpm_conf.c578
-rw-r--r--sapi/fpm/fpm/fpm_conf.h56
-rw-r--r--sapi/fpm/fpm/fpm_env.c1
-rw-r--r--sapi/fpm/fpm/fpm_events.c184
-rw-r--r--sapi/fpm/fpm/fpm_events.h20
-rw-r--r--sapi/fpm/fpm/fpm_log.c51
-rw-r--r--sapi/fpm/fpm/fpm_log.h1
-rw-r--r--sapi/fpm/fpm/fpm_main.c300
-rw-r--r--sapi/fpm/fpm/fpm_php.c38
-rw-r--r--sapi/fpm/fpm/fpm_php.h1
-rw-r--r--sapi/fpm/fpm/fpm_php_trace.c2
-rw-r--r--sapi/fpm/fpm/fpm_process_ctl.c73
-rw-r--r--sapi/fpm/fpm/fpm_process_ctl.h6
-rw-r--r--sapi/fpm/fpm/fpm_request.c62
-rw-r--r--sapi/fpm/fpm/fpm_request.h2
-rw-r--r--sapi/fpm/fpm/fpm_scoreboard.c27
-rw-r--r--sapi/fpm/fpm/fpm_scoreboard.h10
-rw-r--r--sapi/fpm/fpm/fpm_shm.c2
-rw-r--r--sapi/fpm/fpm/fpm_signals.c10
-rw-r--r--sapi/fpm/fpm/fpm_sockets.c10
-rw-r--r--sapi/fpm/fpm/fpm_status.c256
-rw-r--r--sapi/fpm/fpm/fpm_stdio.c55
-rw-r--r--sapi/fpm/fpm/fpm_trace_mach.c4
-rw-r--r--sapi/fpm/fpm/fpm_trace_pread.c4
-rw-r--r--sapi/fpm/fpm/fpm_trace_ptrace.c8
-rw-r--r--sapi/fpm/fpm/fpm_unix.c42
-rw-r--r--sapi/fpm/fpm/fpm_worker_pool.c1
-rw-r--r--sapi/fpm/fpm/fpm_worker_pool.h5
-rw-r--r--sapi/fpm/fpm/zlog.c68
-rw-r--r--sapi/fpm/fpm/zlog.h8
-rw-r--r--sapi/fpm/php-fpm.conf.in211
-rw-r--r--sapi/fpm/status.html.in459
-rw-r--r--sapi/isapi/php5isapi.c4
-rw-r--r--sapi/litespeed/lsapi_main.c20
-rw-r--r--sapi/milter/php_milter.c6
-rw-r--r--sapi/nsapi/nsapi.c10
-rw-r--r--sapi/phttpd/php_phttpd.h2
-rw-r--r--sapi/phttpd/phttpd.c2
-rw-r--r--sapi/pi3web/pi3web_sapi.c6
-rw-r--r--sapi/roxen/roxen.c6
-rw-r--r--sapi/thttpd/README2
-rw-r--r--sapi/thttpd/php_thttpd.h2
-rw-r--r--sapi/thttpd/thttpd.c4
-rw-r--r--sapi/tux/README2
-rw-r--r--sapi/tux/php_tux.c2
-rw-r--r--sapi/webjames/php_webjames.h2
-rw-r--r--sapi/webjames/webjames.c2
100 files changed, 3857 insertions, 734 deletions
diff --git a/sapi/aolserver/aolserver.c b/sapi/aolserver/aolserver.c
index fda7364c7..53010e7f5 100644
--- a/sapi/aolserver/aolserver.c
+++ b/sapi/aolserver/aolserver.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -22,7 +22,7 @@
* - CGI/1.1 conformance
*/
-/* $Id: aolserver.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: aolserver.c 321634 2012-01-01 13:15:04Z felipe $ */
/* conflict between PHP and AOLserver headers */
#define Debug php_Debug
@@ -205,7 +205,7 @@ static void php_info_aolserver(ZEND_MODULE_INFO_FUNC_ARGS)
int i;
php_info_print_table_start();
- php_info_print_table_row(2, "SAPI module version", "$Id: aolserver.c 306939 2011-01-01 02:19:59Z felipe $");
+ php_info_print_table_row(2, "SAPI module version", "$Id: aolserver.c 321634 2012-01-01 13:15:04Z felipe $");
php_info_print_table_row(2, "Build date", Ns_InfoBuildDate());
php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile());
php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog());
diff --git a/sapi/apache/libpre.c b/sapi/apache/libpre.c
index 033ea5461..2361db9ab 100644
--- a/sapi/apache/libpre.c
+++ b/sapi/apache/libpre.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: libpre.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: libpre.c 321634 2012-01-01 13:15:04Z felipe $ */
#ifdef NETWARE
diff --git a/sapi/apache/mod_php5.c b/sapi/apache/mod_php5.c
index ebcd69f7f..76139575b 100644
--- a/sapi/apache/mod_php5.c
+++ b/sapi/apache/mod_php5.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -17,7 +17,7 @@
| PHP 4.0 patches by Zeev Suraski <zeev@zend.com> |
+----------------------------------------------------------------------+
*/
-/* $Id: mod_php5.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: mod_php5.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php_apache_http.h"
#include "http_conf_globals.h"
@@ -533,7 +533,7 @@ static void init_request_info(TSRMLS_D)
SG(request_info).request_uri = r->uri;
SG(request_info).request_method = (char *)r->method;
SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE");
- SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
+ SG(request_info).content_length = (content_length ? atol(content_length) : 0);
SG(sapi_headers).http_response_code = r->status;
SG(request_info).proto_num = r->proto_num;
diff --git a/sapi/apache/mod_php5.h b/sapi/apache/mod_php5.h
index 1360731f9..df9dd9dbc 100644
--- a/sapi/apache/mod_php5.h
+++ b/sapi/apache/mod_php5.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -15,7 +15,7 @@
| Author: Rasmus Lerdorf <rasmus@php.net> |
+----------------------------------------------------------------------+
*/
-/* $Id: mod_php5.h 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: mod_php5.h 321634 2012-01-01 13:15:04Z felipe $ */
#ifndef MOD_PHP5_H
#define MOD_PHP5_H
diff --git a/sapi/apache/php_apache.c b/sapi/apache/php_apache.c
index 0f73b848c..d171d56d4 100644
--- a/sapi/apache/php_apache.c
+++ b/sapi/apache/php_apache.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -17,7 +17,7 @@
| David Sklar <sklar@student.net> |
+----------------------------------------------------------------------+
*/
-/* $Id: php_apache.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: php_apache.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php_apache_http.h"
diff --git a/sapi/apache/php_apache_http.h b/sapi/apache/php_apache_http.h
index 693d1b721..aead028db 100644
--- a/sapi/apache/php_apache_http.h
+++ b/sapi/apache/php_apache_http.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_apache_http.h 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: php_apache_http.h 321634 2012-01-01 13:15:04Z felipe $ */
#define NO_REGEX_EXTRA_H
diff --git a/sapi/apache/sapi_apache.c b/sapi/apache/sapi_apache.c
index 13827d648..9b9fa0a6f 100644
--- a/sapi/apache/sapi_apache.c
+++ b/sapi/apache/sapi_apache.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -19,7 +19,7 @@
| Stig Bakken <ssb@php.net> |
+----------------------------------------------------------------------+
*/
-/* $Id: sapi_apache.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: sapi_apache.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php_apache_http.h"
diff --git a/sapi/apache2filter/apache_config.c b/sapi/apache2filter/apache_config.c
index 3b53f010d..301e48058 100644
--- a/sapi/apache2filter/apache_config.c
+++ b/sapi/apache2filter/apache_config.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: apache_config.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: apache_config.c 321634 2012-01-01 13:15:04Z felipe $ */
#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
diff --git a/sapi/apache2filter/php_apache.h b/sapi/apache2filter/php_apache.h
index 72eaa3f17..ebbed1d5c 100644
--- a/sapi/apache2filter/php_apache.h
+++ b/sapi/apache2filter/php_apache.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_apache.h 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: php_apache.h 321634 2012-01-01 13:15:04Z felipe $ */
#ifndef PHP_APACHE_H
#define PHP_APACHE_H
diff --git a/sapi/apache2filter/php_functions.c b/sapi/apache2filter/php_functions.c
index 8b5ba8331..cbb0e4cf8 100644
--- a/sapi/apache2filter/php_functions.c
+++ b/sapi/apache2filter/php_functions.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_functions.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: php_functions.c 321634 2012-01-01 13:15:04Z felipe $ */
#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
diff --git a/sapi/apache2filter/sapi_apache2.c b/sapi/apache2filter/sapi_apache2.c
index f2c7a87d8..6597057f3 100644
--- a/sapi/apache2filter/sapi_apache2.c
+++ b/sapi/apache2filter/sapi_apache2.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: sapi_apache2.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: sapi_apache2.c 321634 2012-01-01 13:15:04Z felipe $ */
#include <fcntl.h>
@@ -420,7 +420,7 @@ static void php_apache_request_ctor(ap_filter_t *f, php_struct *ctx TSRMLS_DC)
efree(content_type);
content_length = (char *) apr_table_get(f->r->headers_in, "Content-Length");
- SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
+ SG(request_info).content_length = (content_length ? atol(content_length) : 0);
apr_table_unset(f->r->headers_out, "Content-Length");
apr_table_unset(f->r->headers_out, "Last-Modified");
diff --git a/sapi/apache2handler/apache_config.c b/sapi/apache2handler/apache_config.c
index c7eafeb96..2d221fe87 100644
--- a/sapi/apache2handler/apache_config.c
+++ b/sapi/apache2handler/apache_config.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: apache_config.c 311342 2011-05-23 01:47:06Z felipe $ */
+/* $Id: apache_config.c 321634 2012-01-01 13:15:04Z felipe $ */
#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
diff --git a/sapi/apache2handler/mod_php5.c b/sapi/apache2handler/mod_php5.c
index 56bfdad35..9884fc66b 100644
--- a/sapi/apache2handler/mod_php5.c
+++ b/sapi/apache2handler/mod_php5.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: mod_php5.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: mod_php5.c 321634 2012-01-01 13:15:04Z felipe $ */
#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
diff --git a/sapi/apache2handler/php_apache.h b/sapi/apache2handler/php_apache.h
index 2ee8bd896..292919327 100644
--- a/sapi/apache2handler/php_apache.h
+++ b/sapi/apache2handler/php_apache.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_apache.h 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: php_apache.h 321634 2012-01-01 13:15:04Z felipe $ */
#ifndef PHP_APACHE_H
#define PHP_APACHE_H
diff --git a/sapi/apache2handler/php_functions.c b/sapi/apache2handler/php_functions.c
index b7cc64054..ed9a03165 100644
--- a/sapi/apache2handler/php_functions.c
+++ b/sapi/apache2handler/php_functions.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_functions.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: php_functions.c 321634 2012-01-01 13:15:04Z felipe $ */
#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
diff --git a/sapi/apache2handler/sapi_apache2.c b/sapi/apache2handler/sapi_apache2.c
index 18f21247a..d373adb50 100644
--- a/sapi/apache2handler/sapi_apache2.c
+++ b/sapi/apache2handler/sapi_apache2.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: sapi_apache2.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: sapi_apache2.c 321634 2012-01-01 13:15:04Z felipe $ */
#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
@@ -484,7 +484,7 @@ static int php_apache_request_ctor(request_rec *r, php_struct *ctx TSRMLS_DC)
r->no_local_copy = 1;
content_length = (char *) apr_table_get(r->headers_in, "Content-Length");
- SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
+ SG(request_info).content_length = (content_length ? atol(content_length) : 0);
apr_table_unset(r->headers_out, "Content-Length");
apr_table_unset(r->headers_out, "Last-Modified");
diff --git a/sapi/apache_hooks/mod_php5.c b/sapi/apache_hooks/mod_php5.c
index 79a733b4b..db68e5c9b 100644
--- a/sapi/apache_hooks/mod_php5.c
+++ b/sapi/apache_hooks/mod_php5.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -17,7 +17,7 @@
| PHP 4.0 patches by Zeev Suraski <zeev@zend.com> |
+----------------------------------------------------------------------+
*/
-/* $Id: mod_php5.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: mod_php5.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php_apache_http.h"
@@ -587,7 +587,7 @@ static void init_request_info(TSRMLS_D)
SG(request_info).request_method = (char *)r->method;
SG(request_info).proto_num = r->proto_num;
SG(request_info).content_type = (char *) table_get(r->subprocess_env, "CONTENT_TYPE");
- SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
+ SG(request_info).content_length = (content_length ? atol(content_length) : 0);
SG(sapi_headers).http_response_code = r->status;
if (r->headers_in) {
diff --git a/sapi/apache_hooks/mod_php5.h b/sapi/apache_hooks/mod_php5.h
index 08ec4eb41..a665a5083 100644
--- a/sapi/apache_hooks/mod_php5.h
+++ b/sapi/apache_hooks/mod_php5.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -15,7 +15,7 @@
| Author: Rasmus Lerdorf <rasmus@php.net> |
+----------------------------------------------------------------------+
*/
-/* $Id: mod_php5.h 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: mod_php5.h 321634 2012-01-01 13:15:04Z felipe $ */
#ifndef MOD_PHP5_H
#define MOD_PHP5_H
diff --git a/sapi/apache_hooks/php_apache.c b/sapi/apache_hooks/php_apache.c
index 8a4920920..bfcc629f0 100644
--- a/sapi/apache_hooks/php_apache.c
+++ b/sapi/apache_hooks/php_apache.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -17,7 +17,7 @@
| David Sklar <sklar@student.net> |
+----------------------------------------------------------------------+
*/
-/* $Id: php_apache.c 314352 2011-08-06 01:22:27Z felipe $ */
+/* $Id: php_apache.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php_apache_http.h"
diff --git a/sapi/apache_hooks/sapi_apache.c b/sapi/apache_hooks/sapi_apache.c
index f1b948be9..568f10c4a 100644
--- a/sapi/apache_hooks/sapi_apache.c
+++ b/sapi/apache_hooks/sapi_apache.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -19,7 +19,7 @@
| Stig Bakken <ssb@php.net> |
+----------------------------------------------------------------------+
*/
-/* $Id: sapi_apache.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: sapi_apache.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php_apache_http.h"
diff --git a/sapi/caudium/caudium.c b/sapi/caudium/caudium.c
index e0c4847f3..51d0c3087 100644
--- a/sapi/caudium/caudium.c
+++ b/sapi/caudium/caudium.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: caudium.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: caudium.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php.h"
#ifdef HAVE_CAUDIUM
@@ -444,7 +444,7 @@ static void php_info_caudium(ZEND_MODULE_INFO_FUNC_ARGS)
{
/* char buf[512]; */
php_info_print_table_start();
- php_info_print_table_row(2, "SAPI module version", "$Id: caudium.c 306939 2011-01-01 02:19:59Z felipe $");
+ php_info_print_table_row(2, "SAPI module version", "$Id: caudium.c 321634 2012-01-01 13:15:04Z felipe $");
/* php_info_print_table_row(2, "Build date", Ns_InfoBuildDate());
php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile());
php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog());
diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
index 590419ee8..083c6e353 100644
--- a/sapi/cgi/cgi_main.c
+++ b/sapi/cgi/cgi_main.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -21,7 +21,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: cgi_main.c 314773 2011-08-11 06:38:42Z dmitry $ */
+/* $Id: cgi_main.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php.h"
#include "php_globals.h"
@@ -1353,7 +1353,7 @@ static void init_request_info(TSRMLS_D)
/* FIXME - Work out proto_num here */
SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING")-1 TSRMLS_CC);
SG(request_info).content_type = (content_type ? content_type : "" );
- SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
+ SG(request_info).content_length = (content_length ? atol(content_length) : 0);
/* The CGI RFC allows servers to pass on unvalidated Authorization data */
auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION")-1 TSRMLS_CC);
@@ -1933,9 +1933,9 @@ consult the installation file that came with this distribution, or visit \n\
SG(request_info).no_headers = 1;
}
#if ZEND_DEBUG
- php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ php_printf("PHP %s (%s) (built: %s %s) (DEBUG)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
#else
- php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
#endif
php_request_shutdown((void *) 0);
fcgi_shutdown();
diff --git a/sapi/cgi/fastcgi.c b/sapi/cgi/fastcgi.c
index c6f96f3e2..66628f60c 100644
--- a/sapi/cgi/fastcgi.c
+++ b/sapi/cgi/fastcgi.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: fastcgi.c 307579 2011-01-19 08:38:25Z dmitry $ */
+/* $Id: fastcgi.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php.h"
#include "fastcgi.h"
diff --git a/sapi/cgi/fastcgi.h b/sapi/cgi/fastcgi.h
index 226b68f3e..9b42f07a0 100644
--- a/sapi/cgi/fastcgi.h
+++ b/sapi/cgi/fastcgi.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: fastcgi.h 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: fastcgi.h 321634 2012-01-01 13:15:04Z felipe $ */
/* FastCGI protocol */
diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c
index c80d46490..3fbce7476 100644
--- a/sapi/cli/php_cli.c
+++ b/sapi/cli/php_cli.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -20,7 +20,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_cli.c 314468 2011-08-08 07:12:12Z laruence $ */
+/* $Id: php_cli.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php.h"
#include "php_globals.h"
@@ -826,7 +826,7 @@ int main(int argc, char *argv[])
}
request_started = 1;
- php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2011 The PHP Group\n%s",
+ php_printf("PHP %s (%s) (built: %s %s) %s\nCopyright (c) 1997-2012 The PHP Group\n%s",
PHP_VERSION, sapi_module.name, __DATE__, __TIME__,
#if ZEND_DEBUG && defined(HAVE_GCOV)
"(DEBUG GCOV)",
diff --git a/sapi/cli/php_cli_readline.c b/sapi/cli/php_cli_readline.c
index 4b601ee55..888f4b60b 100644
--- a/sapi/cli/php_cli_readline.c
+++ b/sapi/cli/php_cli_readline.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_cli_readline.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: php_cli_readline.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php.h"
diff --git a/sapi/cli/php_cli_readline.h b/sapi/cli/php_cli_readline.h
index 93d869603..d62bb7d50 100644
--- a/sapi/cli/php_cli_readline.h
+++ b/sapi/cli/php_cli_readline.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_cli_readline.h 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: php_cli_readline.h 321634 2012-01-01 13:15:04Z felipe $ */
#include "php.h"
diff --git a/sapi/cli/tests/016.phpt b/sapi/cli/tests/016.phpt
index adde106df..9c28d15a3 100644
--- a/sapi/cli/tests/016.phpt
+++ b/sapi/cli/tests/016.phpt
@@ -65,25 +65,37 @@ Snippet no. 1:
--------------
Interactive shell
-php > Hello world
-php >
+php > echo 'Hello world';
+Hello world
+php > exit
+
--------------
Snippet no. 2:
--------------
Interactive shell
-php > php ' php ' multine
+php > echo 'multine
+php ' single
+php ' quote';
+multine
single
quote
-php >
+php > exit
+
--------------
Snippet no. 3:
--------------
Interactive shell
-php > <<< > <<< > <<< > <<< > <<< > Here
+php > echo <<<HEREDOC
+<<< > Here
+<<< > comes
+<<< > the
+<<< > doc
+<<< > HEREDOC;
+Here
comes
the
doc
@@ -94,7 +106,11 @@ Snippet no. 4:
--------------
Interactive shell
-php > php { php { php > Done
+php > if (0) {
+php { echo "I'm not there";
+php { }
+php > echo "Done";
+Done
php >
--------------
@@ -102,7 +118,11 @@ Snippet no. 5:
--------------
Interactive shell
-php > php { php { php > I was called!
+php > function a_function_with_some_name() {
+php { echo "I was called!";
+php { }
+php > a_function_with_some_name();
+I was called!
php >
Done
diff --git a/sapi/cli/tests/021.phpt b/sapi/cli/tests/021.phpt
index a4442b0e0..2ddd68890 100644
--- a/sapi/cli/tests/021.phpt
+++ b/sapi/cli/tests/021.phpt
@@ -6,6 +6,10 @@ include 'skipif.inc';
if (substr(PHP_OS, 0, 3) == 'WIN') {
die ("skip not for Windows");
}
+
+if (strlen("#!".getenv('TEST_PHP_EXECUTABLE')) > 127) {
+ die ("skip shebang is too long, see http://www.in-ulm.de/~mascheck/various/shebang/#results");
+}
?>
--FILE--
<?php
diff --git a/sapi/cli/tests/022.phpt b/sapi/cli/tests/022.phpt
index eabb8bdf8..0110220be 100644
--- a/sapi/cli/tests/022.phpt
+++ b/sapi/cli/tests/022.phpt
@@ -8,7 +8,7 @@ if (substr(PHP_OS, 0, 3) == "WIN") die("skip non windows test");
--FILE--
<?php
$php = getenv("TEST_PHP_EXECUTABLE");
-$socket_file = dirname(__FILE__) . '/' . pathinfo(__FILE__, PATHINFO_FILENAME) . '.sock';
+$socket_file = tempnam(sys_get_temp_dir(), pathinfo(__FILE__, PATHINFO_FILENAME) . '.sock');
$test_file = dirname(__FILE__) . '/' . pathinfo(__FILE__, PATHINFO_FILENAME) . '.inc';
if (file_exists($socket_file)) {
unlink($socket_file);
diff --git a/sapi/continuity/capi.c b/sapi/continuity/capi.c
index 720727bb7..4253cc28f 100644
--- a/sapi/continuity/capi.c
+++ b/sapi/continuity/capi.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -110,7 +110,7 @@ PHP_MSHUTDOWN_FUNCTION(continuity)
PHP_MINFO_FUNCTION(continuity)
{
php_info_print_table_start();
- php_info_print_table_row(2, "Continuity Module Revision", "$Revision: 306939 $");
+ php_info_print_table_row(2, "Continuity Module Revision", "$Revision: 321634 $");
php_info_print_table_row(2, "Server Version", conFget_build());
#ifdef CONTINUITY_CDPEXT
php_info_print_table_row(2,"CDP Extensions", "enabled");
diff --git a/sapi/embed/php_embed.c b/sapi/embed/php_embed.c
index 563d3e10c..a412d0515 100644
--- a/sapi/embed/php_embed.c
+++ b/sapi/embed/php_embed.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -15,7 +15,7 @@
| Author: Edin Kadribasic <edink@php.net> |
+----------------------------------------------------------------------+
*/
-/* $Id: php_embed.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: php_embed.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php_embed.h"
#include "ext/standard/php_standard.h"
diff --git a/sapi/embed/php_embed.h b/sapi/embed/php_embed.h
index c5e731d5e..9cd21fb95 100644
--- a/sapi/embed/php_embed.h
+++ b/sapi/embed/php_embed.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -15,7 +15,7 @@
| Author: Edin Kadribasic <edink@php.net> |
+----------------------------------------------------------------------+
*/
-/* $Id: php_embed.h 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: php_embed.h 321634 2012-01-01 13:15:04Z felipe $ */
#ifndef _PHP_EMBED_H_
#define _PHP_EMBED_H_
diff --git a/sapi/fpm/Makefile.frag b/sapi/fpm/Makefile.frag
index 0859ef10c..c5cea7e52 100644
--- a/sapi/fpm/Makefile.frag
+++ b/sapi/fpm/Makefile.frag
@@ -2,6 +2,7 @@ fpm: $(SAPI_FPM_PATH)
$(builddir)/fpm:
@mkdir -p $(builddir)/fpm
+ @mkdir -p $(builddir)/fpm/events
$(SAPI_FPM_PATH): $(builddir)/fpm $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(SAPI_EXTRA_DEPS)
$(BUILD_FPM)
@@ -26,3 +27,6 @@ install-fpm: install-sapi
@$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man8
@$(INSTALL_DATA) sapi/fpm/php-fpm.8 $(INSTALL_ROOT)$(mandir)/man8/php-fpm$(program_suffix).8
+ @echo "Installing PHP FPM status page: $(INSTALL_ROOT)$(datadir)/fpm/"
+ @$(mkinstalldirs) $(INSTALL_ROOT)$(datadir)/fpm
+ @$(INSTALL_DATA) sapi/fpm/status.html $(INSTALL_ROOT)$(datadir)/fpm/status.html
diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4
index 1105ec8d2..953fa1f7b 100644
--- a/sapi/fpm/config.m4
+++ b/sapi/fpm/config.m4
@@ -366,6 +366,171 @@ AC_DEFUN([AC_FPM_TIMES],
])
dnl }}}
+AC_DEFUN([AC_FPM_KQUEUE],
+[
+ AC_MSG_CHECKING([for kqueue])
+
+ AC_TRY_COMPILE(
+ [
+ #include <sys/types.h>
+ #include <sys/event.h>
+ #include <sys/time.h>
+ ], [
+ int kfd;
+ struct kevent k;
+ kfd = kqueue();
+ /* 0 -> STDIN_FILENO */
+ EV_SET(&k, 0, EVFILT_READ , EV_ADD | EV_CLEAR, 0, 0, NULL);
+ ], [
+ AC_DEFINE([HAVE_KQUEUE], 1, [do we have kqueue?])
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
+dnl }}}
+
+AC_DEFUN([AC_FPM_PORT],
+[
+ AC_MSG_CHECKING([for port framework])
+
+ AC_TRY_COMPILE(
+ [
+ #include <port.h>
+ ], [
+ int port;
+
+ port = port_create();
+ if (port < 0) {
+ return 1;
+ }
+ ], [
+ AC_DEFINE([HAVE_PORT], 1, [do we have port framework?])
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
+dnl }}}
+
+AC_DEFUN([AC_FPM_DEVPOLL],
+[
+ AC_MSG_CHECKING([for /dev/poll])
+
+ AC_TRY_COMPILE(
+ [
+ #include <stdio.h>
+ #include <sys/devpoll.h>
+ ], [
+ int n, dp;
+ struct dvpoll dvp;
+ dp = 0;
+ dvp.dp_fds = NULL;
+ dvp.dp_nfds = 0;
+ dvp.dp_timeout = 0;
+ n = ioctl(dp, DP_POLL, &dvp)
+ ], [
+ AC_DEFINE([HAVE_DEVPOLL], 1, [do we have /dev/poll?])
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
+dnl }}}
+
+AC_DEFUN([AC_FPM_EPOLL],
+[
+ AC_MSG_CHECKING([for epoll])
+
+ AC_TRY_COMPILE(
+ [
+ #include <sys/epoll.h>
+ ], [
+ int epollfd;
+ struct epoll_event e;
+
+ epollfd = epoll_create(1);
+ if (epollfd < 0) {
+ return 1;
+ }
+
+ e.events = EPOLLIN | EPOLLET;
+ e.data.fd = 0;
+
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, 0, &e) == -1) {
+ return 1;
+ }
+
+ e.events = 0;
+ if (epoll_wait(epollfd, &e, 1, 1) < 0) {
+ return 1;
+ }
+ ], [
+ AC_DEFINE([HAVE_EPOLL], 1, [do we have epoll?])
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
+dnl }}}
+
+AC_DEFUN([AC_FPM_POLL],
+[
+ AC_MSG_CHECKING([for poll])
+
+ AC_TRY_COMPILE(
+ [
+ #include <poll.h>
+ ], [
+ struct pollfd fds[2];
+
+ fds[0].fd = 0;
+ fds[0].events = POLLIN;
+
+ fds[1].fd = 0;
+ fds[1].events = POLLIN;
+
+ poll(fds, 2, 1);
+ ], [
+ AC_DEFINE([HAVE_POLL], 1, [do we have poll?])
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
+dnl }}}
+
+AC_DEFUN([AC_FPM_SELECT],
+[
+ AC_MSG_CHECKING([for select])
+
+ AC_TRY_COMPILE(
+ [
+ /* According to POSIX.1-2001 */
+ #include <sys/select.h>
+
+ /* According to earlier standards */
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <unistd.h>
+ ], [
+ fd_set fds;
+ struct timeval t;
+ t.tv_sec = 0;
+ t.tv_usec = 42;
+ FD_ZERO(&fds);
+ /* 0 -> STDIN_FILENO */
+ FD_SET(0, &fds);
+ select(FD_SETSIZE, &fds, NULL, NULL, &t);
+ ], [
+ AC_DEFINE([HAVE_SELECT], 1, [do we have select?])
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+])
+dnl }}}
+
AC_MSG_CHECKING(for FPM build)
if test "$PHP_FPM" != "no"; then
@@ -379,6 +544,12 @@ if test "$PHP_FPM" != "no"; then
AC_FPM_LQ
AC_FPM_SYSCONF
AC_FPM_TIMES
+ AC_FPM_KQUEUE
+ AC_FPM_PORT
+ AC_FPM_DEVPOLL
+ AC_FPM_EPOLL
+ AC_FPM_POLL
+ AC_FPM_SELECT
PHP_ARG_WITH(fpm-user,,
[ --with-fpm-user[=USER] Set the user for php-fpm to run as. (default: nobody)], nobody, no)
@@ -411,7 +582,7 @@ if test "$PHP_FPM" != "no"; then
AC_DEFINE_UNQUOTED(PHP_FPM_USER, "$php_fpm_user", [fpm user name])
AC_DEFINE_UNQUOTED(PHP_FPM_GROUP, "$php_fpm_group", [fpm group name])
- PHP_OUTPUT(sapi/fpm/php-fpm.conf sapi/fpm/init.d.php-fpm sapi/fpm/php-fpm.8)
+ PHP_OUTPUT(sapi/fpm/php-fpm.conf sapi/fpm/init.d.php-fpm sapi/fpm/php-fpm.8 sapi/fpm/status.html)
PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/sapi/fpm/Makefile.frag], [$abs_srcdir/sapi/fpm], [sapi/fpm])
SAPI_FPM_PATH=sapi/fpm/php-fpm
@@ -447,6 +618,12 @@ if test "$PHP_FPM" != "no"; then
fpm/fpm_unix.c \
fpm/fpm_worker_pool.c \
fpm/zlog.c \
+ fpm/events/select.c \
+ fpm/events/poll.c \
+ fpm/events/epoll.c \
+ fpm/events/kqueue.c \
+ fpm/events/devpoll.c \
+ fpm/events/port.c \
"
PHP_SELECT_SAPI(fpm, program, $PHP_FPM_FILES $PHP_FPM_TRACE_FILES, $PHP_FPM_CFLAGS, '$(SAPI_FPM_PATH)')
diff --git a/sapi/fpm/fpm/events/devpoll.c b/sapi/fpm/fpm/events/devpoll.c
new file mode 100644
index 000000000..eec7e5e13
--- /dev/null
+++ b/sapi/fpm/fpm/events/devpoll.c
@@ -0,0 +1,248 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+#include "../fpm.h"
+#include "../zlog.h"
+
+#if HAVE_DEVPOLL
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/devpoll.h>
+#include <errno.h>
+
+static int fpm_event_devpoll_init(int max);
+static int fpm_event_devpoll_clean();
+static int fpm_event_devpoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
+static int fpm_event_devpoll_add(struct fpm_event_s *ev);
+static int fpm_event_devpoll_remove(struct fpm_event_s *ev);
+
+static struct fpm_event_module_s devpoll_module = {
+ .name = "/dev/poll",
+ .support_edge_trigger = 0,
+ .init = fpm_event_devpoll_init,
+ .clean = fpm_event_devpoll_clean,
+ .wait = fpm_event_devpoll_wait,
+ .add = fpm_event_devpoll_add,
+ .remove = fpm_event_devpoll_remove,
+};
+
+int dpfd = -1;
+static struct pollfd *pollfds = NULL;
+static struct pollfd *active_pollfds = NULL;
+static int npollfds = 0;
+
+#endif /* HAVE_DEVPOLL */
+
+struct fpm_event_module_s *fpm_event_devpoll_module() /* {{{ */
+{
+#if HAVE_DEVPOLL
+ return &devpoll_module;
+#else
+ return NULL;
+#endif /* HAVE_DEVPOLL */
+}
+/* }}} */
+
+#if HAVE_DEVPOLL
+
+/*
+ * Init module
+ */
+static int fpm_event_devpoll_init(int max) /* {{{ */
+{
+ int i;
+
+ /* open /dev/poll for future usages */
+ dpfd = open("/dev/poll", O_RDWR);
+ if (dpfd < 0) {
+ zlog(ZLOG_ERROR, "Unable to open /dev/poll");
+ return -1;
+ }
+
+ if (max < 1) {
+ return 0;
+ }
+
+ /* alloc and clear pollfds */
+ pollfds = malloc(sizeof(struct pollfd) * max);
+ if (!pollfds) {
+ zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
+ return -1;
+ }
+ memset(pollfds, 0, sizeof(struct pollfd) * max);
+
+ /* set all fd to -1 in order to ensure it's not set */
+ for (i = 0; i < max; i++) {
+ pollfds[i].fd = -1;
+ }
+
+ /* alloc and clear active_pollfds */
+ active_pollfds = malloc(sizeof(struct pollfd) * max);
+ if (!active_pollfds) {
+ free(pollfds);
+ zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
+ return -1;
+ }
+ memset(active_pollfds, 0, sizeof(struct pollfd) * max);
+
+ /* save max */
+ npollfds = max;
+
+ return 0;
+}
+/* }}} */
+
+/*
+ * Clean the module
+ */
+static int fpm_event_devpoll_clean() /* {{{ */
+{
+ /* close /dev/poll if open */
+ if (dpfd > -1) {
+ close(dpfd);
+ dpfd = -1;
+ }
+
+ /* free pollfds */
+ if (pollfds) {
+ free(pollfds);
+ pollfds = NULL;
+ }
+
+ /* free active_pollfds */
+ if (active_pollfds) {
+ free(active_pollfds);
+ active_pollfds = NULL;
+ }
+
+ npollfds = 0;
+ return 0;
+}
+/* }}} */
+
+/*
+ * wait for events or timeout
+ */
+static int fpm_event_devpoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
+{
+ int ret, i;
+ struct fpm_event_queue_s *q;
+ struct dvpoll dopoll;
+
+ /* setup /dev/poll */
+ dopoll.dp_fds = active_pollfds;
+ dopoll.dp_nfds = npollfds;
+ dopoll.dp_timeout = (int)timeout;
+
+ /* wait for inconming event or timeout */
+ ret = ioctl(dpfd, DP_POLL, &dopoll);
+
+ if (ret < 0) {
+
+ /* trigger error unless signal interrupt */
+ if (errno != EINTR) {
+ zlog(ZLOG_WARNING, "/dev/poll: ioctl() returns %d", errno);
+ return -1;
+ }
+ }
+
+ /* iterate throught triggered events */
+ for (i = 0; i < ret; i++) {
+
+ /* find the corresponding event */
+ q = queue;
+ while (q) {
+
+ /* found */
+ if (q->ev && q->ev->fd == active_pollfds[i].fd) {
+
+ /* fire the event */
+ fpm_event_fire(q->ev);
+
+ /* sanity check */
+ if (fpm_globals.parent_pid != getpid()) {
+ return -2;
+ }
+ break; /* next triggered event */
+ }
+ q = q->next; /* iterate */
+ }
+ }
+
+ return ret;
+}
+/* }}} */
+
+/*
+ * Add a FD from the fd set
+ */
+static int fpm_event_devpoll_add(struct fpm_event_s *ev) /* {{{ */
+{
+ struct pollfd pollfd;
+
+ /* fill pollfd with event informations */
+ pollfd.fd = ev->fd;
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
+
+ /* add the event to the internal queue */
+ if (write(dpfd, &pollfd, sizeof(struct pollfd)) != sizeof(struct pollfd)) {
+ zlog(ZLOG_ERROR, "/dev/poll: Unable to add the event in the internal queue");
+ return -1;
+ }
+
+ /* mark the event as registered */
+ ev->index = ev->fd;
+
+ return 0;
+}
+/* }}} */
+
+/*
+ * Remove a FD from the fd set
+ */
+static int fpm_event_devpoll_remove(struct fpm_event_s *ev) /* {{{ */
+{
+ struct pollfd pollfd;
+
+ /* fill pollfd with the same informations as fpm_event_devpoll_add */
+ pollfd.fd = ev->fd;
+ pollfd.events = POLLIN | POLLREMOVE;
+ pollfd.revents = 0;
+
+ /* add the event to the internal queue */
+ if (write(dpfd, &pollfd, sizeof(struct pollfd)) != sizeof(struct pollfd)) {
+ zlog(ZLOG_ERROR, "/dev/poll: Unable to remove the event in the internal queue");
+ return -1;
+ }
+
+ /* mark the event as registered */
+ ev->index = -1;
+
+ return 0;
+}
+/* }}} */
+
+#endif /* HAVE_DEVPOLL */
diff --git a/sapi/fpm/fpm/events/devpoll.h b/sapi/fpm/fpm/events/devpoll.h
new file mode 100644
index 000000000..95291b158
--- /dev/null
+++ b/sapi/fpm/fpm/events/devpoll.h
@@ -0,0 +1,29 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef FPM_EVENTS_DEVPOLL_H
+#define FPM_EVENTS_DEVPOLL_H
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+
+struct fpm_event_module_s *fpm_event_devpoll_module();
+
+#endif /* FPM_EVENTS_DEVPOLL_H */
diff --git a/sapi/fpm/fpm/events/epoll.c b/sapi/fpm/fpm/events/epoll.c
new file mode 100644
index 000000000..2914aa010
--- /dev/null
+++ b/sapi/fpm/fpm/events/epoll.c
@@ -0,0 +1,211 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+#include "../fpm.h"
+#include "../zlog.h"
+
+#if HAVE_EPOLL
+
+#include <sys/epoll.h>
+#include <errno.h>
+
+static int fpm_event_epoll_init(int max);
+static int fpm_event_epoll_clean();
+static int fpm_event_epoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
+static int fpm_event_epoll_add(struct fpm_event_s *ev);
+static int fpm_event_epoll_remove(struct fpm_event_s *ev);
+
+static struct fpm_event_module_s epoll_module = {
+ .name = "epoll",
+ .support_edge_trigger = 1,
+ .init = fpm_event_epoll_init,
+ .clean = fpm_event_epoll_clean,
+ .wait = fpm_event_epoll_wait,
+ .add = fpm_event_epoll_add,
+ .remove = fpm_event_epoll_remove,
+};
+
+static struct epoll_event *epollfds = NULL;
+static int nepollfds = 0;
+static int epollfd = 0;
+
+#endif /* HAVE_EPOLL */
+
+struct fpm_event_module_s *fpm_event_epoll_module() /* {{{ */
+{
+#if HAVE_EPOLL
+ return &epoll_module;
+#else
+ return NULL;
+#endif /* HAVE_EPOLL */
+}
+/* }}} */
+
+#if HAVE_EPOLL
+
+/*
+ * Init the module
+ */
+static int fpm_event_epoll_init(int max) /* {{{ */
+{
+ if (max < 1) {
+ return 0;
+ }
+
+ /* init epoll */
+ epollfd = epoll_create(max + 1);
+ if (epollfd < 0) {
+ zlog(ZLOG_ERROR, "epoll: unable to initialize");
+ return -1;
+ }
+
+ /* allocate fds */
+ epollfds = malloc(sizeof(struct epoll_event) * max);
+ if (!epollfds) {
+ zlog(ZLOG_ERROR, "epoll: unable to allocate %d events", max);
+ return -1;
+ }
+ memset(epollfds, 0, sizeof(struct epoll_event) * max);
+
+ /* save max */
+ nepollfds = max;
+
+ return 0;
+}
+/* }}} */
+
+/*
+ * Clean the module
+ */
+static int fpm_event_epoll_clean() /* {{{ */
+{
+ /* free epollfds */
+ if (epollfds) {
+ free(epollfds);
+ epollfds = NULL;
+ }
+
+ nepollfds = 0;
+
+ return 0;
+}
+/* }}} */
+
+/*
+ * wait for events or timeout
+ */
+static int fpm_event_epoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
+{
+ int ret, i;
+
+ /* ensure we have a clean epoolfds before calling epoll_wait() */
+ memset(epollfds, 0, sizeof(struct epoll_event) * nepollfds);
+
+ /* wait for inconming event or timeout */
+ ret = epoll_wait(epollfd, epollfds, nepollfds, timeout);
+ if (ret == -1) {
+
+ /* trigger error unless signal interrupt */
+ if (errno != EINTR) {
+ zlog(ZLOG_WARNING, "epoll_wait() returns %d", errno);
+ return -1;
+ }
+ }
+
+ /* events have been triggered, let's fire them */
+ for (i = 0; i < ret; i++) {
+
+ /* do we have a valid ev ptr ? */
+ if (!epollfds[i].data.ptr) {
+ continue;
+ }
+
+ /* fire the event */
+ fpm_event_fire((struct fpm_event_s *)epollfds[i].data.ptr);
+
+ /* sanity check */
+ if (fpm_globals.parent_pid != getpid()) {
+ return -2;
+ }
+ }
+
+ return ret;
+}
+/* }}} */
+
+/*
+ * Add a FD to the fd set
+ */
+static int fpm_event_epoll_add(struct fpm_event_s *ev) /* {{{ */
+{
+ struct epoll_event e;
+
+ /* fill epoll struct */
+ e.events = EPOLLIN;
+ e.data.fd = ev->fd;
+ e.data.ptr = (void *)ev;
+
+ if (ev->flags & FPM_EV_EDGE) {
+ e.events = e.events | EPOLLET;
+ }
+
+ /* add the event to epoll internal queue */
+ if (epoll_ctl(epollfd, EPOLL_CTL_ADD, ev->fd, &e) == -1) {
+ zlog(ZLOG_ERROR, "epoll: unable to add fd %d", ev->fd);
+ return -1;
+ }
+
+ /* mark the event as registered */
+ ev->index = ev->fd;
+ return 0;
+}
+/* }}} */
+
+/*
+ * Remove a FD from the fd set
+ */
+static int fpm_event_epoll_remove(struct fpm_event_s *ev) /* {{{ */
+{
+ struct epoll_event e;
+
+ /* fill epoll struct the same way we did in fpm_event_epoll_add() */
+ e.events = EPOLLIN;
+ e.data.fd = ev->fd;
+ e.data.ptr = (void *)ev;
+
+ if (ev->flags & FPM_EV_EDGE) {
+ e.events = e.events | EPOLLET;
+ }
+
+ /* remove the event from epoll internal queue */
+ if (epoll_ctl(epollfd, EPOLL_CTL_DEL, ev->fd, &e) == -1) {
+ zlog(ZLOG_ERROR, "epoll: unable to remove fd %d", ev->fd);
+ return -1;
+ }
+
+ /* mark the event as not registered */
+ ev->index = -1;
+ return 0;
+}
+/* }}} */
+
+#endif /* HAVE_EPOLL */
diff --git a/sapi/fpm/fpm/events/epoll.h b/sapi/fpm/fpm/events/epoll.h
new file mode 100644
index 000000000..63de752fc
--- /dev/null
+++ b/sapi/fpm/fpm/events/epoll.h
@@ -0,0 +1,29 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef FPM_EVENTS_EPOLL_H
+#define FPM_EVENTS_EPOLL_H
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+
+struct fpm_event_module_s *fpm_event_epoll_module();
+
+#endif /* FPM_EVENTS_EPOLL_H */
diff --git a/sapi/fpm/fpm/events/kqueue.c b/sapi/fpm/fpm/events/kqueue.c
new file mode 100644
index 000000000..eb90c5fcf
--- /dev/null
+++ b/sapi/fpm/fpm/events/kqueue.c
@@ -0,0 +1,208 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+#include "../fpm.h"
+#include "../zlog.h"
+
+#if HAVE_KQUEUE
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+
+#include <errno.h>
+
+static int fpm_event_kqueue_init(int max);
+static int fpm_event_kqueue_clean();
+static int fpm_event_kqueue_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
+static int fpm_event_kqueue_add(struct fpm_event_s *ev);
+static int fpm_event_kqueue_remove(struct fpm_event_s *ev);
+
+static struct fpm_event_module_s kqueue_module = {
+ .name = "kqueue",
+ .support_edge_trigger = 1,
+ .init = fpm_event_kqueue_init,
+ .clean = fpm_event_kqueue_clean,
+ .wait = fpm_event_kqueue_wait,
+ .add = fpm_event_kqueue_add,
+ .remove = fpm_event_kqueue_remove,
+};
+
+static struct kevent *kevents = NULL;
+static int nkevents = 0;
+static int kfd = 0;
+
+#endif /* HAVE_KQUEUE */
+
+/*
+ * Return the module configuration
+ */
+struct fpm_event_module_s *fpm_event_kqueue_module() /* {{{ */
+{
+#if HAVE_KQUEUE
+ return &kqueue_module;
+#else
+ return NULL;
+#endif /* HAVE_KQUEUE */
+}
+/* }}} */
+
+#if HAVE_KQUEUE
+
+/*
+ * init kqueue and stuff
+ */
+static int fpm_event_kqueue_init(int max) /* {{{ */
+{
+ if (max < 1) {
+ return 0;
+ }
+
+ kfd = kqueue();
+ if (kfd < 0) {
+ zlog(ZLOG_ERROR, "kqueue: unable to initialize");
+ return -1;
+ }
+
+ kevents = malloc(sizeof(struct kevent) * max);
+ if (!kevents) {
+ zlog(ZLOG_ERROR, "epoll: unable to allocate %d events", max);
+ return -1;
+ }
+
+ memset(kevents, 0, sizeof(struct kevent) * max);
+
+ nkevents = max;
+
+ return 0;
+}
+/* }}} */
+
+/*
+ * release kqueue stuff
+ */
+static int fpm_event_kqueue_clean() /* {{{ */
+{
+ if (kevents) {
+ free(kevents);
+ kevents = NULL;
+ }
+
+ nkevents = 0;
+
+ return 0;
+}
+/* }}} */
+
+/*
+ * wait for events or timeout
+ */
+static int fpm_event_kqueue_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
+{
+ struct timespec t;
+ int ret, i;
+
+ /* ensure we have a clean kevents before calling kevent() */
+ memset(kevents, 0, sizeof(struct kevent) * nkevents);
+
+ /* convert ms to timespec struct */
+ t.tv_sec = timeout / 1000;
+ t.tv_nsec = (timeout % 1000) * 1000 * 1000;
+
+ /* wait for incoming event or timeout */
+ ret = kevent(kfd, NULL, 0, kevents, nkevents, &t);
+ if (ret == -1) {
+
+ /* trigger error unless signal interrupt */
+ if (errno != EINTR) {
+ zlog(ZLOG_WARNING, "epoll_wait() returns %d", errno);
+ return -1;
+ }
+ }
+
+ /* fire triggered events */
+ for (i = 0; i < ret; i++) {
+ if (kevents[i].udata) {
+ struct fpm_event_s *ev = (struct fpm_event_s *)kevents[i].udata;
+ fpm_event_fire(ev);
+ /* sanity check */
+ if (fpm_globals.parent_pid != getpid()) {
+ return -2;
+ }
+ }
+ }
+
+ return ret;
+}
+/* }}} */
+
+/*
+ * Add a FD to to kevent queue
+ */
+static int fpm_event_kqueue_add(struct fpm_event_s *ev) /* {{{ */
+{
+ struct kevent k;
+ int flags = EV_ADD;
+
+ if (ev->flags & FPM_EV_EDGE) {
+ flags = flags | EV_CLEAR;
+ }
+
+ EV_SET(&k, ev->fd, EVFILT_READ, flags, 0, 0, (void *)ev);
+
+ if (kevent(kfd, &k, 1, NULL, 0, NULL) < 0) {
+ zlog(ZLOG_ERROR, "kevent: unable to add event");
+ return -1;
+ }
+
+ /* mark the event as registered */
+ ev->index = ev->fd;
+ return 0;
+}
+/* }}} */
+
+/*
+ * Remove a FD from the kevent queue
+ */
+static int fpm_event_kqueue_remove(struct fpm_event_s *ev) /* {{{ */
+{
+ struct kevent k;
+ int flags = EV_DELETE;
+
+ if (ev->flags & FPM_EV_EDGE) {
+ flags = flags | EV_CLEAR;
+ }
+
+ EV_SET(&k, ev->fd, EVFILT_READ, flags, 0, 0, (void *)ev);
+
+ if (kevent(kfd, &k, 1, NULL, 0, NULL) < 0) {
+ zlog(ZLOG_ERROR, "kevent: unable to add event");
+ return -1;
+ }
+
+ /* mark the vent as not registered */
+ ev->index = -1;
+ return 0;
+}
+/* }}} */
+
+#endif /* HAVE_KQUEUE */
diff --git a/sapi/fpm/fpm/events/kqueue.h b/sapi/fpm/fpm/events/kqueue.h
new file mode 100644
index 000000000..aeddce074
--- /dev/null
+++ b/sapi/fpm/fpm/events/kqueue.h
@@ -0,0 +1,29 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef FPM_EVENTS_KQUEUE_H
+#define FPM_EVENTS_KQUEUE_H
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+
+struct fpm_event_module_s *fpm_event_kqueue_module();
+
+#endif /* FPM_EVENTS_KQUEUE_H */
diff --git a/sapi/fpm/fpm/events/poll.c b/sapi/fpm/fpm/events/poll.c
new file mode 100644
index 000000000..41ab4ca63
--- /dev/null
+++ b/sapi/fpm/fpm/events/poll.c
@@ -0,0 +1,276 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+#include "../fpm.h"
+#include "../zlog.h"
+
+#if HAVE_POLL
+
+#include <poll.h>
+#include <errno.h>
+#include <string.h>
+
+static int fpm_event_poll_init(int max);
+static int fpm_event_poll_clean();
+static int fpm_event_poll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
+static int fpm_event_poll_add(struct fpm_event_s *ev);
+static int fpm_event_poll_remove(struct fpm_event_s *ev);
+
+static struct fpm_event_module_s poll_module = {
+ .name = "poll",
+ .support_edge_trigger = 0,
+ .init = fpm_event_poll_init,
+ .clean = fpm_event_poll_clean,
+ .wait = fpm_event_poll_wait,
+ .add = fpm_event_poll_add,
+ .remove = fpm_event_poll_remove,
+};
+
+static struct pollfd *pollfds = NULL;
+static struct pollfd *active_pollfds = NULL;
+static int npollfds = 0;
+static int next_free_slot = 0;
+#endif /* HAVE_POLL */
+
+/*
+ * return the module configuration
+ */
+struct fpm_event_module_s *fpm_event_poll_module() /* {{{ */
+{
+#if HAVE_POLL
+ return &poll_module;
+#else
+ return NULL;
+#endif /* HAVE_POLL */
+}
+/* }}} */
+
+#if HAVE_POLL
+
+/*
+ * Init the module
+ */
+static int fpm_event_poll_init(int max) /* {{{ */
+{
+ int i;
+
+ if (max < 1) {
+ return 0;
+ }
+
+ /* alloc and clear pollfds */
+ pollfds = malloc(sizeof(struct pollfd) * max);
+ if (!pollfds) {
+ zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
+ return -1;
+ }
+ memset(pollfds, 0, sizeof(struct pollfd) * max);
+
+ /* set all fd to -1 in order to ensure it's not set */
+ for (i = 0; i < max; i++) {
+ pollfds[i].fd = -1;
+ }
+
+ /* alloc and clear active_pollfds */
+ active_pollfds = malloc(sizeof(struct pollfd) * max);
+ if (!active_pollfds) {
+ free(pollfds);
+ zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
+ return -1;
+ }
+ memset(active_pollfds, 0, sizeof(struct pollfd) * max);
+
+ /* save max */
+ npollfds = max;
+ return 0;
+}
+/* }}} */
+
+/*
+ * Clean the module
+ */
+static int fpm_event_poll_clean() /* {{{ */
+{
+ /* free pollfds */
+ if (pollfds) {
+ free(pollfds);
+ pollfds = NULL;
+ }
+
+ /* free active_pollfds */
+ if (active_pollfds) {
+ free(active_pollfds);
+ active_pollfds = NULL;
+ }
+
+ npollfds = 0;
+ return 0;
+}
+/* }}} */
+
+/*
+ * wait for events or timeout
+ */
+static int fpm_event_poll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
+{
+ int ret;
+ struct fpm_event_queue_s *q;
+
+ if (npollfds > 0) {
+ /* copy pollfds because poll() alters it */
+ memcpy(active_pollfds, pollfds, sizeof(struct pollfd) * npollfds);
+ }
+
+ /* wait for inconming event or timeout */
+ ret = poll(active_pollfds, npollfds, timeout);
+ if (ret == -1) {
+
+ /* trigger error unless signal interrupt */
+ if (errno != EINTR) {
+ zlog(ZLOG_WARNING, "poll() returns %d", errno);
+ return -1;
+ }
+ }
+
+ /* events have been triggered */
+ if (ret > 0) {
+
+ /* trigger POLLIN events */
+ q = queue;
+ while (q) {
+ /* ensure ev->index is valid */
+ if (q->ev && q->ev->index >= 0 && q->ev->index < npollfds && q->ev->fd == active_pollfds[q->ev->index].fd) {
+
+ /* has the event has been triggered ? */
+ if (active_pollfds[q->ev->index].revents & POLLIN) {
+
+ /* fire the event */
+ fpm_event_fire(q->ev);
+
+ /* sanity check */
+ if (fpm_globals.parent_pid != getpid()) {
+ return -2;
+ }
+ }
+ }
+ q = q->next; /* iterate */
+ }
+ }
+
+ return ret;
+}
+/* }}} */
+
+/*
+ * Add a FD to the fd set
+ */
+static int fpm_event_poll_add(struct fpm_event_s *ev) /* {{{ */
+{
+ int i;
+
+ /* do we have a direct free slot */
+ if (pollfds[next_free_slot].fd == -1) {
+ /* register the event */
+ pollfds[next_free_slot].fd = ev->fd;
+ pollfds[next_free_slot].events = POLLIN;
+
+ /* remember the event place in the fd list and suppose next slot is free */
+ ev->index = next_free_slot++;
+ if (next_free_slot >= npollfds) {
+ next_free_slot = 0;
+ }
+ return 0;
+ }
+
+ /* let's search */
+ for (i = 0; i < npollfds; i++) {
+ if (pollfds[i].fd != -1) {
+ /* not free */
+ continue;
+ }
+
+ /* register the event */
+ pollfds[i].fd = ev->fd;
+ pollfds[i].events = POLLIN;
+
+ /* remember the event place in the fd list and suppose next slot is free */
+ ev->index = next_free_slot++;
+ if (next_free_slot >= npollfds) {
+ next_free_slot = 0;
+ }
+ return 0;
+ }
+
+ zlog(ZLOG_ERROR, "poll: not enought space to add event (fd=%d)", ev->fd);
+ return -1;
+}
+/* }}} */
+
+/*
+ * Remove a FD from the fd set
+ */
+static int fpm_event_poll_remove(struct fpm_event_s *ev) /* {{{ */
+{
+ int i;
+
+ /* do we have a direct access */
+ if (ev->index >= 0 && ev->index < npollfds && pollfds[ev->index].fd == ev->fd) {
+ /* remember this slot as free */
+ next_free_slot = ev->index;
+
+ /* clear event in pollfds */
+ pollfds[ev->index].fd = -1;
+ pollfds[ev->index].events = 0;
+
+ /* mark the event as not registered */
+ ev->index = -1;
+
+ return 0;
+ }
+
+ /* let's search */
+ for (i = 0; i < npollfds; i++) {
+
+ if (pollfds[i].fd != ev->fd) {
+ /* not found */
+ continue;
+ }
+
+ /* remember this slot as free */
+ next_free_slot = i;
+
+ /* clear event in pollfds */
+ pollfds[i].fd = -1;
+ pollfds[i].events = 0;
+
+ /* mark the event as not registered */
+ ev->index = -1;
+
+ return 0;
+ }
+
+ zlog(ZLOG_ERROR, "poll: unable to remove event: not found (fd=%d, index=%d)", ev->fd, ev->index);
+ return -1;
+}
+/* }}} */
+
+#endif /* HAVE_POLL */
diff --git a/sapi/fpm/fpm/events/poll.h b/sapi/fpm/fpm/events/poll.h
new file mode 100644
index 000000000..601a03b3a
--- /dev/null
+++ b/sapi/fpm/fpm/events/poll.h
@@ -0,0 +1,29 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef FPM_EVENTS_POLL_H
+#define FPM_EVENTS_POLL_H
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+
+struct fpm_event_module_s *fpm_event_poll_module();
+
+#endif /* FPM_EVENTS_POLL_H */
diff --git a/sapi/fpm/fpm/events/port.c b/sapi/fpm/fpm/events/port.c
new file mode 100644
index 000000000..6564ff245
--- /dev/null
+++ b/sapi/fpm/fpm/events/port.c
@@ -0,0 +1,185 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+#include "../fpm.h"
+#include "../zlog.h"
+
+#if HAVE_PORT
+
+#include <port.h>
+#include <poll.h>
+#include <errno.h>
+
+static int fpm_event_port_init(int max);
+static int fpm_event_port_clean();
+static int fpm_event_port_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
+static int fpm_event_port_add(struct fpm_event_s *ev);
+static int fpm_event_port_remove(struct fpm_event_s *ev);
+
+static struct fpm_event_module_s port_module = {
+ .name = "port",
+ .support_edge_trigger = 0,
+ .init = fpm_event_port_init,
+ .clean = fpm_event_port_clean,
+ .wait = fpm_event_port_wait,
+ .add = fpm_event_port_add,
+ .remove = fpm_event_port_remove,
+};
+
+port_event_t *events = NULL;
+int nevents = 0;
+static int pfd = -1;
+
+#endif /* HAVE_PORT */
+
+struct fpm_event_module_s *fpm_event_port_module() /* {{{ */
+{
+#if HAVE_PORT
+ return &port_module;
+#else
+ return NULL;
+#endif /* HAVE_PORT */
+}
+/* }}} */
+
+#if HAVE_PORT
+
+/*
+ * Init the module
+ */
+static int fpm_event_port_init(int max) /* {{{ */
+{
+ /* open port */
+ pfd = port_create();
+ if (pfd < 0) {
+ zlog(ZLOG_ERROR, "port: unable to initialize port_create()");
+ return -1;
+ }
+
+ if (max < 1) {
+ return 0;
+ }
+
+ /* alloc and clear active_pollfds */
+ events = malloc(sizeof(port_event_t) * max);
+ if (!events) {
+ zlog(ZLOG_ERROR, "port: Unable to allocate %d events", max);
+ return -1;
+ }
+
+ nevents = max;
+ return 0;
+}
+/* }}} */
+
+/*
+ * Clean the module
+ */
+static int fpm_event_port_clean() /* {{{ */
+{
+ if (pfd > -1) {
+ close(pfd);
+ pfd = -1;
+ }
+
+ if (events) {
+ free(events);
+ events = NULL;
+ }
+
+ nevents = 0;
+ return 0;
+}
+/* }}} */
+
+/*
+ * wait for events or timeout
+ */
+static int fpm_event_port_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
+{
+ int ret, i, nget;
+ timespec_t t;
+
+ /* convert timeout into timespec_t */
+ t.tv_sec = (int)(timeout / 1000);
+ t.tv_nsec = (timeout % 1000) * 1000 * 1000;
+
+ /* wait for inconming event or timeout. We want at least one event or timeout */
+ nget = 1;
+ ret = port_getn(pfd, events, nevents, &nget, &t);
+ if (ret < 0) {
+
+ /* trigger error unless signal interrupt or timeout */
+ if (errno != EINTR && errno != ETIME) {
+ zlog(ZLOG_WARNING, "poll() returns %d", errno);
+ return -1;
+ }
+ }
+
+ for (i = 0; i < nget; i++) {
+
+ /* do we have a ptr to the event ? */
+ if (!events[i].portev_user) {
+ continue;
+ }
+
+ /* fire the event */
+ fpm_event_fire((struct fpm_event_s *)events[i].portev_user);
+
+ /* sanity check */
+ if (fpm_globals.parent_pid != getpid()) {
+ return -2;
+ }
+ }
+ return nget;
+}
+/* }}} */
+
+/*
+ * Add a FD to the fd set
+ */
+static int fpm_event_port_add(struct fpm_event_s *ev) /* {{{ */
+{
+ /* add the event to port */
+ if (port_associate(pfd, PORT_SOURCE_FD, ev->fd, POLLIN, (void *)ev) < 0) {
+ zlog(ZLOG_ERROR, "port: unable to add the event");
+ return -1;
+ }
+ return 0;
+}
+/* }}} */
+
+/*
+ * Remove a FD from the fd set
+ */
+static int fpm_event_port_remove(struct fpm_event_s *ev) /* {{{ */
+{
+ /* remove the event from port */
+ if (port_dissociate(pfd, PORT_SOURCE_FD, ev->fd) < 0) {
+ zlog(ZLOG_ERROR, "port: unable to add the event");
+ return -1;
+ }
+ return 0;
+}
+/* }}} */
+
+#endif /* HAVE_PORT */
diff --git a/sapi/fpm/fpm/events/port.h b/sapi/fpm/fpm/events/port.h
new file mode 100644
index 000000000..a48b3f624
--- /dev/null
+++ b/sapi/fpm/fpm/events/port.h
@@ -0,0 +1,29 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef FPM_EVENTS_PORT_H
+#define FPM_EVENTS_PORT_H
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+
+struct fpm_event_module_s *fpm_event_port_module();
+
+#endif /* FPM_EVENTS_PORT_H */
diff --git a/sapi/fpm/fpm/events/select.c b/sapi/fpm/fpm/events/select.c
new file mode 100644
index 000000000..03a715840
--- /dev/null
+++ b/sapi/fpm/fpm/events/select.c
@@ -0,0 +1,175 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+#include "../fpm.h"
+#include "../zlog.h"
+
+#if HAVE_SELECT
+
+/* According to POSIX.1-2001 */
+#include <sys/select.h>
+
+/* According to earlier standards */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <errno.h>
+
+static int fpm_event_select_init(int max);
+static int fpm_event_select_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
+static int fpm_event_select_add(struct fpm_event_s *ev);
+static int fpm_event_select_remove(struct fpm_event_s *ev);
+
+static struct fpm_event_module_s select_module = {
+ .name = "select",
+ .support_edge_trigger = 0,
+ .init = fpm_event_select_init,
+ .clean = NULL,
+ .wait = fpm_event_select_wait,
+ .add = fpm_event_select_add,
+ .remove = fpm_event_select_remove,
+};
+
+static fd_set fds;
+
+#endif /* HAVE_SELECT */
+
+/*
+ * return the module configuration
+ */
+struct fpm_event_module_s *fpm_event_select_module() /* {{{ */
+{
+#if HAVE_SELECT
+ return &select_module;
+#else
+ return NULL;
+#endif /* HAVE_SELECT */
+}
+/* }}} */
+
+#if HAVE_SELECT
+
+/*
+ * Init the module
+ */
+static int fpm_event_select_init(int max) /* {{{ */
+{
+ FD_ZERO(&fds);
+ return 0;
+}
+/* }}} */
+
+
+/*
+ * wait for events or timeout
+ */
+static int fpm_event_select_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
+{
+ int ret;
+ struct fpm_event_queue_s *q;
+ fd_set current_fds;
+ struct timeval t;
+
+ /* copy fds because select() alters it */
+ current_fds = fds;
+
+ /* fill struct timeval with timeout */
+ t.tv_sec = timeout / 1000;
+ t.tv_usec = (timeout % 1000) * 1000;
+
+ /* wait for inconming event or timeout */
+ ret = select(FD_SETSIZE, &current_fds, NULL, NULL, &t);
+ if (ret == -1) {
+
+ /* trigger error unless signal interrupt */
+ if (errno != EINTR) {
+ zlog(ZLOG_WARNING, "poll() returns %d", errno);
+ return -1;
+ }
+ }
+
+ /* events have been triggered */
+ if (ret > 0) {
+
+ /* trigger POLLIN events */
+ q = queue;
+ while (q) {
+ if (q->ev) { /* sanity check */
+
+ /* check if the event has been triggered */
+ if (FD_ISSET(q->ev->fd, &current_fds)) {
+
+ /* fire the event */
+ fpm_event_fire(q->ev);
+
+ /* sanity check */
+ if (fpm_globals.parent_pid != getpid()) {
+ return -2;
+ }
+ }
+ }
+ q = q->next; /* iterate */
+ }
+ }
+ return ret;
+
+}
+/* }}} */
+
+/*
+ * Add a FD to the fd set
+ */
+static int fpm_event_select_add(struct fpm_event_s *ev) /* {{{ */
+{
+ /* check size limitation */
+ if (ev->fd >= FD_SETSIZE) {
+ zlog(ZLOG_ERROR, "select: not enough space in the select fd list (max = %d). Please consider using another event mechanism.", FD_SETSIZE);
+ return -1;
+ }
+
+ /* add the FD if not already in */
+ if (!FD_ISSET(ev->fd, &fds)) {
+ FD_SET(ev->fd, &fds);
+ ev->index = ev->fd;
+ }
+
+ return 0;
+}
+/* }}} */
+
+/*
+ * Remove a FD from the fd set
+ */
+static int fpm_event_select_remove(struct fpm_event_s *ev) /* {{{ */
+{
+ /* remove the fd if it's in */
+ if (FD_ISSET(ev->fd, &fds)) {
+ FD_CLR(ev->fd, &fds);
+ ev->index = -1;
+ }
+
+ return 0;
+}
+/* }}} */
+
+#endif /* HAVE_SELECT */
diff --git a/sapi/fpm/fpm/events/select.h b/sapi/fpm/fpm/events/select.h
new file mode 100644
index 000000000..6fda70fbd
--- /dev/null
+++ b/sapi/fpm/fpm/events/select.h
@@ -0,0 +1,29 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2012 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Jerome Loyet <jerome@loyet.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef FPM_EVENTS_SELECT_H
+#define FPM_EVENTS_SELECT_H
+
+#include "../fpm_config.h"
+#include "../fpm_events.h"
+
+struct fpm_event_module_s *fpm_event_select_module();
+
+#endif /* FPM_EVENTS_SELECT_H */
diff --git a/sapi/fpm/fpm/fastcgi.c b/sapi/fpm/fpm/fastcgi.c
index 22a8f3a2f..212b6ff1d 100644
--- a/sapi/fpm/fpm/fastcgi.c
+++ b/sapi/fpm/fpm/fastcgi.c
@@ -29,9 +29,9 @@
#include <limits.h>
#include <php_config.h>
-#include <fpm/fpm.h>
-#include <fpm/fpm_request.h>
-#include <fpm/zlog.h>
+#include "fpm.h"
+#include "fpm_request.h"
+#include "zlog.h"
#ifdef _WIN32
@@ -142,7 +142,6 @@ typedef union _sa_t {
static HashTable fcgi_mgmt_vars;
static int is_initialized = 0;
-static int is_fastcgi = 0;
static int in_shutdown = 0;
static in_addr_t *allowed_clients = NULL;
@@ -186,10 +185,6 @@ static void fcgi_setup_signals(void)
int fcgi_init(void)
{
if (!is_initialized) {
-#ifndef _WIN32
- sa_t sa;
- socklen_t len = sizeof(sa);
-#endif
zend_hash_init(&fcgi_mgmt_vars, 0, NULL, fcgi_free_mgmt_var_cb, 1);
fcgi_set_mgmt_var("FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS") - 1, "0", sizeof("0")-1);
@@ -204,9 +199,7 @@ int fcgi_init(void)
return 0;
}
# endif
- if ((GetStdHandle(STD_OUTPUT_HANDLE) == INVALID_HANDLE_VALUE) &&
- (GetStdHandle(STD_ERROR_HANDLE) == INVALID_HANDLE_VALUE) &&
- (GetStdHandle(STD_INPUT_HANDLE) != INVALID_HANDLE_VALUE)) {
+ {
char *str;
DWORD pipe_mode = PIPE_READMODE_BYTE | PIPE_WAIT;
HANDLE pipe = GetStdHandle(STD_INPUT_HANDLE);
@@ -225,36 +218,14 @@ int fcgi_init(void)
if (str != NULL) {
fcgi_accept_mutex = (HANDLE) atoi(str);
}
- return is_fastcgi = 1;
- } else {
- return is_fastcgi = 0;
+ return 1;
}
#else
- errno = 0;
- if (getpeername(0, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) {
- fcgi_setup_signals();
- return is_fastcgi = 1;
- } else {
- return is_fastcgi = 0;
- }
+ fcgi_setup_signals();
+ return 1;
#endif
}
- return is_fastcgi;
-}
-
-
-int fcgi_is_fastcgi(void)
-{
- if (!is_initialized) {
- return fcgi_init();
- } else {
- return is_fastcgi;
- }
-}
-
-void fcgi_set_is_fastcgi(int new_value)
-{
- is_fastcgi = new_value;
+ return 1;
}
void fcgi_set_in_shutdown(int new_value)
@@ -267,7 +238,6 @@ void fcgi_shutdown(void)
if (is_initialized) {
zend_hash_destroy(&fcgi_mgmt_vars);
}
- is_fastcgi = 0;
if (allowed_clients) {
free(allowed_clients);
}
@@ -298,7 +268,7 @@ void fcgi_set_allowed_clients(char *ip)
}
allowed_clients[n] = inet_addr(cur);
if (allowed_clients[n] == INADDR_NONE) {
- fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS or listen.allowed_clients\n", cur);
+ zlog(ZLOG_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur);
}
n++;
cur = end;
@@ -846,7 +816,7 @@ int fcgi_accept_request(fcgi_request *req)
n++;
}
if (!allowed) {
- fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr));
+ zlog(ZLOG_ERROR, "Connection disallowed: IP address '%s' has been dropped.", inet_ntoa(sa.sa_inet.sin_addr));
closesocket(req->fd);
req->fd = -1;
continue;
@@ -902,7 +872,7 @@ int fcgi_accept_request(fcgi_request *req)
}
fcgi_close(req, 1, 0);
} else {
- fprintf(stderr, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
+ zlog(ZLOG_ERROR, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
fcgi_close(req, 1, 0);
}
#endif
@@ -976,7 +946,7 @@ int fcgi_flush(fcgi_request *req, int close)
return 1;
}
-int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len)
+ssize_t fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len)
{
int limit, rest;
diff --git a/sapi/fpm/fpm/fastcgi.h b/sapi/fpm/fpm/fastcgi.h
index 4129def05..7a9f3ef36 100644
--- a/sapi/fpm/fpm/fastcgi.h
+++ b/sapi/fpm/fpm/fastcgi.h
@@ -114,12 +114,10 @@ typedef struct _fcgi_request {
int fcgi_init(void);
void fcgi_shutdown(void);
-int fcgi_is_fastcgi(void);
void fcgi_init_request(fcgi_request *req, int listen_socket);
int fcgi_accept_request(fcgi_request *req);
int fcgi_finish_request(fcgi_request *req, int force_close);
-void fcgi_set_is_fastcgi(int new_value);
void fcgi_set_in_shutdown(int);
void fcgi_set_allowed_clients(char *);
void fcgi_close(fcgi_request *req, int force, int destroy);
@@ -129,7 +127,7 @@ char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val);
int fcgi_read(fcgi_request *req, char *str, int len);
-int fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len);
+ssize_t fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len);
int fcgi_flush(fcgi_request *req, int close);
void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len);
diff --git a/sapi/fpm/fpm/fpm.c b/sapi/fpm/fpm/fpm.c
index 57efcfd75..96aabbfc4 100644
--- a/sapi/fpm/fpm/fpm.c
+++ b/sapi/fpm/fpm/fpm.c
@@ -36,7 +36,8 @@ struct fpm_globals_s fpm_globals = {
.listening_socket = 0,
.max_requests = 0,
.is_child = 0,
- .test_successful = 0
+ .test_successful = 0,
+ .heartbeat = 0
};
int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int test_conf) /* {{{ */
@@ -51,7 +52,6 @@ int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int t
if (0 > fpm_php_init_main() ||
0 > fpm_stdio_init_main() ||
- 0 > fpm_log_init_main() ||
0 > fpm_conf_init_main(test_conf) ||
0 > fpm_unix_init_main() ||
0 > fpm_scoreboard_init_main() ||
@@ -66,11 +66,13 @@ int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int t
if (fpm_globals.test_successful) {
exit(0);
} else {
+ zlog(ZLOG_ERROR, "FPM initialization failed");
return -1;
}
}
if (0 > fpm_conf_write_pid()) {
+ zlog(ZLOG_ERROR, "FPM initialization failed");
return -1;
}
diff --git a/sapi/fpm/fpm/fpm.h b/sapi/fpm/fpm/fpm.h
index 3c6f798fb..bfeac4d67 100644
--- a/sapi/fpm/fpm/fpm.h
+++ b/sapi/fpm/fpm/fpm.h
@@ -24,6 +24,7 @@ struct fpm_globals_s {
int max_requests; /* for this child */
int is_child;
int test_successful;
+ int heartbeat;
};
extern struct fpm_globals_s fpm_globals;
diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c
index 94580194f..35058b0ea 100644
--- a/sapi/fpm/fpm/fpm_children.c
+++ b/sapi/fpm/fpm/fpm_children.c
@@ -147,13 +147,13 @@ static void fpm_child_init(struct fpm_worker_pool_s *wp) /* {{{ */
{
fpm_globals.max_requests = wp->config->pm_max_requests;
- if (0 > fpm_stdio_init_child(wp) ||
- 0 > fpm_log_init_child(wp) ||
- 0 > fpm_status_init_child(wp) ||
- 0 > fpm_unix_init_child(wp) ||
- 0 > fpm_signals_init_child() ||
- 0 > fpm_env_init_child(wp) ||
- 0 > fpm_php_init_child(wp)) {
+ if (0 > fpm_stdio_init_child(wp) ||
+ 0 > fpm_log_init_child(wp) ||
+ 0 > fpm_status_init_child(wp) ||
+ 0 > fpm_unix_init_child(wp) ||
+ 0 > fpm_signals_init_child() ||
+ 0 > fpm_env_init_child(wp) ||
+ 0 > fpm_php_init_child(wp)) {
zlog(ZLOG_ERROR, "[pool %s] child failed to initialize", wp->config->name);
exit(255);
@@ -292,7 +292,7 @@ void fpm_children_bury() /* {{{ */
}
}
} else {
- zlog(ZLOG_ALERT, "oops, unknown child (%d) exited %s", pid, buf);
+ zlog(ZLOG_ALERT, "oops, unknown child (%d) exited %s. Please open a bug report (https://bugs.php.net).", pid, buf);
}
}
}
@@ -305,7 +305,7 @@ static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) /
c = fpm_child_alloc();
if (!c) {
- zlog(ZLOG_ERROR, "[pool %s] malloc failed", wp->config->name);
+ zlog(ZLOG_ERROR, "[pool %s] unable to malloc new child", wp->config->name);
return 0;
}
@@ -344,6 +344,7 @@ static void fpm_child_resources_use(struct fpm_child_s *child) /* {{{ */
}
fpm_scoreboard_free(wp->scoreboard);
}
+
fpm_scoreboard_child_use(child->wp->scoreboard, child->scoreboard_i, getpid());
fpm_stdio_child_use_pipes(child);
fpm_child_free(child);
@@ -362,6 +363,7 @@ int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to
pid_t pid;
struct fpm_child_s *child;
int max;
+ static int warned = 0;
if (wp->config->pm == PM_STYLE_DYNAMIC) {
if (!in_event_loop) { /* starting */
@@ -369,11 +371,26 @@ int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to
} else {
max = wp->running_children + nb_to_spawn;
}
+ } else if (wp->config->pm == PM_STYLE_ONDEMAND) {
+ if (!in_event_loop) { /* starting */
+ max = 0; /* do not create any child at startup */
+ } else {
+ max = wp->running_children + nb_to_spawn;
+ }
} else { /* PM_STYLE_STATIC */
max = wp->config->pm_max_children;
}
- while (fpm_pctl_can_spawn_children() && wp->running_children < max) {
+ /*
+ * fork children while:
+ * - fpm_pctl_can_spawn_children : FPM is running in a NORMAL state (aka not restart, stop or reload)
+ * - wp->running_children < max : there is less than the max process for the current pool
+ * - (fpm_global_config.process_max < 1 || fpm_globals.running_children < fpm_global_config.process_max):
+ * if fpm_global_config.process_max is set, FPM has not fork this number of processes (globaly)
+ */
+ while (fpm_pctl_can_spawn_children() && wp->running_children < max && (fpm_global_config.process_max < 1 || fpm_globals.running_children < fpm_global_config.process_max)) {
+
+ warned = 0;
child = fpm_resources_prepare(wp);
if (!child) {
@@ -406,12 +423,33 @@ int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to
}
+ if (!warned && fpm_global_config.process_max > 0 && fpm_globals.running_children >= fpm_global_config.process_max) {
+ warned = 1;
+ zlog(ZLOG_WARNING, "The maximum number of processes has been reached. Please review your configuration and consider raising 'process.max'");
+ }
+
return 1; /* we are done */
}
/* }}} */
int fpm_children_create_initial(struct fpm_worker_pool_s *wp) /* {{{ */
{
+ if (wp->config->pm == PM_STYLE_ONDEMAND) {
+ wp->ondemand_event = (struct fpm_event_s *)malloc(sizeof(struct fpm_event_s));
+
+ if (!wp->ondemand_event) {
+ zlog(ZLOG_ERROR, "[pool %s] unable to malloc the ondemand socket event", wp->config->name);
+ // FIXME handle crash
+ return 1;
+ }
+
+ memset(wp->ondemand_event, 0, sizeof(struct fpm_event_s));
+ fpm_event_set(wp->ondemand_event, wp->listening_socket, FPM_EV_READ | FPM_EV_EDGE, fpm_pctl_on_socket_accept, wp);
+ wp->socket_event_set = 1;
+ fpm_event_add(wp->ondemand_event, 0);
+
+ return 1;
+ }
return fpm_children_make(wp, 0 /* not in event loop yet */, 0, 1);
}
/* }}} */
diff --git a/sapi/fpm/fpm/fpm_cleanup.c b/sapi/fpm/fpm/fpm_cleanup.c
index 3f59e6585..260ddb32e 100644
--- a/sapi/fpm/fpm/fpm_cleanup.c
+++ b/sapi/fpm/fpm/fpm_cleanup.c
@@ -8,7 +8,6 @@
#include "fpm_arrays.h"
#include "fpm_cleanup.h"
-#include "zlog.h"
struct cleanup_s {
int type;
diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c
index 6a37ae27f..61f066fc9 100644
--- a/sapi/fpm/fpm/fpm_conf.c
+++ b/sapi/fpm/fpm/fpm_conf.c
@@ -31,6 +31,7 @@
#include "zend_ini_scanner.h"
#include "zend_globals.h"
#include "zend_stream.h"
+#include "php_syslog.h"
#include "fpm.h"
#include "fpm_conf.h"
@@ -42,72 +43,96 @@
#include "fpm_shm.h"
#include "fpm_status.h"
#include "fpm_log.h"
+#include "fpm_events.h"
#include "zlog.h"
#define STR2STR(a) (a ? a : "undefined")
#define BOOL2STR(a) (a ? "yes" : "no")
-#define PM2STR(a) (a == PM_STYLE_STATIC ? "static" : "dynamic")
#define GO(field) offsetof(struct fpm_global_config_s, field)
#define WPO(field) offsetof(struct fpm_worker_pool_config_s, field)
static int fpm_conf_load_ini_file(char *filename TSRMLS_DC);
static char *fpm_conf_set_integer(zval *value, void **config, intptr_t offset);
+static char *fpm_conf_set_long(zval *value, void **config, intptr_t offset);
static char *fpm_conf_set_time(zval *value, void **config, intptr_t offset);
static char *fpm_conf_set_boolean(zval *value, void **config, intptr_t offset);
static char *fpm_conf_set_string(zval *value, void **config, intptr_t offset);
static char *fpm_conf_set_log_level(zval *value, void **config, intptr_t offset);
static char *fpm_conf_set_rlimit_core(zval *value, void **config, intptr_t offset);
static char *fpm_conf_set_pm(zval *value, void **config, intptr_t offset);
+#ifdef HAVE_SYSLOG_H
+static char *fpm_conf_set_syslog_facility(zval *value, void **config, intptr_t offset);
+#endif
-struct fpm_global_config_s fpm_global_config = { .daemonize = 1 };
+struct fpm_global_config_s fpm_global_config = {
+ .daemonize = 1,
+#ifdef HAVE_SYSLOG_H
+ .syslog_facility = -1,
+#endif
+ .process_max = 0,
+};
static struct fpm_worker_pool_s *current_wp = NULL;
static int ini_recursion = 0;
static char *ini_filename = NULL;
static int ini_lineno = 0;
static char *ini_include = NULL;
+/*
+ * Please keep the same order as in fpm_conf.h and in php-fpm.conf.in
+ */
static struct ini_value_parser_s ini_fpm_global_options[] = {
- { "emergency_restart_threshold", &fpm_conf_set_integer, GO(emergency_restart_threshold) },
- { "emergency_restart_interval", &fpm_conf_set_time, GO(emergency_restart_interval) },
- { "process_control_timeout", &fpm_conf_set_time, GO(process_control_timeout) },
- { "daemonize", &fpm_conf_set_boolean, GO(daemonize) },
- { "pid", &fpm_conf_set_string, GO(pid_file) },
- { "error_log", &fpm_conf_set_string, GO(error_log) },
- { "log_level", &fpm_conf_set_log_level, 0 },
- { "rlimit_files", &fpm_conf_set_integer, GO(rlimit_files) },
- { "rlimit_core", &fpm_conf_set_rlimit_core, GO(rlimit_core) },
+ { "pid", &fpm_conf_set_string, GO(pid_file) },
+ { "error_log", &fpm_conf_set_string, GO(error_log) },
+#ifdef HAVE_SYSLOG_H
+ { "syslog.ident", &fpm_conf_set_string, GO(syslog_ident) },
+ { "syslog.facility", &fpm_conf_set_syslog_facility, GO(syslog_facility) },
+#endif
+ { "log_level", &fpm_conf_set_log_level, GO(log_level) },
+ { "emergency_restart_threshold", &fpm_conf_set_integer, GO(emergency_restart_threshold) },
+ { "emergency_restart_interval", &fpm_conf_set_time, GO(emergency_restart_interval) },
+ { "process_control_timeout", &fpm_conf_set_time, GO(process_control_timeout) },
+ { "process.max", &fpm_conf_set_integer, GO(process_max) },
+ { "daemonize", &fpm_conf_set_boolean, GO(daemonize) },
+ { "rlimit_files", &fpm_conf_set_integer, GO(rlimit_files) },
+ { "rlimit_core", &fpm_conf_set_rlimit_core, GO(rlimit_core) },
+ { "events.mechanism", &fpm_conf_set_string, GO(events_mechanism) },
{ 0, 0, 0 }
};
+/*
+ * Please keep the same order as in fpm_conf.h and in php-fpm.conf.in
+ */
static struct ini_value_parser_s ini_fpm_pool_options[] = {
{ "prefix", &fpm_conf_set_string, WPO(prefix) },
{ "user", &fpm_conf_set_string, WPO(user) },
{ "group", &fpm_conf_set_string, WPO(group) },
- { "chroot", &fpm_conf_set_string, WPO(chroot) },
- { "chdir", &fpm_conf_set_string, WPO(chdir) },
- { "request_terminate_timeout", &fpm_conf_set_time, WPO(request_terminate_timeout) },
- { "request_slowlog_timeout", &fpm_conf_set_time, WPO(request_slowlog_timeout) },
- { "slowlog", &fpm_conf_set_string, WPO(slowlog) },
- { "rlimit_files", &fpm_conf_set_integer, WPO(rlimit_files) },
- { "rlimit_core", &fpm_conf_set_rlimit_core, WPO(rlimit_core) },
- { "catch_workers_output", &fpm_conf_set_boolean, WPO(catch_workers_output) },
{ "listen", &fpm_conf_set_string, WPO(listen_address) },
+ { "listen.backlog", &fpm_conf_set_integer, WPO(listen_backlog) },
{ "listen.owner", &fpm_conf_set_string, WPO(listen_owner) },
{ "listen.group", &fpm_conf_set_string, WPO(listen_group) },
{ "listen.mode", &fpm_conf_set_string, WPO(listen_mode) },
- { "listen.backlog", &fpm_conf_set_integer, WPO(listen_backlog) },
{ "listen.allowed_clients", &fpm_conf_set_string, WPO(listen_allowed_clients) },
{ "pm", &fpm_conf_set_pm, WPO(pm) },
- { "pm.max_requests", &fpm_conf_set_integer, WPO(pm_max_requests) },
{ "pm.max_children", &fpm_conf_set_integer, WPO(pm_max_children) },
{ "pm.start_servers", &fpm_conf_set_integer, WPO(pm_start_servers) },
{ "pm.min_spare_servers", &fpm_conf_set_integer, WPO(pm_min_spare_servers) },
{ "pm.max_spare_servers", &fpm_conf_set_integer, WPO(pm_max_spare_servers) },
+ { "pm.process_idle_timeout", &fpm_conf_set_time, WPO(pm_process_idle_timeout) },
+ { "pm.max_requests", &fpm_conf_set_integer, WPO(pm_max_requests) },
{ "pm.status_path", &fpm_conf_set_string, WPO(pm_status_path) },
{ "ping.path", &fpm_conf_set_string, WPO(ping_path) },
{ "ping.response", &fpm_conf_set_string, WPO(ping_response) },
{ "access.log", &fpm_conf_set_string, WPO(access_log) },
{ "access.format", &fpm_conf_set_string, WPO(access_format) },
+ { "slowlog", &fpm_conf_set_string, WPO(slowlog) },
+ { "request_slowlog_timeout", &fpm_conf_set_time, WPO(request_slowlog_timeout) },
+ { "request_terminate_timeout", &fpm_conf_set_time, WPO(request_terminate_timeout) },
+ { "rlimit_files", &fpm_conf_set_integer, WPO(rlimit_files) },
+ { "rlimit_core", &fpm_conf_set_rlimit_core, WPO(rlimit_core) },
+ { "chroot", &fpm_conf_set_string, WPO(chroot) },
+ { "chdir", &fpm_conf_set_string, WPO(chdir) },
+ { "catch_workers_output", &fpm_conf_set_boolean, WPO(catch_workers_output) },
+ { "security.limit_extensions", &fpm_conf_set_string, WPO(security_limit_extensions) },
{ 0, 0, 0 }
};
@@ -174,21 +199,25 @@ static char *fpm_conf_set_boolean(zval *value, void **config, intptr_t offset) /
static char *fpm_conf_set_string(zval *value, void **config, intptr_t offset) /* {{{ */
{
- char *new;
- char **old = (char **) ((char *) *config + offset);
- if (*old) {
- return "it's already been defined. Can't do that twice.";
+ char **config_val = (char **) ((char *) *config + offset);
+
+ if (!config_val) {
+ return "internal error: NULL value";
+ }
+
+ /* Check if there is a previous value to deallocate */
+ if (*config_val) {
+ free(*config_val);
}
- new = strdup(Z_STRVAL_P(value));
- if (!new) {
+ *config_val = strdup(Z_STRVAL_P(value));
+ if (!*config_val) {
return "fpm_conf_set_string(): strdup() failed";
}
- if (fpm_conf_expand_pool_name(&new) == -1) {
+ if (fpm_conf_expand_pool_name(config_val) == -1) {
return "Can't use '$pool' when the pool is not defined";
}
- *old = new;
return NULL;
}
/* }}} */
@@ -198,8 +227,9 @@ static char *fpm_conf_set_integer(zval *value, void **config, intptr_t offset) /
char *val = Z_STRVAL_P(value);
char *p;
+ /* we don't use strtol because we don't want to allow negative values */
for (p = val; *p; p++) {
- if ( p == val && *p == '-' ) continue;
+ if (p == val && *p == '-') continue;
if (*p < '0' || *p > '9') {
return "is not a valid number (greater or equal than zero)";
}
@@ -209,6 +239,22 @@ static char *fpm_conf_set_integer(zval *value, void **config, intptr_t offset) /
}
/* }}} */
+static char *fpm_conf_set_long(zval *value, void **config, intptr_t offset) /* {{{ */
+{
+ char *val = Z_STRVAL_P(value);
+ char *p;
+
+ for (p = val; *p; p++) {
+ if ( p == val && *p == '-' ) continue;
+ if (*p < '0' || *p > '9') {
+ return "is not a valid number (greater or equal than zero)";
+ }
+ }
+ * (long int *) ((char *) *config + offset) = atol(val);
+ return NULL;
+}
+/* }}} */
+
static char *fpm_conf_set_time(zval *value, void **config, intptr_t offset) /* {{{ */
{
char *val = Z_STRVAL_P(value);
@@ -252,25 +298,178 @@ static char *fpm_conf_set_time(zval *value, void **config, intptr_t offset) /* {
static char *fpm_conf_set_log_level(zval *value, void **config, intptr_t offset) /* {{{ */
{
char *val = Z_STRVAL_P(value);
+ int log_level;
if (!strcasecmp(val, "debug")) {
- fpm_globals.log_level = ZLOG_DEBUG;
+ log_level = ZLOG_DEBUG;
} else if (!strcasecmp(val, "notice")) {
- fpm_globals.log_level = ZLOG_NOTICE;
+ log_level = ZLOG_NOTICE;
} else if (!strcasecmp(val, "warning") || !strcasecmp(val, "warn")) {
- fpm_globals.log_level = ZLOG_WARNING;
+ log_level = ZLOG_WARNING;
} else if (!strcasecmp(val, "error")) {
- fpm_globals.log_level = ZLOG_ERROR;
+ log_level = ZLOG_ERROR;
} else if (!strcasecmp(val, "alert")) {
- fpm_globals.log_level = ZLOG_ALERT;
+ log_level = ZLOG_ALERT;
} else {
return "invalid value for 'log_level'";
}
+ * (int *) ((char *) *config + offset) = log_level;
return NULL;
}
/* }}} */
+#ifdef HAVE_SYSLOG_H
+static char *fpm_conf_set_syslog_facility(zval *value, void **config, intptr_t offset) /* {{{ */
+{
+ char *val = Z_STRVAL_P(value);
+ int *conf = (int *) ((char *) *config + offset);
+
+#ifdef LOG_AUTH
+ if (!strcasecmp(val, "AUTH")) {
+ *conf = LOG_AUTH;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_AUTHPRIV
+ if (!strcasecmp(val, "AUTHPRIV")) {
+ *conf = LOG_AUTHPRIV;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_CRON
+ if (!strcasecmp(val, "CRON")) {
+ *conf = LOG_CRON;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_DAEMON
+ if (!strcasecmp(val, "DAEMON")) {
+ *conf = LOG_DAEMON;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_FTP
+ if (!strcasecmp(val, "FTP")) {
+ *conf = LOG_FTP;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_KERN
+ if (!strcasecmp(val, "KERN")) {
+ *conf = LOG_KERN;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_LPR
+ if (!strcasecmp(val, "LPR")) {
+ *conf = LOG_LPR;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_MAIL
+ if (!strcasecmp(val, "MAIL")) {
+ *conf = LOG_MAIL;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_NEWS
+ if (!strcasecmp(val, "NEWS")) {
+ *conf = LOG_NEWS;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_SYSLOG
+ if (!strcasecmp(val, "SYSLOG")) {
+ *conf = LOG_SYSLOG;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_USER
+ if (!strcasecmp(val, "USER")) {
+ *conf = LOG_USER;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_UUCP
+ if (!strcasecmp(val, "UUCP")) {
+ *conf = LOG_UUCP;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_LOCAL0
+ if (!strcasecmp(val, "LOCAL0")) {
+ *conf = LOG_LOCAL0;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_LOCAL1
+ if (!strcasecmp(val, "LOCAL1")) {
+ *conf = LOG_LOCAL1;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_LOCAL2
+ if (!strcasecmp(val, "LOCAL2")) {
+ *conf = LOG_LOCAL2;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_LOCAL3
+ if (!strcasecmp(val, "LOCAL3")) {
+ *conf = LOG_LOCAL3;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_LOCAL4
+ if (!strcasecmp(val, "LOCAL4")) {
+ *conf = LOG_LOCAL4;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_LOCAL5
+ if (!strcasecmp(val, "LOCAL5")) {
+ *conf = LOG_LOCAL5;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_LOCAL6
+ if (!strcasecmp(val, "LOCAL6")) {
+ *conf = LOG_LOCAL6;
+ return NULL;
+ }
+#endif
+
+#ifdef LOG_LOCAL7
+ if (!strcasecmp(val, "LOCAL7")) {
+ *conf = LOG_LOCAL7;
+ return NULL;
+ }
+#endif
+
+ return "invalid value";
+}
+/* }}} */
+#endif
+
static char *fpm_conf_set_rlimit_core(zval *value, void **config, intptr_t offset) /* {{{ */
{
char *val = Z_STRVAL_P(value);
@@ -308,8 +507,10 @@ static char *fpm_conf_set_pm(zval *value, void **config, intptr_t offset) /* {{{
c->pm = PM_STYLE_STATIC;
} else if (!strcasecmp(val, "dynamic")) {
c->pm = PM_STYLE_DYNAMIC;
+ } else if (!strcasecmp(val, "ondemand")) {
+ c->pm = PM_STYLE_ONDEMAND;
} else {
- return "invalid process manager (static or dynamic)";
+ return "invalid process manager (static, dynamic or ondemand)";
}
return NULL;
}
@@ -338,7 +539,7 @@ static char *fpm_conf_set_array(zval *key, zval *value, void **config, int conve
if (convert_to_bool) {
char *err = fpm_conf_set_boolean(value, &subconf, 0);
if (err) return err;
- kv->value = strdup(b ? "On" : "Off");
+ kv->value = strdup(b ? "1" : "0");
} else {
kv->value = strdup(Z_STRVAL_P(value));
if (fpm_conf_expand_pool_name(&kv->value) == -1) {
@@ -375,6 +576,7 @@ static void *fpm_worker_pool_config_alloc() /* {{{ */
memset(wp->config, 0, sizeof(struct fpm_worker_pool_config_s));
wp->config->listen_backlog = FPM_BACKLOG_DEFAULT;
+ wp->config->pm_process_idle_timeout = 10; /* 10s by default */
if (!fpm_worker_all_pools) {
fpm_worker_all_pools = wp;
@@ -399,13 +601,24 @@ int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc) /* {{{ */
struct key_value_s *kv, *kv_next;
free(wpc->name);
- free(wpc->pm_status_path);
- free(wpc->ping_path);
- free(wpc->ping_response);
+ free(wpc->prefix);
+ free(wpc->user);
+ free(wpc->group);
free(wpc->listen_address);
free(wpc->listen_owner);
free(wpc->listen_group);
free(wpc->listen_mode);
+ free(wpc->listen_allowed_clients);
+ free(wpc->pm_status_path);
+ free(wpc->ping_path);
+ free(wpc->ping_response);
+ free(wpc->access_log);
+ free(wpc->access_format);
+ free(wpc->slowlog);
+ free(wpc->chroot);
+ free(wpc->chdir);
+ free(wpc->security_limit_extensions);
+
for (kv = wpc->php_values; kv; kv = kv_next) {
kv_next = kv->next;
free(kv->key);
@@ -424,15 +637,6 @@ int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc) /* {{{ */
free(kv->value);
free(kv);
}
- free(wpc->listen_allowed_clients);
- free(wpc->user);
- free(wpc->group);
- free(wpc->chroot);
- free(wpc->chdir);
- free(wpc->slowlog);
- free(wpc->prefix);
- free(wpc->access_log);
- free(wpc->access_format);
return 0;
}
@@ -503,12 +707,13 @@ static int fpm_conf_process_all_pools() /* {{{ */
struct fpm_worker_pool_s *wp;
if (!fpm_worker_all_pools) {
- zlog(ZLOG_ERROR, "at least one pool section must be specified in config file");
+ zlog(ZLOG_ERROR, "No pool defined. at least one pool section must be specified in config file");
return -1;
}
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
+ /* prefix */
if (wp->config->prefix && *wp->config->prefix) {
fpm_evaluate_full_path(&wp->config->prefix, NULL, NULL, 0);
@@ -518,6 +723,13 @@ static int fpm_conf_process_all_pools() /* {{{ */
}
}
+ /* user */
+ if (!wp->config->user) {
+ zlog(ZLOG_ALERT, "[pool %s] user has not been defined", wp->config->name);
+ return -1;
+ }
+
+ /* listen */
if (wp->config->listen_address && *wp->config->listen_address) {
wp->listen_address_domain = fpm_sockets_domain_from_address(wp->config->listen_address);
@@ -529,21 +741,19 @@ static int fpm_conf_process_all_pools() /* {{{ */
return -1;
}
- if (!wp->config->user) {
- zlog(ZLOG_ALERT, "[pool %s] user has not been defined", wp->config->name);
- return -1;
- }
-
- if (wp->config->pm != PM_STYLE_STATIC && wp->config->pm != PM_STYLE_DYNAMIC) {
- zlog(ZLOG_ALERT, "[pool %s] the process manager is missing (static or dynamic)", wp->config->name);
+ /* pm */
+ if (wp->config->pm != PM_STYLE_STATIC && wp->config->pm != PM_STYLE_DYNAMIC && wp->config->pm != PM_STYLE_ONDEMAND) {
+ zlog(ZLOG_ALERT, "[pool %s] the process manager is missing (static, dynamic or ondemand)", wp->config->name);
return -1;
}
+ /* pm.max_children */
if (wp->config->pm_max_children < 1) {
zlog(ZLOG_ALERT, "[pool %s] pm.max_children must be a positive value", wp->config->name);
return -1;
}
+ /* pm.start_servers, pm.min_spare_servers, pm.max_spare_servers */
if (wp->config->pm == PM_STYLE_DYNAMIC) {
struct fpm_worker_pool_config_s *config = wp->config;
@@ -559,8 +769,7 @@ static int fpm_conf_process_all_pools() /* {{{ */
if (config->pm_min_spare_servers > config->pm_max_children ||
config->pm_max_spare_servers > config->pm_max_children) {
- zlog(ZLOG_ALERT, "[pool %s] pm.min_spare_servers(%d) and pm.max_spare_servers(%d) cannot be greater than pm.max_children(%d)",
- wp->config->name, config->pm_min_spare_servers, config->pm_max_spare_servers, config->pm_max_children);
+ zlog(ZLOG_ALERT, "[pool %s] pm.min_spare_servers(%d) and pm.max_spare_servers(%d) cannot be greater than pm.max_children(%d)", wp->config->name, config->pm_min_spare_servers, config->pm_max_spare_servers, config->pm_max_children);
return -1;
}
@@ -572,47 +781,59 @@ static int fpm_conf_process_all_pools() /* {{{ */
if (config->pm_start_servers <= 0) {
config->pm_start_servers = config->pm_min_spare_servers + ((config->pm_max_spare_servers - config->pm_min_spare_servers) / 2);
zlog(ZLOG_WARNING, "[pool %s] pm.start_servers is not set. It's been set to %d.", wp->config->name, config->pm_start_servers);
+
} else if (config->pm_start_servers < config->pm_min_spare_servers || config->pm_start_servers > config->pm_max_spare_servers) {
zlog(ZLOG_ALERT, "[pool %s] pm.start_servers(%d) must not be less than pm.min_spare_servers(%d) and not greater than pm.max_spare_servers(%d)", wp->config->name, config->pm_start_servers, config->pm_min_spare_servers, config->pm_max_spare_servers);
return -1;
}
+ } else if (wp->config->pm == PM_STYLE_ONDEMAND) {
+ struct fpm_worker_pool_config_s *config = wp->config;
- }
-
- if (wp->config->slowlog && *wp->config->slowlog) {
- fpm_evaluate_full_path(&wp->config->slowlog, wp, NULL, 0);
- }
+ if (!fpm_event_support_edge_trigger()) {
+ zlog(ZLOG_ALERT, "[pool %s] ondemand process manager can ONLY be used when events.mechanisme is either epoll (Linux) or kqueue (*BSD).", wp->config->name);
+ return -1;
+ }
- if (wp->config->request_slowlog_timeout) {
-#if HAVE_FPM_TRACE
- if (! (wp->config->slowlog && *wp->config->slowlog)) {
- zlog(ZLOG_ERROR, "[pool %s] 'slowlog' must be specified for use with 'request_slowlog_timeout'", wp->config->name);
+ if (config->pm_process_idle_timeout < 1) {
+ zlog(ZLOG_ALERT, "[pool %s] pm.process_idle_timeout(%ds) must be greater than 0s", wp->config->name, config->pm_process_idle_timeout);
return -1;
}
-#else
- static int warned = 0;
- if (!warned) {
- zlog(ZLOG_WARNING, "[pool %s] 'request_slowlog_timeout' is not supported on your system", wp->config->name);
- warned = 1;
+ if (config->listen_backlog < FPM_BACKLOG_DEFAULT) {
+ zlog(ZLOG_WARNING, "[pool %s] listen.backlog(%d) was too low for the ondemand process manager. I updated it for you to %d.", wp->config->name, config->listen_backlog, FPM_BACKLOG_DEFAULT);
+ config->listen_backlog = FPM_BACKLOG_DEFAULT;
}
- wp->config->request_slowlog_timeout = 0;
-#endif
+ /* certainely useless but proper */
+ config->pm_start_servers = 0;
+ config->pm_min_spare_servers = 0;
+ config->pm_max_spare_servers = 0;
+ }
- if (wp->config->slowlog && *wp->config->slowlog) {
- int fd;
+ /* status */
+ if (wp->config->pm_status_path && *wp->config->pm_status_path) {
+ int i;
+ char *status = wp->config->pm_status_path;
- fd = open(wp->config->slowlog, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
+ if (*status != '/') {
+ zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must start with a '/'", wp->config->name, status);
+ return -1;
+ }
- if (0 > fd) {
- zlog(ZLOG_SYSERROR, "open(%s) failed", wp->config->slowlog);
+ if (strlen(status) < 2) {
+ zlog(ZLOG_ERROR, "[pool %s] the status path '%s' is not long enough", wp->config->name, status);
+ return -1;
+ }
+
+ for (i = 0; i < strlen(status); i++) {
+ if (!isalnum(status[i]) && status[i] != '/' && status[i] != '-' && status[i] != '_' && status[i] != '.') {
+ zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must contain only the following characters '[alphanum]/_-.'", wp->config->name, status);
return -1;
}
- close(fd);
}
}
+ /* ping */
if (wp->config->ping_path && *wp->config->ping_path) {
char *ping = wp->config->ping_path;
int i;
@@ -649,36 +870,62 @@ static int fpm_conf_process_all_pools() /* {{{ */
}
}
- if (wp->config->pm_status_path && *wp->config->pm_status_path) {
- int i;
- char *status = wp->config->pm_status_path;
- /* struct fpm_status_s fpm_status; */
+ /* access.log, access.format */
+ if (wp->config->access_log && *wp->config->access_log) {
+ fpm_evaluate_full_path(&wp->config->access_log, wp, NULL, 0);
+ if (!wp->config->access_format) {
+ wp->config->access_format = strdup("%R - %u %t \"%m %r\" %s");
+ }
+ }
- if (*status != '/') {
- zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must start with a '/'", wp->config->name, status);
+ if (wp->config->request_terminate_timeout) {
+ fpm_globals.heartbeat = fpm_globals.heartbeat ? MIN(fpm_globals.heartbeat, (wp->config->request_terminate_timeout * 1000) / 3) : (wp->config->request_terminate_timeout * 1000) / 3;
+ }
+
+ /* slowlog */
+ if (wp->config->slowlog && *wp->config->slowlog) {
+ fpm_evaluate_full_path(&wp->config->slowlog, wp, NULL, 0);
+ }
+
+ /* request_slowlog_timeout */
+ if (wp->config->request_slowlog_timeout) {
+#if HAVE_FPM_TRACE
+ if (! (wp->config->slowlog && *wp->config->slowlog)) {
+ zlog(ZLOG_ERROR, "[pool %s] 'slowlog' must be specified for use with 'request_slowlog_timeout'", wp->config->name);
return -1;
}
+#else
+ static int warned = 0;
- if (strlen(status) < 2) {
- zlog(ZLOG_ERROR, "[pool %s] the status path '%s' is not long enough", wp->config->name, status);
- return -1;
+ if (!warned) {
+ zlog(ZLOG_WARNING, "[pool %s] 'request_slowlog_timeout' is not supported on your system", wp->config->name);
+ warned = 1;
}
- for (i = 0; i < strlen(status); i++) {
- if (!isalnum(status[i]) && status[i] != '/' && status[i] != '-' && status[i] != '_' && status[i] != '.') {
- zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must contain only the following characters '[alphanum]/_-.'", wp->config->name, status);
+ wp->config->request_slowlog_timeout = 0;
+#endif
+
+ if (wp->config->slowlog && *wp->config->slowlog) {
+ int fd;
+
+ fd = open(wp->config->slowlog, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
+
+ if (0 > fd) {
+ zlog(ZLOG_SYSERROR, "Unable to create or open slowlog(%s)", wp->config->slowlog);
return -1;
}
+ close(fd);
}
- }
- if (wp->config->access_log && *wp->config->access_log) {
- fpm_evaluate_full_path(&wp->config->access_log, wp, NULL, 0);
- if (!wp->config->access_format) {
- wp->config->access_format = strdup("%R - %u %t \"%m %r\" %s");
+ fpm_globals.heartbeat = fpm_globals.heartbeat ? MIN(fpm_globals.heartbeat, (wp->config->request_slowlog_timeout * 1000) / 3) : (wp->config->request_slowlog_timeout * 1000) / 3;
+
+ if (wp->config->request_terminate_timeout && wp->config->request_slowlog_timeout > wp->config->request_terminate_timeout) {
+ zlog(ZLOG_ERROR, "[pool %s] 'request_slowlog_timeout' (%d) can't be greater than 'request_terminate_timeout' (%d)", wp->config->name, wp->config->request_slowlog_timeout, wp->config->request_terminate_timeout);
+ return -1;
}
}
+ /* chroot */
if (wp->config->chroot && *wp->config->chroot) {
fpm_evaluate_full_path(&wp->config->chroot, wp, NULL, 1);
@@ -687,12 +934,14 @@ static int fpm_conf_process_all_pools() /* {{{ */
zlog(ZLOG_ERROR, "[pool %s] the chroot path '%s' must start with a '/'", wp->config->name, wp->config->chroot);
return -1;
}
+
if (!fpm_conf_is_dir(wp->config->chroot)) {
zlog(ZLOG_ERROR, "[pool %s] the chroot path '%s' does not exist or is not a directory", wp->config->name, wp->config->chroot);
return -1;
}
}
+ /* chdir */
if (wp->config->chdir && *wp->config->chdir) {
fpm_evaluate_full_path(&wp->config->chdir, wp, NULL, 0);
@@ -721,6 +970,59 @@ static int fpm_conf_process_all_pools() /* {{{ */
}
}
}
+
+ /* security.limit_extensions */
+ if (!wp->config->security_limit_extensions) {
+ wp->config->security_limit_extensions = strdup(".php .phar");
+ }
+
+ if (*wp->config->security_limit_extensions) {
+ int nb_ext;
+ char *ext;
+ char *security_limit_extensions;
+ char *limit_extensions;
+
+
+ /* strdup because strtok(3) alters the string it parses */
+ security_limit_extensions = strdup(wp->config->security_limit_extensions);
+ limit_extensions = security_limit_extensions;
+ nb_ext = 0;
+
+ /* find the number of extensions */
+ while ((ext = strtok(limit_extensions, " \t"))) {
+ limit_extensions = NULL;
+ nb_ext++;
+ }
+ free(security_limit_extensions);
+
+ /* if something found */
+ if (nb_ext > 0) {
+
+ /* malloc the extension array */
+ wp->limit_extensions = malloc(sizeof(char *) * (nb_ext + 1));
+ if (!wp->limit_extensions) {
+ zlog(ZLOG_ERROR, "[pool %s] unable to malloc extensions array", wp->config->name);
+ return -1;
+ }
+
+ /* strdup because strtok(3) alters the string it parses */
+ security_limit_extensions = strdup(wp->config->security_limit_extensions);
+ limit_extensions = security_limit_extensions;
+ nb_ext = 0;
+
+ /* parse the string and save the extension in the array */
+ while ((ext = strtok(security_limit_extensions, " \t"))) {
+ security_limit_extensions = NULL;
+ wp->limit_extensions[nb_ext++] = strdup(ext);
+ }
+
+ /* end the array with NULL in order to parse it */
+ wp->limit_extensions[nb_ext] = NULL;
+ free(security_limit_extensions);
+ }
+ }
+
+ /* env[], php_value[], php_admin_values[] */
if (!wp->config->chroot) {
struct key_value_s *kv;
char *options[] = FPM_PHP_INI_TO_EXPAND;
@@ -750,7 +1052,7 @@ int fpm_conf_unlink_pid() /* {{{ */
{
if (fpm_global_config.pid_file) {
if (0 > unlink(fpm_global_config.pid_file)) {
- zlog(ZLOG_SYSERROR, "unlink(\"%s\") failed", fpm_global_config.pid_file);
+ zlog(ZLOG_SYSERROR, "Unable to remove the PID file (%s).", fpm_global_config.pid_file);
return -1;
}
}
@@ -770,14 +1072,14 @@ int fpm_conf_write_pid() /* {{{ */
fd = creat(fpm_global_config.pid_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd < 0) {
- zlog(ZLOG_SYSERROR, "creat(\"%s\") failed", fpm_global_config.pid_file);
+ zlog(ZLOG_SYSERROR, "Unable to create the PID file (%s).", fpm_global_config.pid_file);
return -1;
}
len = sprintf(buf, "%d", (int) fpm_globals.parent_pid);
if (len != write(fd, buf, len)) {
- zlog(ZLOG_SYSERROR, "write() failed");
+ zlog(ZLOG_SYSERROR, "Unable to write to the PID file.");
return -1;
}
close(fd);
@@ -794,11 +1096,31 @@ static int fpm_conf_post_process(TSRMLS_D) /* {{{ */
fpm_evaluate_full_path(&fpm_global_config.pid_file, NULL, PHP_LOCALSTATEDIR, 0);
}
+ fpm_globals.log_level = fpm_global_config.log_level;
+
+ if (fpm_global_config.process_max < 0) {
+ zlog(ZLOG_ERROR, "process_max can't be negative");
+ return -1;
+ }
+
if (!fpm_global_config.error_log) {
fpm_global_config.error_log = strdup("log/php-fpm.log");
}
- fpm_evaluate_full_path(&fpm_global_config.error_log, NULL, PHP_LOCALSTATEDIR, 0);
+#ifdef HAVE_SYSLOG_H
+ if (!fpm_global_config.syslog_ident) {
+ fpm_global_config.syslog_ident = strdup("php-fpm");
+ }
+
+ if (fpm_global_config.syslog_facility < 0) {
+ fpm_global_config.syslog_facility = LOG_DAEMON;
+ }
+
+ if (strcasecmp(fpm_global_config.error_log, "syslog") != 0)
+#endif
+ {
+ fpm_evaluate_full_path(&fpm_global_config.error_log, NULL, PHP_LOCALSTATEDIR, 0);
+ }
if (0 > fpm_stdio_open_error_log(0)) {
return -1;
@@ -808,6 +1130,10 @@ static int fpm_conf_post_process(TSRMLS_D) /* {{{ */
return -1;
}
+ if (0 > fpm_event_pre_init(fpm_global_config.events_mechanism)) {
+ return -1;
+ }
+
if (0 > fpm_conf_process_all_pools()) {
return -1;
}
@@ -830,8 +1156,13 @@ static void fpm_conf_cleanup(int which, void *arg) /* {{{ */
{
free(fpm_global_config.pid_file);
free(fpm_global_config.error_log);
+ free(fpm_global_config.events_mechanism);
fpm_global_config.pid_file = 0;
fpm_global_config.error_log = 0;
+#ifdef HAVE_SYSLOG_H
+ free(fpm_global_config.syslog_ident);
+ fpm_global_config.syslog_ident = 0;
+#endif
free(fpm_globals.config);
}
/* }}} */
@@ -1012,20 +1343,10 @@ static void fpm_conf_ini_parser_array(zval *name, zval *key, zval *value, void *
err = fpm_conf_set_array(key, value, &config, 0);
} else if (!strcmp("php_value", Z_STRVAL_P(name))) {
- if (!*Z_STRVAL_P(value)) {
- zlog(ZLOG_ERROR, "[%s:%d] empty value", ini_filename, ini_lineno);
- *error = 1;
- return;
- }
config = (char *)current_wp->config + WPO(php_values);
err = fpm_conf_set_array(key, value, &config, 0);
} else if (!strcmp("php_admin_value", Z_STRVAL_P(name))) {
- if (!*Z_STRVAL_P(value)) {
- zlog(ZLOG_ERROR, "[%s:%d] empty value", ini_filename, ini_lineno);
- *error = 1;
- return;
- }
config = (char *)current_wp->config + WPO(php_admin_values);
err = fpm_conf_set_array(key, value, &config, 0);
@@ -1088,18 +1409,18 @@ int fpm_conf_load_ini_file(char *filename TSRMLS_DC) /* {{{ */
int ret = 1;
if (!filename || !filename[0]) {
- zlog(ZLOG_ERROR, "Configuration file is empty");
+ zlog(ZLOG_ERROR, "configuration filename is empty");
return -1;
}
fd = open(filename, O_RDONLY, 0);
if (fd < 0) {
- zlog(ZLOG_ERROR, "Unable to open file '%s', errno=%d", filename, errno);
+ zlog(ZLOG_SYSERROR, "failed to open configuration file '%s'", filename);
return -1;
}
if (ini_recursion++ > 4) {
- zlog(ZLOG_ERROR, "You can include more than 5 files recusively");
+ zlog(ZLOG_ERROR, "failed to include more than 5 files recusively");
return -1;
}
@@ -1147,16 +1468,25 @@ static void fpm_conf_dump() /* {{{ */
{
struct fpm_worker_pool_s *wp;
+ /*
+ * Please keep the same order as in fpm_conf.h and in php-fpm.conf.in
+ */
zlog(ZLOG_NOTICE, "[General]");
zlog(ZLOG_NOTICE, "\tpid = %s", STR2STR(fpm_global_config.pid_file));
- zlog(ZLOG_NOTICE, "\tdaemonize = %s", BOOL2STR(fpm_global_config.daemonize));
zlog(ZLOG_NOTICE, "\terror_log = %s", STR2STR(fpm_global_config.error_log));
+#ifdef HAVE_SYSLOG_H
+ zlog(ZLOG_NOTICE, "\tsyslog.ident = %s", STR2STR(fpm_global_config.syslog_ident));
+ zlog(ZLOG_NOTICE, "\tsyslog.facility = %d", fpm_global_config.syslog_facility); /* FIXME: convert to string */
+#endif
zlog(ZLOG_NOTICE, "\tlog_level = %s", zlog_get_level_name(fpm_globals.log_level));
- zlog(ZLOG_NOTICE, "\tprocess_control_timeout = %ds", fpm_global_config.process_control_timeout);
zlog(ZLOG_NOTICE, "\temergency_restart_interval = %ds", fpm_global_config.emergency_restart_interval);
zlog(ZLOG_NOTICE, "\temergency_restart_threshold = %d", fpm_global_config.emergency_restart_threshold);
+ zlog(ZLOG_NOTICE, "\tprocess_control_timeout = %ds", fpm_global_config.process_control_timeout);
+ zlog(ZLOG_NOTICE, "\tprocess.max = %d", fpm_global_config.process_max);
+ zlog(ZLOG_NOTICE, "\tdaemonize = %s", BOOL2STR(fpm_global_config.daemonize));
zlog(ZLOG_NOTICE, "\trlimit_files = %d", fpm_global_config.rlimit_files);
zlog(ZLOG_NOTICE, "\trlimit_core = %d", fpm_global_config.rlimit_core);
+ zlog(ZLOG_NOTICE, "\tevents.mechanism = %s", fpm_event_machanism_name());
zlog(ZLOG_NOTICE, " ");
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
@@ -1166,8 +1496,6 @@ static void fpm_conf_dump() /* {{{ */
zlog(ZLOG_NOTICE, "\tprefix = %s", STR2STR(wp->config->prefix));
zlog(ZLOG_NOTICE, "\tuser = %s", STR2STR(wp->config->user));
zlog(ZLOG_NOTICE, "\tgroup = %s", STR2STR(wp->config->group));
- zlog(ZLOG_NOTICE, "\tchroot = %s", STR2STR(wp->config->chroot));
- zlog(ZLOG_NOTICE, "\tchdir = %s", STR2STR(wp->config->chdir));
zlog(ZLOG_NOTICE, "\tlisten = %s", STR2STR(wp->config->listen_address));
zlog(ZLOG_NOTICE, "\tlisten.backlog = %d", wp->config->listen_backlog);
zlog(ZLOG_NOTICE, "\tlisten.owner = %s", STR2STR(wp->config->listen_owner));
@@ -1176,21 +1504,25 @@ static void fpm_conf_dump() /* {{{ */
zlog(ZLOG_NOTICE, "\tlisten.allowed_clients = %s", STR2STR(wp->config->listen_allowed_clients));
zlog(ZLOG_NOTICE, "\tpm = %s", PM2STR(wp->config->pm));
zlog(ZLOG_NOTICE, "\tpm.max_children = %d", wp->config->pm_max_children);
- zlog(ZLOG_NOTICE, "\tpm.max_requests = %d", wp->config->pm_max_requests);
zlog(ZLOG_NOTICE, "\tpm.start_servers = %d", wp->config->pm_start_servers);
zlog(ZLOG_NOTICE, "\tpm.min_spare_servers = %d", wp->config->pm_min_spare_servers);
zlog(ZLOG_NOTICE, "\tpm.max_spare_servers = %d", wp->config->pm_max_spare_servers);
+ zlog(ZLOG_NOTICE, "\tpm.process_idle_timeout = %d", wp->config->pm_process_idle_timeout);
+ zlog(ZLOG_NOTICE, "\tpm.max_requests = %d", wp->config->pm_max_requests);
zlog(ZLOG_NOTICE, "\tpm.status_path = %s", STR2STR(wp->config->pm_status_path));
zlog(ZLOG_NOTICE, "\tping.path = %s", STR2STR(wp->config->ping_path));
zlog(ZLOG_NOTICE, "\tping.response = %s", STR2STR(wp->config->ping_response));
zlog(ZLOG_NOTICE, "\taccess.log = %s", STR2STR(wp->config->access_log));
zlog(ZLOG_NOTICE, "\taccess.format = %s", STR2STR(wp->config->access_format));
- zlog(ZLOG_NOTICE, "\tcatch_workers_output = %s", BOOL2STR(wp->config->catch_workers_output));
- zlog(ZLOG_NOTICE, "\trequest_terminate_timeout = %ds", wp->config->request_terminate_timeout);
- zlog(ZLOG_NOTICE, "\trequest_slowlog_timeout = %ds", wp->config->request_slowlog_timeout);
zlog(ZLOG_NOTICE, "\tslowlog = %s", STR2STR(wp->config->slowlog));
+ zlog(ZLOG_NOTICE, "\trequest_slowlog_timeout = %ds", wp->config->request_slowlog_timeout);
+ zlog(ZLOG_NOTICE, "\trequest_terminate_timeout = %ds", wp->config->request_terminate_timeout);
zlog(ZLOG_NOTICE, "\trlimit_files = %d", wp->config->rlimit_files);
zlog(ZLOG_NOTICE, "\trlimit_core = %d", wp->config->rlimit_core);
+ zlog(ZLOG_NOTICE, "\tchroot = %s", STR2STR(wp->config->chroot));
+ zlog(ZLOG_NOTICE, "\tchdir = %s", STR2STR(wp->config->chdir));
+ zlog(ZLOG_NOTICE, "\tcatch_workers_output = %s", BOOL2STR(wp->config->catch_workers_output));
+ zlog(ZLOG_NOTICE, "\tsecurity.limit_extensions = %s", wp->config->security_limit_extensions);
for (kv = wp->config->env; kv; kv = kv->next) {
zlog(ZLOG_NOTICE, "\tenv[%s] = %s", kv->key, kv->value);
diff --git a/sapi/fpm/fpm/fpm_conf.h b/sapi/fpm/fpm/fpm_conf.h
index 2152527ee..9fbd5064c 100644
--- a/sapi/fpm/fpm/fpm_conf.h
+++ b/sapi/fpm/fpm/fpm_conf.h
@@ -8,6 +8,8 @@
#include <stdint.h>
#include "php.h"
+#define PM2STR(a) (a == PM_STYLE_STATIC ? "static" : (a == PM_STYLE_DYNAMIC ? "dynamic" : "ondemand"))
+
#define FPM_CONF_MAX_PONG_LENGTH 64
struct key_value_s;
@@ -18,49 +20,64 @@ struct key_value_s {
char *value;
};
+/*
+ * Please keep the same order as in fpm_conf.c and in php-fpm.conf.in
+ */
struct fpm_global_config_s {
+ char *pid_file;
+ char *error_log;
+#ifdef HAVE_SYSLOG_H
+ char *syslog_ident;
+ int syslog_facility;
+#endif
+ int log_level;
int emergency_restart_threshold;
int emergency_restart_interval;
int process_control_timeout;
+ int process_max;
int daemonize;
- char *pid_file;
- char *error_log;
int rlimit_files;
int rlimit_core;
+ char *events_mechanism;
};
extern struct fpm_global_config_s fpm_global_config;
+/*
+ * Please keep the same order as in fpm_conf.c and in php-fpm.conf.in
+ */
struct fpm_worker_pool_config_s {
char *name;
char *prefix;
char *user;
char *group;
- char *chroot;
- char *chdir;
- int request_terminate_timeout;
- int request_slowlog_timeout;
- char *slowlog;
- int rlimit_files;
- int rlimit_core;
- int catch_workers_output;
+ char *listen_address;
+ int listen_backlog;
+ char *listen_owner;
+ char *listen_group;
+ char *listen_mode;
+ char *listen_allowed_clients;
int pm;
int pm_max_children;
- char *pm_status_path;
- int pm_max_requests;
int pm_start_servers;
int pm_min_spare_servers;
int pm_max_spare_servers;
+ int pm_process_idle_timeout;
+ int pm_max_requests;
+ char *pm_status_path;
char *ping_path;
char *ping_response;
char *access_log;
char *access_format;
- char *listen_address;
- int listen_backlog;
- char *listen_owner;
- char *listen_group;
- char *listen_mode;
- char *listen_allowed_clients;
+ char *slowlog;
+ int request_slowlog_timeout;
+ int request_terminate_timeout;
+ int rlimit_files;
+ int rlimit_core;
+ char *chroot;
+ char *chdir;
+ int catch_workers_output;
+ char *security_limit_extensions;
struct key_value_s *env;
struct key_value_s *php_admin_values;
struct key_value_s *php_values;
@@ -74,7 +91,8 @@ struct ini_value_parser_s {
enum {
PM_STYLE_STATIC = 1,
- PM_STYLE_DYNAMIC = 2
+ PM_STYLE_DYNAMIC = 2,
+ PM_STYLE_ONDEMAND = 3
};
int fpm_conf_init_main(int test_conf);
diff --git a/sapi/fpm/fpm/fpm_env.c b/sapi/fpm/fpm/fpm_env.c
index 03bf82340..6b64fedfe 100644
--- a/sapi/fpm/fpm/fpm_env.c
+++ b/sapi/fpm/fpm/fpm_env.c
@@ -13,7 +13,6 @@
#include "fpm_env.h"
#include "fpm.h"
-#include "zlog.h"
#ifndef HAVE_SETPROCTITLE
#ifdef __linux__
diff --git a/sapi/fpm/fpm/fpm_events.c b/sapi/fpm/fpm/fpm_events.c
index 8ae9ad2e2..d5f7483b4 100644
--- a/sapi/fpm/fpm/fpm_events.c
+++ b/sapi/fpm/fpm/fpm_events.c
@@ -10,7 +10,6 @@
#include <string.h>
#include <php.h>
-#include <php_network.h>
#include "fpm.h"
#include "fpm_process_ctl.h"
@@ -23,13 +22,14 @@
#include "fpm_clock.h"
#include "fpm_log.h"
-#define fpm_event_set_timeout(ev, now) timeradd(&(now), &(ev)->frequency, &(ev)->timeout);
+#include "events/select.h"
+#include "events/poll.h"
+#include "events/epoll.h"
+#include "events/devpoll.h"
+#include "events/port.h"
+#include "events/kqueue.h"
-typedef struct fpm_event_queue_s {
- struct fpm_event_queue_s *prev;
- struct fpm_event_queue_s *next;
- struct fpm_event_s *ev;
-} fpm_event_queue;
+#define fpm_event_set_timeout(ev, now) timeradd(&(now), &(ev)->frequency, &(ev)->timeout);
static void fpm_event_cleanup(int which, void *arg);
static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg);
@@ -38,16 +38,12 @@ static int fpm_event_queue_add(struct fpm_event_queue_s **queue, struct fpm_even
static int fpm_event_queue_del(struct fpm_event_queue_s **queue, struct fpm_event_s *ev);
static void fpm_event_queue_destroy(struct fpm_event_queue_s **queue);
-static int fpm_event_nfds_max;
+static struct fpm_event_module_s *module;
static struct fpm_event_queue_s *fpm_event_queue_timer = NULL;
static struct fpm_event_queue_s *fpm_event_queue_fd = NULL;
-static php_pollfd *fpm_event_ufds = NULL;
static void fpm_event_cleanup(int which, void *arg) /* {{{ */
{
- if (fpm_event_ufds) {
- free(fpm_event_ufds);
- }
fpm_event_queue_destroy(&fpm_event_queue_timer);
fpm_event_queue_destroy(&fpm_event_queue_fd);
}
@@ -66,7 +62,7 @@ static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg) /* {{
if (res <= 0) {
if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
- zlog(ZLOG_SYSERROR, "read() failed");
+ zlog(ZLOG_SYSERROR, "unable to read from the signal pipe");
}
return;
}
@@ -153,7 +149,7 @@ static int fpm_event_queue_add(struct fpm_event_queue_s **queue, struct fpm_even
}
if (!(elt = malloc(sizeof(struct fpm_event_queue_s)))) {
- zlog(ZLOG_SYSERROR, "malloc() failed");
+ zlog(ZLOG_SYSERROR, "Unable to add the event to queue: malloc() failed");
return -1;
}
elt->prev = NULL;
@@ -166,6 +162,11 @@ static int fpm_event_queue_add(struct fpm_event_queue_s **queue, struct fpm_even
}
*queue = elt;
+ /* ask the event module to add the fd from its own queue */
+ if (*queue == fpm_event_queue_fd && module->add) {
+ module->add(ev);
+ }
+
return 0;
}
/* }}} */
@@ -189,6 +190,12 @@ static int fpm_event_queue_del(struct fpm_event_queue_s **queue, struct fpm_even
*queue = q->next;
(*queue)->prev = NULL;
}
+
+ /* ask the event module to remove the fd from its own queue */
+ if (*queue == fpm_event_queue_fd && module->remove) {
+ module->remove(ev);
+ }
+
free(q);
return 0;
}
@@ -205,6 +212,11 @@ static void fpm_event_queue_destroy(struct fpm_event_queue_s **queue) /* {{{ */
if (!queue) {
return;
}
+
+ if (*queue == fpm_event_queue_fd && module->clean) {
+ module->clean();
+ }
+
q = *queue;
while (q) {
tmp = q;
@@ -216,27 +228,107 @@ static void fpm_event_queue_destroy(struct fpm_event_queue_s **queue) /* {{{ */
}
/* }}} */
+int fpm_event_pre_init(char *machanism) /* {{{ */
+{
+ /* kqueue */
+ module = fpm_event_kqueue_module();
+ if (module) {
+ if (!machanism || strcasecmp(module->name, machanism) == 0) {
+ return 0;
+ }
+ }
+
+ /* port */
+ module = fpm_event_port_module();
+ if (module) {
+ if (!machanism || strcasecmp(module->name, machanism) == 0) {
+ return 0;
+ }
+ }
+
+ /* epoll */
+ module = fpm_event_epoll_module();
+ if (module) {
+ if (!machanism || strcasecmp(module->name, machanism) == 0) {
+ return 0;
+ }
+ }
+
+ /* /dev/poll */
+ module = fpm_event_devpoll_module();
+ if (module) {
+ if (!machanism || strcasecmp(module->name, machanism) == 0) {
+ return 0;
+ }
+ }
+
+ /* poll */
+ module = fpm_event_poll_module();
+ if (module) {
+ if (!machanism || strcasecmp(module->name, machanism) == 0) {
+ return 0;
+ }
+ }
+
+ /* select */
+ module = fpm_event_select_module();
+ if (module) {
+ if (!machanism || strcasecmp(module->name, machanism) == 0) {
+ return 0;
+ }
+ }
+
+ if (machanism) {
+ zlog(ZLOG_ERROR, "event mechanism '%s' is not available on this system", machanism);
+ } else {
+ zlog(ZLOG_ERROR, "unable to find a suitable event mechanism on this system");
+ }
+ return -1;
+}
+/* }} */
+
+const char *fpm_event_machanism_name() /* {{{ */
+{
+ return module ? module->name : NULL;
+}
+/* }}} */
+
+int fpm_event_support_edge_trigger() /* {{{ */
+{
+ return module ? module->support_edge_trigger : 0;
+}
+/* }}} */
+
int fpm_event_init_main() /* {{{ */
{
struct fpm_worker_pool_s *wp;
+ int max;
+
+ if (!module) {
+ zlog(ZLOG_ERROR, "no event module found");
+ return -1;
+ }
+
+ if (!module->wait) {
+ zlog(ZLOG_ERROR, "Incomplete event implementation. Please open a bug report on https://bugs.php.net.");
+ return -1;
+ }
/* count the max number of necessary fds for polling */
- fpm_event_nfds_max = 1; /* only one FD is necessary at startup for the master process signal pipe */
+ max = 1; /* only one FD is necessary at startup for the master process signal pipe */
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
if (!wp->config) continue;
if (wp->config->catch_workers_output && wp->config->pm_max_children > 0) {
- fpm_event_nfds_max += (wp->config->pm_max_children * 2);
+ max += (wp->config->pm_max_children * 2);
}
}
- /* malloc the max number of necessary fds for polling */
- fpm_event_ufds = malloc(sizeof(php_pollfd) * fpm_event_nfds_max);
- if (!fpm_event_ufds) {
- zlog(ZLOG_SYSERROR, "malloc() failed");
+ if (module->init(max) < 0) {
+ zlog(ZLOG_ERROR, "Unable to initialize the event module %s", module->name);
return -1;
}
- zlog(ZLOG_DEBUG, "%d fds have been reserved", fpm_event_nfds_max);
+ zlog(ZLOG_DEBUG, "event module is %s and %d fds have been reserved", module->name, max);
if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_event_cleanup, NULL)) {
return -1;
@@ -258,7 +350,9 @@ void fpm_event_loop(int err) /* {{{ */
fpm_event_add(&signal_fd_event, 0);
/* add timers */
- fpm_pctl_heartbeat(NULL, 0, NULL);
+ if (fpm_globals.heartbeat > 0) {
+ fpm_pctl_heartbeat(NULL, 0, NULL);
+ }
if (!err) {
fpm_pctl_perform_idle_server_maintenance_heartbeat(NULL, 0, NULL);
@@ -273,7 +367,7 @@ void fpm_event_loop(int err) /* {{{ */
struct timeval tmp;
struct timeval now;
unsigned long int timeout;
- int i, ret;
+ int ret;
/* sanity check */
if (fpm_globals.parent_pid != getpid()) {
@@ -304,41 +398,15 @@ void fpm_event_loop(int err) /* {{{ */
timeout = (tmp.tv_sec * 1000) + (tmp.tv_usec / 1000) + 1;
}
- /* init fpm_event_ufds for php_poll2 */
- memset(fpm_event_ufds, 0, sizeof(php_pollfd) * fpm_event_nfds_max);
- i = 0;
- q = fpm_event_queue_fd;
- while (q && i < fpm_event_nfds_max) {
- fpm_event_ufds[i].fd = q->ev->fd;
- fpm_event_ufds[i].events = POLLIN;
- q->ev->index = i++;
- q = q->next;
+ ret = module->wait(fpm_event_queue_fd, timeout);
+
+ /* is a child, nothing to do here */
+ if (ret == -2) {
+ return;
}
- /* wait for inconming event or timeout */
- if ((ret = php_poll2(fpm_event_ufds, i, timeout)) == -1) {
- if (errno != EINTR) {
- zlog(ZLOG_WARNING, "php_poll2() returns %d", errno);
- }
- } else if (ret > 0) {
-
- /* trigger POLLIN events */
- q = fpm_event_queue_fd;
- while (q) {
- if (q->ev && q->ev->index >= 0 && q->ev->index < fpm_event_nfds_max) {
- if (q->ev->fd == fpm_event_ufds[q->ev->index].fd) {
- if (fpm_event_ufds[q->ev->index].revents & POLLIN) {
- fpm_event_fire(q->ev);
- /* sanity check */
- if (fpm_globals.parent_pid != getpid()) {
- return;
- }
- }
- }
- q->ev->index = -1;
- }
- q = q->next;
- }
+ if (ret > 0) {
+ zlog(ZLOG_DEBUG, "event module triggered %d events", ret);
}
/* trigger timers */
@@ -446,11 +514,11 @@ int fpm_event_add(struct fpm_event_s *ev, unsigned long int frequency) /* {{{ */
int fpm_event_del(struct fpm_event_s *ev) /* {{{ */
{
- if (fpm_event_queue_del(&fpm_event_queue_fd, ev) != 0) {
+ if (ev->index >= 0 && fpm_event_queue_del(&fpm_event_queue_fd, ev) != 0) {
return -1;
}
- if (fpm_event_queue_del(&fpm_event_queue_timer, ev) != 0) {
+ if (ev->index < 0 && fpm_event_queue_del(&fpm_event_queue_timer, ev) != 0) {
return -1;
}
diff --git a/sapi/fpm/fpm/fpm_events.h b/sapi/fpm/fpm/fpm_events.h
index 586b24283..416ec6e72 100644
--- a/sapi/fpm/fpm/fpm_events.h
+++ b/sapi/fpm/fpm/fpm_events.h
@@ -8,6 +8,7 @@
#define FPM_EV_TIMEOUT (1 << 0)
#define FPM_EV_READ (1 << 1)
#define FPM_EV_PERSIST (1 << 2)
+#define FPM_EV_EDGE (1 << 3)
#define fpm_event_set_timer(ev, flags, cb, arg) fpm_event_set((ev), -1, (flags), (cb), (arg))
@@ -22,11 +23,30 @@ struct fpm_event_s {
short which; /* type of event */
};
+typedef struct fpm_event_queue_s {
+ struct fpm_event_queue_s *prev;
+ struct fpm_event_queue_s *next;
+ struct fpm_event_s *ev;
+} fpm_event_queue;
+
+struct fpm_event_module_s {
+ const char *name;
+ int support_edge_trigger;
+ int (*init)(int max_fd);
+ int (*clean)(void);
+ int (*wait)(struct fpm_event_queue_s *queue, unsigned long int timeout);
+ int (*add)(struct fpm_event_s *ev);
+ int (*remove)(struct fpm_event_s *ev);
+};
+
void fpm_event_loop(int err);
void fpm_event_fire(struct fpm_event_s *ev);
int fpm_event_init_main();
int fpm_event_set(struct fpm_event_s *ev, int fd, int flags, void (*callback)(struct fpm_event_s *, short, void *), void *arg);
int fpm_event_add(struct fpm_event_s *ev, unsigned long int timeout);
int fpm_event_del(struct fpm_event_s *ev);
+int fpm_event_pre_init(char *machanism);
+const char *fpm_event_machanism_name();
+int fpm_event_support_edge_trigger();
#endif
diff --git a/sapi/fpm/fpm/fpm_log.c b/sapi/fpm/fpm/fpm_log.c
index ef1c0c3be..69bd31b11 100644
--- a/sapi/fpm/fpm/fpm_log.c
+++ b/sapi/fpm/fpm/fpm_log.c
@@ -29,9 +29,6 @@
static char *fpm_log_format = NULL;
static int fpm_log_fd = -1;
-#ifdef HAVE_TIMES
-static float tick;
-#endif
int fpm_log_open(int reopen) /* {{{ */
{
@@ -47,7 +44,7 @@ int fpm_log_open(int reopen) /* {{{ */
fd = open(wp->config->access_log, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
if (0 > fd) {
- zlog(ZLOG_SYSERROR, "open(\"%s\") failed", wp->config->access_log);
+ zlog(ZLOG_SYSERROR, "failed to open access log (%s)", wp->config->access_log);
return -1;
}
@@ -67,24 +64,6 @@ int fpm_log_open(int reopen) /* {{{ */
}
/* }}} */
-int fpm_log_init_main() /* {{{ */
-{
-#ifdef HAVE_TIMES
-#if (defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK))
- tick = sysconf(_SC_CLK_TCK);
-#else /* _SC_CLK_TCK */
-#ifdef HZ
- tick = HZ;
-#else /* HZ */
- tick = 100;
-#endif /* HZ */
-#endif /* _SC_CLK_TCK */
- zlog(ZLOG_DEBUG, "got clock tick '%.0f'", tick);
-#endif /* HAVE_TIMES */
- return 0;
-}
-/* }}} */
-
/* }}} */
int fpm_log_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
{
@@ -122,7 +101,6 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
size_t len, len2;
struct fpm_scoreboard_proc_s proc, *proc_p;
struct fpm_scoreboard_s *scoreboard;
- struct timeval uptime, now;
char tmp[129];
char format[129];
time_t now_epoch;
@@ -141,24 +119,21 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
test = 1;
}
- fpm_clock_get(&now);
now_epoch = time(NULL);
if (!test) {
scoreboard = fpm_scoreboard_get();
if (!scoreboard) {
- zlog(ZLOG_WARNING, "unable to get scoreboard");
+ zlog(ZLOG_WARNING, "unable to get scoreboard while preparing the access log");
return -1;
}
proc_p = fpm_scoreboard_proc_acquire(NULL, -1, 0);
if (!proc_p) {
- zlog(ZLOG_WARNING, "[pool %s] Unable to acquire shm slot", scoreboard->pool);
+ zlog(ZLOG_WARNING, "[pool %s] Unable to acquire shm slot while preparing the access log", scoreboard->pool);
return -1;
}
proc = *proc_p;
fpm_scoreboard_proc_release(proc_p);
-
- timersub(&now, &proc.accepted, &uptime);
}
token = 0;
@@ -172,7 +147,7 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
while (*s != '\0') {
if (len > FPM_LOG_BUFFER) {
- zlog(ZLOG_NOTICE, "the log buffer is full (%d). The log request has been truncated.", FPM_LOG_BUFFER);
+ zlog(ZLOG_NOTICE, "the log buffer is full (%d). The access log request has been truncated.", FPM_LOG_BUFFER);
len = FPM_LOG_BUFFER - 1;
break;
}
@@ -198,19 +173,15 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
case 'C': /* %CPU */
if (format[0] == '\0' || !strcasecmp(format, "total")) {
if (!test) {
- tms_total =
- (proc.cpu_finished.tms_utime + proc.cpu_finished.tms_stime + proc.cpu_finished.tms_cutime + proc.cpu_finished.tms_cstime)
- -
- (proc.cpu_accepted.tms_utime + proc.cpu_accepted.tms_stime + proc.cpu_accepted.tms_cutime + proc.cpu_accepted.tms_cstime)
- ;
+ tms_total = proc.last_request_cpu.tms_utime + proc.last_request_cpu.tms_stime + proc.last_request_cpu.tms_cutime + proc.last_request_cpu.tms_cstime;
}
} else if (!strcasecmp(format, "user")) {
if (!test) {
- tms_total = (proc.cpu_finished.tms_utime + proc.cpu_finished.tms_cutime) - (proc.cpu_accepted.tms_utime + proc.cpu_accepted.tms_cutime);
+ tms_total = proc.last_request_cpu.tms_utime + proc.last_request_cpu.tms_cutime;
}
} else if (!strcasecmp(format, "system")) {
if (!test) {
- tms_total = (proc.cpu_finished.tms_stime + proc.cpu_finished.tms_cstime) - (proc.cpu_accepted.tms_stime + proc.cpu_accepted.tms_cstime);
+ tms_total = proc.last_request_cpu.tms_stime + proc.last_request_cpu.tms_cstime;
}
} else {
zlog(ZLOG_WARNING, "only 'total', 'user' or 'system' are allowed as a modifier for %%%c ('%s')", *s, format);
@@ -219,7 +190,7 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
format[0] = '\0';
if (!test) {
- len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.2f", tms_total / tick / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.);
+ len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.2f", tms_total / fpm_scoreboard_get_tick() / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.);
}
break;
#endif
@@ -228,19 +199,19 @@ int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */
/* seconds */
if (format[0] == '\0' || !strcasecmp(format, "seconds")) {
if (!test) {
- len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", uptime.tv_sec + uptime.tv_usec / 1000000.);
+ len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration.tv_sec + proc.duration.tv_usec / 1000000.);
}
/* miliseconds */
} else if (!strcasecmp(format, "miliseconds") || !strcasecmp(format, "mili")) {
if (!test) {
- len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", uptime.tv_sec * 1000. + uptime.tv_usec / 1000.);
+ len2 = snprintf(b, FPM_LOG_BUFFER - len, "%.3f", proc.duration.tv_sec * 1000. + proc.duration.tv_usec / 1000.);
}
/* microseconds */
} else if (!strcasecmp(format, "microseconds") || !strcasecmp(format, "micro")) {
if (!test) {
- len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", uptime.tv_sec * 1000000UL + uptime.tv_usec);
+ len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", proc.duration.tv_sec * 1000000UL + proc.duration.tv_usec);
}
} else {
diff --git a/sapi/fpm/fpm/fpm_log.h b/sapi/fpm/fpm/fpm_log.h
index 74f842646..f0199d9cb 100644
--- a/sapi/fpm/fpm/fpm_log.h
+++ b/sapi/fpm/fpm/fpm_log.h
@@ -6,7 +6,6 @@
#define FPM_LOG_H 1
#include "fpm_worker_pool.h"
-int fpm_log_init_main();
int fpm_log_init_child(struct fpm_worker_pool_s *wp);
int fpm_log_write(char *log_format TSRMLS_DC);
int fpm_log_open(int reopen);
diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c
index c2db60f11..ea0dd149f 100644
--- a/sapi/fpm/fpm/fpm_main.c
+++ b/sapi/fpm/fpm/fpm_main.c
@@ -100,12 +100,13 @@ int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS;
#include "fastcgi.h"
#include <php_config.h>
-#include <fpm/fpm.h>
-#include <fpm/fpm_request.h>
-#include <fpm/fpm_status.h>
-#include <fpm/fpm_conf.h>
-#include <fpm/fpm_php.h>
-#include <fpm/fpm_log.h>
+#include "fpm.h"
+#include "fpm_request.h"
+#include "fpm_status.h"
+#include "fpm_conf.h"
+#include "fpm_php.h"
+#include "fpm_log.h"
+#include "zlog.h"
#ifndef PHP_WIN32
/* XXX this will need to change later when threaded fastcgi is implemented. shane */
@@ -124,6 +125,7 @@ static int parent = 1;
#endif
static int request_body_fd;
+static int fpm_is_running = 0;
static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC);
static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg TSRMLS_DC);
@@ -260,34 +262,33 @@ static void print_extensions(TSRMLS_D)
zend_llist_destroy(&sorted_exts);
}
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
#endif
static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC)
{
-#ifdef PHP_WRITE_STDOUT
- long ret;
-#else
- size_t ret;
-#endif
+ ssize_t ret;
- if (fcgi_is_fastcgi()) {
+ /* sapi has started which means everyhting must be send through fcgi */
+ if (fpm_is_running) {
fcgi_request *request = (fcgi_request*) SG(server_context);
- long ret = fcgi_write(request, FCGI_STDOUT, str, str_length);
+ ret = fcgi_write(request, FCGI_STDOUT, str, str_length);
if (ret <= 0) {
return 0;
}
- return ret;
+ return (size_t)ret;
}
-#ifdef PHP_WRITE_STDOUT
- ret = write(STDOUT_FILENO, str, str_length);
- if (ret <= 0) return 0;
- return ret;
+ /* sapi has not started, output to stdout instead of fcgi */
+#ifdef PHP_WRITE_STDOUT
+ ret = write(STDOUT_FILENO, str, str_length);
+ if (ret <= 0) {
+ return 0;
+ }
+ return (size_t)ret;
#else
- ret = fwrite(str, 1, MIN(str_length, 16384), stdout);
- return ret;
+ return fwrite(str, 1, MIN(str_length, 16384), stdout);
#endif
}
@@ -313,17 +314,20 @@ static int sapi_cgibin_ub_write(const char *str, uint str_length TSRMLS_DC)
static void sapi_cgibin_flush(void *server_context)
{
- if (fcgi_is_fastcgi()) {
+ /* fpm has started, let use fcgi instead of stdout */
+ if (fpm_is_running) {
fcgi_request *request = (fcgi_request*) server_context;
if (
#ifndef PHP_WIN32
- !parent &&
+ !parent &&
#endif
- request && !fcgi_flush(request, 0)) {
+ request && !fcgi_flush(request, 0)) {
php_handle_aborted_connection();
}
return;
}
+
+ /* fpm has not started yet, let use stdout instead of fcgi */
if (fflush(stdout) == EOF) {
php_handle_aborted_connection();
}
@@ -490,31 +494,27 @@ static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
count_bytes = MIN(count_bytes, (uint) SG(request_info).content_length - SG(read_post_bytes));
while (read_bytes < count_bytes) {
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) SG(server_context);
- if (request_body_fd == -1) {
- char *request_body_filename = sapi_cgibin_getenv((char *) "REQUEST_BODY_FILE",
- sizeof("REQUEST_BODY_FILE") - 1 TSRMLS_CC);
-
- if (request_body_filename && *request_body_filename) {
- request_body_fd = open(request_body_filename, O_RDONLY);
-
- if (0 > request_body_fd) {
- php_error(E_WARNING, "REQUEST_BODY_FILE: open('%s') failed: %s (%d)",
- request_body_filename, strerror(errno), errno);
- return 0;
- }
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+ if (request_body_fd == -1) {
+ char *request_body_filename = sapi_cgibin_getenv((char *) "REQUEST_BODY_FILE",
+ sizeof("REQUEST_BODY_FILE") - 1 TSRMLS_CC);
+
+ if (request_body_filename && *request_body_filename) {
+ request_body_fd = open(request_body_filename, O_RDONLY);
+
+ if (0 > request_body_fd) {
+ php_error(E_WARNING, "REQUEST_BODY_FILE: open('%s') failed: %s (%d)",
+ request_body_filename, strerror(errno), errno);
+ return 0;
}
}
+ }
- /* If REQUEST_BODY_FILE variable not available - read post body from fastcgi stream */
- if (request_body_fd < 0) {
- tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
- } else {
- tmp_read_bytes = read(request_body_fd, buffer + read_bytes, count_bytes - read_bytes);
- }
+ /* If REQUEST_BODY_FILE variable not available - read post body from fastcgi stream */
+ if (request_body_fd < 0) {
+ tmp_read_bytes = fcgi_read(request, buffer + read_bytes, count_bytes - read_bytes);
} else {
- tmp_read_bytes = read(STDIN_FILENO, buffer + read_bytes, count_bytes - read_bytes);
+ tmp_read_bytes = read(request_body_fd, buffer + read_bytes, count_bytes - read_bytes);
}
if (tmp_read_bytes <= 0) {
break;
@@ -526,77 +526,27 @@ static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
static char *sapi_cgibin_getenv(char *name, size_t name_len TSRMLS_DC)
{
- /* when php is started by mod_fastcgi, no regular environment
- * is provided to PHP. It is always sent to PHP at the start
- * of a request. So we have to do our own lookup to get env
- * vars. This could probably be faster somehow. */
- if (fcgi_is_fastcgi()) {
+ /* if fpm has started, use fcgi env */
+ if (fpm_is_running) {
fcgi_request *request = (fcgi_request*) SG(server_context);
return fcgi_getenv(request, name, name_len);
}
- /* if cgi, or fastcgi and not found in fcgi env
- check the regular environment */
+
+ /* if fpm has not started yet, use std env */
return getenv(name);
}
static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC)
{
int name_len;
-#if !HAVE_SETENV || !HAVE_UNSETENV
- int len;
- char *buf;
-#endif
if (!name) {
return NULL;
}
name_len = strlen(name);
- /* when php is started by mod_fastcgi, no regular environment
- * is provided to PHP. It is always sent to PHP at the start
- * of a request. So we have to do our own lookup to get env
- * vars. This could probably be faster somehow. */
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) SG(server_context);
- return fcgi_putenv(request, name, name_len, value);
- }
-
-#if HAVE_SETENV
- if (value) {
- setenv(name, value, 1);
- }
-#endif
-#if HAVE_UNSETENV
- if (!value) {
- unsetenv(name);
- }
-#endif
-
-#if !HAVE_SETENV || !HAVE_UNSETENV
- /* if cgi, or fastcgi and not found in fcgi env
- check the regular environment
- this leaks, but it's only cgi anyway, we'll fix
- it for 5.0
- */
- len = name_len + (value ? strlen(value) : 0) + sizeof("=") + 2;
- buf = (char *) malloc(len);
- if (buf == NULL) {
- return getenv(name);
- }
-#endif
-#if !HAVE_SETENV
- if (value) {
- len = slprintf(buf, len - 1, "%s=%s", name, value);
- putenv(buf);
- }
-#endif
-#if !HAVE_UNSETENV
- if (!value) {
- len = slprintf(buf, len - 1, "%s=", name);
- putenv(buf);
- }
-#endif
- return getenv(name);
+ fcgi_request *request = (fcgi_request*) SG(server_context);
+ return fcgi_putenv(request, name, name_len, value);
}
static char *sapi_cgi_read_cookies(TSRMLS_D)
@@ -606,6 +556,15 @@ static char *sapi_cgi_read_cookies(TSRMLS_D)
void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
{
+ fcgi_request *request;
+ HashPosition pos;
+ int magic_quotes_gpc;;
+ char *var, **val;
+ uint var_len;
+ ulong idx;
+ int filter_arg;
+
+
if (PG(http_globals)[TRACK_VARS_ENV] &&
array_ptr != PG(http_globals)[TRACK_VARS_ENV] &&
Z_TYPE_P(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
@@ -631,30 +590,24 @@ void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC)
/* call php's original import as a catch-all */
php_php_import_environment_variables(array_ptr TSRMLS_CC);
- if (fcgi_is_fastcgi()) {
- fcgi_request *request = (fcgi_request*) SG(server_context);
- HashPosition pos;
- int magic_quotes_gpc = PG(magic_quotes_gpc);
- char *var, **val;
- uint var_len;
- ulong idx;
- int filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER;
-
- /* turn off magic_quotes while importing environment variables */
- PG(magic_quotes_gpc) = 0;
- for (zend_hash_internal_pointer_reset_ex(request->env, &pos);
- zend_hash_get_current_key_ex(request->env, &var, &var_len, &idx, 0, &pos) == HASH_KEY_IS_STRING &&
- zend_hash_get_current_data_ex(request->env, (void **) &val, &pos) == SUCCESS;
- zend_hash_move_forward_ex(request->env, &pos)
- ) {
- unsigned int new_val_len;
+ request = (fcgi_request*) SG(server_context);
+ magic_quotes_gpc = PG(magic_quotes_gpc);
+ filter_arg = (array_ptr == PG(http_globals)[TRACK_VARS_ENV])?PARSE_ENV:PARSE_SERVER;
- if (sapi_module.input_filter(filter_arg, var, val, strlen(*val), &new_val_len TSRMLS_CC)) {
- php_register_variable_safe(var, *val, new_val_len, array_ptr TSRMLS_CC);
- }
+ /* turn off magic_quotes while importing environment variables */
+ PG(magic_quotes_gpc) = 0;
+ for (zend_hash_internal_pointer_reset_ex(request->env, &pos);
+ zend_hash_get_current_key_ex(request->env, &var, &var_len, &idx, 0, &pos) == HASH_KEY_IS_STRING &&
+ zend_hash_get_current_data_ex(request->env, (void **) &val, &pos) == SUCCESS;
+ zend_hash_move_forward_ex(request->env, &pos)
+ ) {
+ unsigned int new_val_len;
+
+ if (sapi_module.input_filter(filter_arg, var, val, strlen(*val), &new_val_len TSRMLS_CC)) {
+ php_register_variable_safe(var, *val, new_val_len, array_ptr TSRMLS_CC);
}
- PG(magic_quotes_gpc) = magic_quotes_gpc;
}
+ PG(magic_quotes_gpc) = magic_quotes_gpc;
}
static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC)
@@ -702,24 +655,8 @@ static void sapi_cgi_log_message(char *message)
{
TSRMLS_FETCH();
- if (fcgi_is_fastcgi() && CGIG(fcgi_logging)) {
- fcgi_request *request;
-
- request = (fcgi_request*) SG(server_context);
- if (request) {
- int len = strlen(message);
- char *buf = malloc(len+2);
-
- memcpy(buf, message, len);
- memcpy(buf + len, "\n", sizeof("\n"));
- fcgi_write(request, FCGI_STDERR, buf, len+1);
- free(buf);
- } else {
- fprintf(stderr, "%s\n", message);
- }
- /* ignore return code */
- } else {
- fprintf(stderr, "%s\n", message);
+ if (CGIG(fcgi_logging)) {
+ zlog(ZLOG_NOTICE, "PHP message: %s", message);
}
}
@@ -877,16 +814,12 @@ static int sapi_cgi_deactivate(TSRMLS_D)
2. When the first call occurs and the request is not set up, flush fails on FastCGI.
*/
if (SG(sapi_started)) {
- if (fcgi_is_fastcgi()) {
- if (
+ if (
#ifndef PHP_WIN32
- !parent &&
+ !parent &&
#endif
- !fcgi_finish_request((fcgi_request*)SG(server_context), 0)) {
- php_handle_aborted_connection();
- }
- } else {
- sapi_cgibin_flush(SG(server_context));
+ !fcgi_finish_request((fcgi_request*)SG(server_context), 0)) {
+ php_handle_aborted_connection();
}
}
return SUCCESS;
@@ -1399,7 +1332,7 @@ static void init_request_info(TSRMLS_D)
/* FIXME - Work out proto_num here */
SG(request_info).query_string = sapi_cgibin_getenv("QUERY_STRING", sizeof("QUERY_STRING") - 1 TSRMLS_CC);
SG(request_info).content_type = (content_type ? content_type : "" );
- SG(request_info).content_length = (content_length ? atoi(content_length) : 0);
+ SG(request_info).content_length = (content_length ? atol(content_length) : 0);
/* The CGI RFC allows servers to pass on unvalidated Authorization data */
auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION") - 1 TSRMLS_CC);
@@ -1437,14 +1370,14 @@ static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_
if (!mode || !arg1) return;
if (callback_type != ZEND_INI_PARSER_ENTRY) {
- fprintf(stderr, "Passing INI directive through FastCGI: only classic entries are allowed\n");
+ zlog(ZLOG_ERROR, "Passing INI directive through FastCGI: only classic entries are allowed");
return;
}
key = Z_STRVAL_P(arg1);
if (!key || strlen(key) < 1) {
- fprintf(stderr, "Passing INI directive through FastCGI: empty key\n");
+ zlog(ZLOG_ERROR, "Passing INI directive through FastCGI: empty key");
return;
}
@@ -1453,7 +1386,7 @@ static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_
}
if (!value) {
- fprintf(stderr, "Passing INI directive through FastCGI: empty value for key '%s'\n", key);
+ zlog(ZLOG_ERROR, "Passing INI directive through FastCGI: empty value for key '%s'", key);
return;
}
@@ -1461,7 +1394,7 @@ static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_
kv.value = value;
kv.next = NULL;
if (fpm_php_apply_defines_ex(&kv, *mode) == -1) {
- fprintf(stderr, "Passing INI directive through FastCGI: unable to set '%s'\n", key);
+ zlog(ZLOG_ERROR, "Passing INI directive through FastCGI: unable to set '%s'", key);
}
}
/* }}} */
@@ -1536,7 +1469,7 @@ PHP_FUNCTION(fastcgi_finish_request) /* {{{ */
{
fcgi_request *request = (fcgi_request*) SG(server_context);
- if (fcgi_is_fastcgi() && request->fd >= 0) {
+ if (request->fd >= 0) {
php_end_ob_buffers(1 TSRMLS_CC);
php_header(TSRMLS_C);
@@ -1595,6 +1528,7 @@ int main(int argc, char *argv[])
char *fpm_prefix = NULL;
char *fpm_pid = NULL;
int test_conf = 0;
+ int php_information = 0;
fcgi_init();
@@ -1705,20 +1639,8 @@ int main(int argc, char *argv[])
goto out;
case 'i': /* php info & quit */
- cgi_sapi_module.phpinfo_as_text = 1;
- cgi_sapi_module.startup(&cgi_sapi_module);
- if (php_request_startup(TSRMLS_C) == FAILURE) {
- SG(server_context) = NULL;
- php_module_shutdown(TSRMLS_C);
- return FAILURE;
- }
- SG(headers_sent) = 1;
- SG(request_info).no_headers = 1;
- php_print_info(0xFFFFFFFF TSRMLS_CC);
- php_request_shutdown((void *) 0);
- fcgi_shutdown();
- exit_status = 0;
- goto out;
+ php_information = 1;
+ break;
default:
case 'h':
@@ -1755,6 +1677,23 @@ int main(int argc, char *argv[])
}
}
+ if (php_information) {
+ cgi_sapi_module.phpinfo_as_text = 1;
+ cgi_sapi_module.startup(&cgi_sapi_module);
+ if (php_request_startup(TSRMLS_C) == FAILURE) {
+ SG(server_context) = NULL;
+ php_module_shutdown(TSRMLS_C);
+ return FAILURE;
+ }
+ SG(headers_sent) = 1;
+ SG(request_info).no_headers = 1;
+ php_print_info(0xFFFFFFFF TSRMLS_CC);
+ php_request_shutdown((void *) 0);
+ fcgi_shutdown();
+ exit_status = 0;
+ goto out;
+ }
+
/* No other args are permitted here as there is not interactive mode */
if (argc != php_optind) {
cgi_sapi_module.startup(&cgi_sapi_module);
@@ -1830,9 +1769,10 @@ consult the installation file that came with this distribution, or visit \n\
return FAILURE;
}
+ fpm_is_running = 1;
+
fcgi_fd = fpm_run(&max_requests);
parent = 0;
- fcgi_set_is_fastcgi(1);
/* make php call us to get _ENV vars */
php_php_import_environment_variables = php_import_environment_variables;
@@ -1847,6 +1787,7 @@ consult the installation file that came with this distribution, or visit \n\
SG(server_context) = (void *) &request;
init_request_info(TSRMLS_C);
CG(interactive) = 0;
+ char *primary_script = NULL;
fpm_request_info();
@@ -1872,15 +1813,30 @@ consult the installation file that came with this distribution, or visit \n\
/* If path_translated is NULL, terminate here with a 404 */
if (!SG(request_info).path_translated) {
zend_try {
+ zlog(ZLOG_DEBUG, "Primary script unknown");
SG(sapi_headers).http_response_code = 404;
+ PUTS("File not found.\n");
} zend_catch {
} zend_end_try();
goto fastcgi_request_done;
}
+ if (fpm_php_limit_extensions(SG(request_info).path_translated)) {
+ SG(sapi_headers).http_response_code = 403;
+ PUTS("Access denied.\n");
+ goto fastcgi_request_done;
+ }
+
+ /*
+ * have to duplicate SG(request_info).path_translated to be able to log errrors
+ * php_fopen_primary_script seems to delete SG(request_info).path_translated on failure
+ */
+ primary_script = estrdup(SG(request_info).path_translated);
+
/* path_translated exists, we can continue ! */
if (php_fopen_primary_script(&file_handle TSRMLS_CC) == FAILURE) {
zend_try {
+ zlog(ZLOG_ERROR, "Unable to open primary script: %s (%s)", primary_script, strerror(errno));
if (errno == EACCES) {
SG(sapi_headers).http_response_code = 403;
PUTS("Access denied.\n");
@@ -1902,6 +1858,10 @@ consult the installation file that came with this distribution, or visit \n\
php_execute_script(&file_handle TSRMLS_CC);
fastcgi_request_done:
+ if (primary_script) {
+ efree(primary_script);
+ }
+
if (request_body_fd != -1) {
close(request_body_fd);
}
diff --git a/sapi/fpm/fpm/fpm_php.c b/sapi/fpm/fpm/fpm_php.c
index 33b9e410e..840eec73e 100644
--- a/sapi/fpm/fpm/fpm_php.c
+++ b/sapi/fpm/fpm/fpm_php.c
@@ -19,6 +19,9 @@
#include "fpm_php.h"
#include "fpm_cleanup.h"
#include "fpm_worker_pool.h"
+#include "zlog.h"
+
+static char **limit_extensions = NULL;
static int fpm_php_zend_ini_alter_master(char *name, int name_length, char *new_value, int new_value_length, int mode, int stage TSRMLS_DC) /* {{{ */
{
@@ -117,13 +120,13 @@ static int fpm_php_apply_defines(struct fpm_worker_pool_s *wp) /* {{{ */
for (kv = wp->config->php_values; kv; kv = kv->next) {
if (fpm_php_apply_defines_ex(kv, ZEND_INI_USER) == -1) {
- fprintf(stderr, "Unable to set php_value '%s'", kv->key);
+ zlog(ZLOG_ERROR, "Unable to set php_value '%s'", kv->key);
}
}
for (kv = wp->config->php_admin_values; kv; kv = kv->next) {
if (fpm_php_apply_defines_ex(kv, ZEND_INI_SYSTEM) == -1) {
- fprintf(stderr, "Unable to set php_admin_value '%s'", kv->key);
+ zlog(ZLOG_ERROR, "Unable to set php_admin_value '%s'", kv->key);
}
}
@@ -219,7 +222,38 @@ int fpm_php_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
0 > fpm_php_set_allowed_clients(wp)) {
return -1;
}
+
+ if (wp->limit_extensions) {
+ limit_extensions = wp->limit_extensions;
+ }
return 0;
}
/* }}} */
+int fpm_php_limit_extensions(char *path) /* {{{ */
+{
+ char **p;
+ size_t path_len;
+
+ if (!path || !limit_extensions) {
+ return 0; /* allowed by default */
+ }
+
+ p = limit_extensions;
+ path_len = strlen(path);
+ while (p && *p) {
+ size_t ext_len = strlen(*p);
+ if (path_len > ext_len) {
+ char *path_ext = path + path_len - ext_len;
+ if (strcmp(*p, path_ext) == 0) {
+ return 0; /* allow as the extension has been found */
+ }
+ }
+ p++;
+ }
+
+
+ zlog(ZLOG_NOTICE, "Access to the script '%s' has been denied (see security.limit_extensions)", path);
+ return 1; /* extension not found: not allowed */
+}
+/* }}} */
diff --git a/sapi/fpm/fpm/fpm_php.h b/sapi/fpm/fpm/fpm_php.h
index 62a47e7fd..a2c7ed318 100644
--- a/sapi/fpm/fpm/fpm_php.h
+++ b/sapi/fpm/fpm/fpm_php.h
@@ -43,6 +43,7 @@ size_t fpm_php_content_length(TSRMLS_D);
void fpm_php_soft_quit();
int fpm_php_init_main();
int fpm_php_apply_defines_ex(struct key_value_s *kv, int mode);
+int fpm_php_limit_extensions(char *path);
#endif
diff --git a/sapi/fpm/fpm/fpm_php_trace.c b/sapi/fpm/fpm/fpm_php_trace.c
index 03874584f..cd97aebb3 100644
--- a/sapi/fpm/fpm/fpm_php_trace.c
+++ b/sapi/fpm/fpm/fpm_php_trace.c
@@ -144,7 +144,7 @@ void fpm_php_trace(struct fpm_child_s *child) /* {{{ */
slowlog = fopen(child->wp->config->slowlog, "a+");
if (!slowlog) {
- zlog(ZLOG_SYSERROR, "fopen(%s) failed", child->wp->config->slowlog);
+ zlog(ZLOG_SYSERROR, "unable to open slowlog (%s)", child->wp->config->slowlog);
goto done0;
}
diff --git a/sapi/fpm/fpm/fpm_process_ctl.c b/sapi/fpm/fpm/fpm_process_ctl.c
index 0f2685c73..e698eb0ca 100644
--- a/sapi/fpm/fpm/fpm_process_ctl.c
+++ b/sapi/fpm/fpm/fpm_process_ctl.c
@@ -99,7 +99,7 @@ static void fpm_pctl_exec() /* {{{ */
fpm_cleanups_run(FPM_CLEANUP_PARENT_EXEC);
execvp(saved_argv[0], saved_argv);
- zlog(ZLOG_SYSERROR, "execvp() failed");
+ zlog(ZLOG_SYSERROR, "failed to reload: execvp() failed");
exit(1);
}
/* }}} */
@@ -317,7 +317,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{
int idle = 0;
int active = 0;
int children_to_fork;
- unsigned cur_lq;
+ unsigned cur_lq = 0;
if (wp->config == NULL) continue;
@@ -352,9 +352,26 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{
}
#endif
}
- fpm_scoreboard_update(idle, active, cur_lq, -1, -1, -1, FPM_SCOREBOARD_ACTION_SET, wp->scoreboard);
}
+ fpm_scoreboard_update(idle, active, cur_lq, -1, -1, -1, FPM_SCOREBOARD_ACTION_SET, wp->scoreboard);
+ /* this is specific to PM_STYLE_ONDEMAND */
+ if (wp->config->pm == PM_STYLE_ONDEMAND) {
+ struct timeval last, now;
+
+ zlog(ZLOG_DEBUG, "[pool %s] currently %d active children, %d spare children", wp->config->name, active, idle);
+
+ if (!last_idle_child) continue;
+
+ fpm_request_last_activity(last_idle_child, &last);
+ fpm_clock_get(&now);
+ if (last.tv_sec < now.tv_sec - wp->config->pm_process_idle_timeout) {
+ last_idle_child->idle_kill = 1;
+ fpm_pctl_kill(last_idle_child->pid, FPM_PCTL_QUIT);
+ }
+
+ continue;
+ }
/* the rest is only used by PM_STYLE_DYNAMIC */
if (wp->config->pm != PM_STYLE_DYNAMIC) continue;
@@ -436,9 +453,13 @@ void fpm_pctl_heartbeat(struct fpm_event_s *ev, short which, void *arg) /* {{{ *
return;
}
+ /* ensure heartbeat is not lower than FPM_PCTL_MIN_HEARTBEAT */
+ fpm_globals.heartbeat = MAX(fpm_globals.heartbeat, FPM_PCTL_MIN_HEARTBEAT);
+
/* first call without setting to initialize the timer */
+ zlog(ZLOG_DEBUG, "heartbeat have been set up with a timeout of %dms", fpm_globals.heartbeat);
fpm_event_set_timer(&heartbeat, FPM_EV_PERSIST, &fpm_pctl_heartbeat, NULL);
- fpm_event_add(&heartbeat, FPM_PCTL_HEARTBEAT);
+ fpm_event_add(&heartbeat, fpm_globals.heartbeat);
}
/* }}} */
@@ -472,3 +493,47 @@ void fpm_pctl_perform_idle_server_maintenance_heartbeat(struct fpm_event_s *ev,
}
/* }}} */
+void fpm_pctl_on_socket_accept(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
+{
+ struct fpm_worker_pool_s *wp = (struct fpm_worker_pool_s *)arg;
+ struct fpm_child_s *child;
+
+
+ if (fpm_globals.parent_pid != getpid()) {
+ /* prevent a event race condition when child process
+ * have not set up its own event loop */
+ return;
+ }
+
+ wp->socket_event_set = 0;
+
+/* zlog(ZLOG_DEBUG, "[pool %s] heartbeat running_children=%d", wp->config->name, wp->running_children);*/
+
+ if (wp->running_children >= wp->config->pm_max_children) {
+ if (!wp->warn_max_children) {
+ fpm_scoreboard_update(0, 0, 0, 0, 0, 1, FPM_SCOREBOARD_ACTION_INC, wp->scoreboard);
+ zlog(ZLOG_WARNING, "[pool %s] server reached max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children);
+ wp->warn_max_children = 1;
+ }
+
+ return;
+ }
+
+ for (child = wp->children; child; child = child->next) {
+ /* if there is at least on idle child, it will handle the connection, stop here */
+ if (fpm_request_is_idle(child)) {
+ return;
+ }
+ }
+
+ wp->warn_max_children = 0;
+ fpm_children_make(wp, 1, 1, 1);
+
+ if (fpm_globals.is_child) {
+ return;
+ }
+
+ zlog(ZLOG_DEBUG, "[pool %s] got accept without idle child available .... I forked", wp->config->name);
+}
+/* }}} */
+
diff --git a/sapi/fpm/fpm/fpm_process_ctl.h b/sapi/fpm/fpm/fpm_process_ctl.h
index 6bfcfd8c6..86a6ef0df 100644
--- a/sapi/fpm/fpm/fpm_process_ctl.h
+++ b/sapi/fpm/fpm/fpm_process_ctl.h
@@ -11,8 +11,9 @@
#define FPM_MAX_SPAWN_RATE (32)
/* 1s (in ms) heartbeat for idle server maintenance */
#define FPM_IDLE_SERVER_MAINTENANCE_HEARTBEAT (1000)
-/* 130ms heartbeat for pctl */
-#define FPM_PCTL_HEARTBEAT (130)
+/* a minimum of 130ms heartbeat for pctl */
+#define FPM_PCTL_MIN_HEARTBEAT (130)
+
struct fpm_child_s;
@@ -22,6 +23,7 @@ int fpm_pctl_kill(pid_t pid, int how);
void fpm_pctl_kill_all(int signo);
void fpm_pctl_heartbeat(struct fpm_event_s *ev, short which, void *arg);
void fpm_pctl_perform_idle_server_maintenance_heartbeat(struct fpm_event_s *ev, short which, void *arg);
+void fpm_pctl_on_socket_accept(struct fpm_event_s *ev, short which, void *arg);
int fpm_pctl_child_exited();
int fpm_pctl_init_main();
diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c
index e0d1815db..28332d0a9 100644
--- a/sapi/fpm/fpm/fpm_request.c
+++ b/sapi/fpm/fpm/fpm_request.c
@@ -23,6 +23,19 @@
#include "zlog.h"
+static const char *requests_stages[] = {
+ [FPM_REQUEST_ACCEPTING] = "Idle",
+ [FPM_REQUEST_READING_HEADERS] = "Reading headers",
+ [FPM_REQUEST_INFO] = "Getting request informations",
+ [FPM_REQUEST_EXECUTING] = "Running",
+ [FPM_REQUEST_END] = "Ending",
+ [FPM_REQUEST_FINISHED] = "Finishing",
+};
+
+const char *fpm_request_get_stage_name(int stage) {
+ return requests_stages[stage];
+}
+
void fpm_request_accepting() /* {{{ */
{
struct fpm_scoreboard_proc_s *proc;
@@ -32,16 +45,12 @@ void fpm_request_accepting() /* {{{ */
proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
if (proc == NULL) {
- zlog(ZLOG_WARNING, "unable to acquire proc scoreboard");
+ zlog(ZLOG_WARNING, "failed to acquire proc scoreboard");
return;
}
proc->request_stage = FPM_REQUEST_ACCEPTING;
proc->tv = now;
- proc->request_uri[0] = '\0';
- proc->request_method[0] = '\0';
- proc->script_filename[0] = '\0';
- proc->content_length = 0;
fpm_scoreboard_proc_release(proc);
/* idle++, active-- */
@@ -67,7 +76,7 @@ void fpm_request_reading_headers() /* {{{ */
proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
if (proc == NULL) {
- zlog(ZLOG_WARNING, "unable to acquire proc scoreboard");
+ zlog(ZLOG_WARNING, "failed to acquire proc scoreboard");
return;
}
@@ -78,6 +87,14 @@ void fpm_request_reading_headers() /* {{{ */
#ifdef HAVE_TIMES
proc->cpu_accepted = cpu;
#endif
+ proc->requests++;
+ proc->request_uri[0] = '\0';
+ proc->request_method[0] = '\0';
+ proc->script_filename[0] = '\0';
+ proc->query_string[0] = '\0';
+ proc->query_string[0] = '\0';
+ proc->auth_user[0] = '\0';
+ proc->content_length = 0;
fpm_scoreboard_proc_release(proc);
/* idle--, active++, request++ */
@@ -101,7 +118,7 @@ void fpm_request_info() /* {{{ */
proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
if (proc == NULL) {
- zlog(ZLOG_WARNING, "unable to acquire proc scoreboard");
+ zlog(ZLOG_WARNING, "failed to acquire proc scoreboard");
return;
}
@@ -145,7 +162,7 @@ void fpm_request_executing() /* {{{ */
proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
if (proc == NULL) {
- zlog(ZLOG_WARNING, "unable to acquire proc scoreboard");
+ zlog(ZLOG_WARNING, "failed to acquire proc scoreboard");
return;
}
@@ -171,14 +188,18 @@ void fpm_request_end(TSRMLS_D) /* {{{ */
proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
if (proc == NULL) {
- zlog(ZLOG_WARNING, "unable to acquire proc scoreboard");
+ zlog(ZLOG_WARNING, "failed to acquire proc scoreboard");
return;
}
proc->request_stage = FPM_REQUEST_FINISHED;
proc->tv = now;
+ timersub(&now, &proc->accepted, &proc->duration);
#ifdef HAVE_TIMES
- proc->cpu_finished = cpu;
timersub(&proc->tv, &proc->accepted, &proc->cpu_duration);
+ proc->last_request_cpu.tms_utime = cpu.tms_utime - proc->cpu_accepted.tms_utime;
+ proc->last_request_cpu.tms_stime = cpu.tms_stime - proc->cpu_accepted.tms_stime;
+ proc->last_request_cpu.tms_cutime = cpu.tms_cutime - proc->cpu_accepted.tms_cutime;
+ proc->last_request_cpu.tms_cstime = cpu.tms_cstime - proc->cpu_accepted.tms_cstime;
#endif
proc->memory = memory;
fpm_scoreboard_proc_release(proc);
@@ -194,7 +215,7 @@ void fpm_request_finished() /* {{{ */
proc = fpm_scoreboard_proc_acquire(NULL, -1, 0);
if (proc == NULL) {
- zlog(ZLOG_WARNING, "unable to acquire proc scoreboard");
+ zlog(ZLOG_WARNING, "failed to acquire proc scoreboard");
return;
}
@@ -212,7 +233,7 @@ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now,
proc_p = fpm_scoreboard_proc_acquire(child->wp->scoreboard, child->scoreboard_i, 1);
if (!proc_p) {
- zlog(ZLOG_WARNING, "unable to acquire scoreboard");
+ zlog(ZLOG_WARNING, "failed to acquire scoreboard");
return;
}
@@ -276,3 +297,20 @@ int fpm_request_is_idle(struct fpm_child_s *child) /* {{{ */
return proc->request_stage == FPM_REQUEST_ACCEPTING;
}
/* }}} */
+
+int fpm_request_last_activity(struct fpm_child_s *child, struct timeval *tv) /* {{{ */
+{
+ struct fpm_scoreboard_proc_s *proc;
+
+ if (!tv) return -1;
+
+ proc = fpm_scoreboard_proc_get(child->wp->scoreboard, child->scoreboard_i);
+ if (!proc) {
+ return -1;
+ }
+
+ *tv = proc->tv;
+
+ return 1;
+}
+/* }}} */
diff --git a/sapi/fpm/fpm/fpm_request.h b/sapi/fpm/fpm/fpm_request.h
index b3014a5f1..aebd36cff 100644
--- a/sapi/fpm/fpm/fpm_request.h
+++ b/sapi/fpm/fpm/fpm_request.h
@@ -17,6 +17,8 @@ struct timeval;
void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *tv, int terminate_timeout, int slowlog_timeout);
int fpm_request_is_idle(struct fpm_child_s *child);
+const char *fpm_request_get_stage_name(int stage);
+int fpm_request_last_activity(struct fpm_child_s *child, struct timeval *tv);
enum fpm_request_stage_e {
FPM_REQUEST_ACCEPTING = 1,
diff --git a/sapi/fpm/fpm/fpm_scoreboard.c b/sapi/fpm/fpm/fpm_scoreboard.c
index 5ff5e5f9f..4222f6037 100644
--- a/sapi/fpm/fpm/fpm_scoreboard.c
+++ b/sapi/fpm/fpm/fpm_scoreboard.c
@@ -17,12 +17,30 @@
static struct fpm_scoreboard_s *fpm_scoreboard = NULL;
static int fpm_scoreboard_i = -1;
+#ifdef HAVE_TIMES
+static float fpm_scoreboard_tick;
+#endif
+
int fpm_scoreboard_init_main() /* {{{ */
{
struct fpm_worker_pool_s *wp;
int i;
+#ifdef HAVE_TIMES
+#if (defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK))
+ fpm_scoreboard_tick = sysconf(_SC_CLK_TCK);
+#else /* _SC_CLK_TCK */
+#ifdef HZ
+ fpm_scoreboard_tick = HZ;
+#else /* HZ */
+ fpm_scoreboard_tick = 100;
+#endif /* HZ */
+#endif /* _SC_CLK_TCK */
+ zlog(ZLOG_DEBUG, "got clock tick '%.0f'", fpm_scoreboard_tick);
+#endif /* HAVE_TIMES */
+
+
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
if (wp->config->pm_max_children < 1) {
zlog(ZLOG_ERROR, "[pool %s] Unable to create scoreboard SHM because max_client is not set", wp->config->name);
@@ -233,6 +251,7 @@ void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_ind
return;
}
proc->pid = pid;
+ proc->start_epoch = time(NULL);
}
/* }}} */
@@ -299,3 +318,11 @@ int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_in
}
/* }}} */
+#ifdef HAVE_TIMES
+float fpm_scoreboard_get_tick() /* {{{ */
+{
+ return fpm_scoreboard_tick;
+}
+/* }}} */
+#endif
+
diff --git a/sapi/fpm/fpm/fpm_scoreboard.h b/sapi/fpm/fpm/fpm_scoreboard.h
index e62c42d98..136ea481a 100644
--- a/sapi/fpm/fpm/fpm_scoreboard.h
+++ b/sapi/fpm/fpm/fpm_scoreboard.h
@@ -23,9 +23,12 @@ struct fpm_scoreboard_proc_s {
char dummy[16];
};
int used;
+ time_t start_epoch;
pid_t pid;
+ unsigned long requests;
enum fpm_request_stage_e request_stage;
struct timeval accepted;
+ struct timeval duration;
time_t accepted_epoch;
struct timeval tv;
char request_uri[128];
@@ -36,8 +39,9 @@ struct fpm_scoreboard_proc_s {
char auth_user[32];
#ifdef HAVE_TIMES
struct tms cpu_accepted;
- struct tms cpu_finished;
struct timeval cpu_duration;
+ struct tms last_request_cpu;
+ struct timeval last_request_cpu_duration;
#endif
size_t memory;
};
@@ -82,4 +86,8 @@ void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_ind
void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index);
int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index);
+#ifdef HAVE_TIMES
+float fpm_scoreboard_get_tick();
+#endif
+
#endif
diff --git a/sapi/fpm/fpm/fpm_shm.c b/sapi/fpm/fpm/fpm_shm.c
index a777612de..6acbddf9a 100644
--- a/sapi/fpm/fpm/fpm_shm.c
+++ b/sapi/fpm/fpm/fpm_shm.c
@@ -49,7 +49,7 @@ int fpm_shm_free(void *mem, size_t size) /* {{{ */
}
if (munmap(mem, size) == -1) {
- zlog(ZLOG_SYSERROR, "Unable to free shm: %s", strerror(errno));
+ zlog(ZLOG_SYSERROR, "Unable to free shm");
return 0;
}
diff --git a/sapi/fpm/fpm/fpm_signals.c b/sapi/fpm/fpm/fpm_signals.c
index 7c317e576..8993a860a 100644
--- a/sapi/fpm/fpm/fpm_signals.c
+++ b/sapi/fpm/fpm/fpm_signals.c
@@ -182,17 +182,17 @@ int fpm_signals_init_main() /* {{{ */
struct sigaction act;
if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) {
- zlog(ZLOG_SYSERROR, "socketpair() failed");
+ zlog(ZLOG_SYSERROR, "failed to init signals: socketpair()");
return -1;
}
if (0 > fd_set_blocked(sp[0], 0) || 0 > fd_set_blocked(sp[1], 0)) {
- zlog(ZLOG_SYSERROR, "fd_set_blocked() failed");
+ zlog(ZLOG_SYSERROR, "failed to init signals: fd_set_blocked()");
return -1;
}
if (0 > fcntl(sp[0], F_SETFD, FD_CLOEXEC) || 0 > fcntl(sp[1], F_SETFD, FD_CLOEXEC)) {
- zlog(ZLOG_SYSERROR, "fcntl(F_SETFD, FD_CLOEXEC) failed");
+ zlog(ZLOG_SYSERROR, "falied to init signals: fcntl(F_SETFD, FD_CLOEXEC)");
return -1;
}
@@ -207,7 +207,7 @@ int fpm_signals_init_main() /* {{{ */
0 > sigaction(SIGCHLD, &act, 0) ||
0 > sigaction(SIGQUIT, &act, 0)) {
- zlog(ZLOG_SYSERROR, "sigaction() failed");
+ zlog(ZLOG_SYSERROR, "failed to init signals: sigaction()");
return -1;
}
return 0;
@@ -236,7 +236,7 @@ int fpm_signals_init_child() /* {{{ */
0 > sigaction(SIGCHLD, &act_dfl, 0) ||
0 > sigaction(SIGQUIT, &act, 0)) {
- zlog(ZLOG_SYSERROR, "sigaction() failed");
+ zlog(ZLOG_SYSERROR, "failed to init child signals: sigaction()");
return -1;
}
return 0;
diff --git a/sapi/fpm/fpm/fpm_sockets.c b/sapi/fpm/fpm/fpm_sockets.c
index 08e2342e5..cb4897e9b 100644
--- a/sapi/fpm/fpm/fpm_sockets.c
+++ b/sapi/fpm/fpm/fpm_sockets.c
@@ -172,7 +172,7 @@ static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct
sock = socket(sa->sa_family, SOCK_STREAM, 0);
if (0 > sock) {
- zlog(ZLOG_SYSERROR, "socket() failed");
+ zlog(ZLOG_SYSERROR, "failed to create new listening socket: socket()");
return -1;
}
@@ -184,7 +184,7 @@ static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct
}
if (0 > bind(sock, sa, socklen)) {
- zlog(ZLOG_SYSERROR, "bind() for address '%s' failed", wp->config->listen_address);
+ zlog(ZLOG_SYSERROR, "unable to bind listening socket for address '%s'", wp->config->listen_address);
if (wp->listen_address_domain == FPM_AF_UNIX) {
umask(saved_umask);
}
@@ -198,14 +198,14 @@ static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct
if (wp->socket_uid != -1 || wp->socket_gid != -1) {
if (0 > chown(path, wp->socket_uid, wp->socket_gid)) {
- zlog(ZLOG_SYSERROR, "chown() for address '%s' failed", wp->config->listen_address);
+ zlog(ZLOG_SYSERROR, "failed to chown() the socket '%s'", wp->config->listen_address);
return -1;
}
}
}
if (0 > listen(sock, wp->config->listen_backlog)) {
- zlog(ZLOG_SYSERROR, "listen() for address '%s' failed", wp->config->listen_address);
+ zlog(ZLOG_SYSERROR, "failed to listen to address '%s'", wp->config->listen_address);
return -1;
}
@@ -392,7 +392,7 @@ int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq)
socklen_t len = sizeof(info);
if (0 > getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, &len)) {
- zlog(ZLOG_SYSERROR, "unable to retrieve TCP_INFO for socket");
+ zlog(ZLOG_SYSERROR, "failed to retrieve TCP_INFO for socket");
return -1;
}
diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c
index 8d7b75997..a20e2dd89 100644
--- a/sapi/fpm/fpm/fpm_status.c
+++ b/sapi/fpm/fpm/fpm_status.c
@@ -1,5 +1,5 @@
- /* $Id: fpm_status.c 312914 2011-07-04 21:29:32Z fat $ */
+ /* $Id: fpm_status.c 317901 2011-10-08 14:04:09Z fat $ */
/* (c) 2009 Jerome Loyet */
#include "php.h"
@@ -13,6 +13,8 @@
#include "fpm_scoreboard.h"
#include "zlog.h"
#include "fpm_atomic.h"
+#include "fpm_conf.h"
+#include <ext/standard/html.h>
static char *fpm_status_uri = NULL;
static char *fpm_status_ping_uri = NULL;
@@ -32,7 +34,7 @@ int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
if (wp->config->ping_path) {
if (!wp->config->ping_response) {
- zlog(ZLOG_ERROR, "[pool %s] ping is set (%s) but pong is not set.", wp->config->name, wp->config->ping_path);
+ zlog(ZLOG_ERROR, "[pool %s] ping is set (%s) but ping.response is not set.", wp->config->name, wp->config->ping_path);
return -1;
}
fpm_status_ping_uri = strdup(wp->config->ping_path);
@@ -46,9 +48,12 @@ int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
int fpm_status_handle_request(TSRMLS_D) /* {{{ */
{
struct fpm_scoreboard_s scoreboard, *scoreboard_p;
-// struct fpm_scoreboard_proc_s proc;
- char *buffer, *syntax, *time_format, time_buffer[64];
+ struct fpm_scoreboard_proc_s proc;
+ char *buffer, *time_format, time_buffer[64];
time_t now_epoch;
+ int full, encode;
+ char *short_syntax, *short_post;
+ char *full_pre, *full_syntax, *full_post, *full_separator;
if (!SG(request_info).request_uri) {
return 0;
@@ -56,6 +61,7 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
/* PING */
if (fpm_status_ping_uri && fpm_status_ping_response && !strcmp(fpm_status_ping_uri, SG(request_info).request_uri)) {
+ fpm_request_executing();
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
sapi_add_header_ex(ZEND_STRL("Expires: Thu, 01 Jan 1970 00:00:00 GMT"), 1, 1 TSRMLS_CC);
sapi_add_header_ex(ZEND_STRL("Cache-Control: no-cache, no-store, must-revalidate, max-age=0"), 1, 1 TSRMLS_CC);
@@ -72,6 +78,7 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
/* STATUS */
if (fpm_status_uri && !strcmp(fpm_status_uri, SG(request_info).request_uri)) {
+ fpm_request_executing();
scoreboard_p = fpm_scoreboard_get();
if (!scoreboard_p) {
@@ -117,12 +124,23 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
return 1;
}
+ /* full status ? */
+ full = SG(request_info).request_uri && strstr(SG(request_info).query_string, "full");
+ short_syntax = short_post = NULL;
+ full_separator = full_pre = full_syntax = full_post = NULL;
+ encode = 0;
+
/* HTML */
if (SG(request_info).query_string && strstr(SG(request_info).query_string, "html")) {
sapi_add_header_ex(ZEND_STRL("Content-Type: text/html"), 1, 1 TSRMLS_CC);
time_format = "%d/%b/%Y:%H:%M:%S %z";
+ encode = 1;
- syntax =
+ short_syntax =
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
+ "<head><title>PHP-FPM Status Page</title></head>\n"
+ "<body>\n"
"<table>\n"
"<tr><th>pool</th><td>%s</td></tr>\n"
"<tr><th>process manager</th><td>%s</td></tr>\n"
@@ -141,12 +159,58 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
"<tr><th>max children reached</th><td>%u</td></tr>\n"
"</table>\n";
+ if (!full) {
+ short_post = "</body></html>";
+ } else {
+ full_pre =
+ "<table border=\"1\">\n"
+ "<tr>"
+ "<th>pid</th>"
+ "<th>state</th>"
+ "<th>start time</th>"
+ "<th>start since</th>"
+ "<th>requests</th>"
+ "<th>request duration</th>"
+ "<th>request method</th>"
+ "<th>request uri</th>"
+ "<th>content length</th>"
+ "<th>user</th>"
+ "<th>script</th>"
+#if HAVE_FPM_LQ
+ "<th>last request cpu</th>"
+#endif
+ "<th>last request memory</th>"
+ "</tr>\n";
+
+ full_syntax =
+ "<tr>"
+ "<td>%d</td>"
+ "<td>%s</td>"
+ "<td>%s</td>"
+ "<td>%lu</td>"
+ "<td>%lu</td>"
+ "<td>%lu</td>"
+ "<td>%s</td>"
+ "<td>%s%s%s</td>"
+ "<td>%zu</td>"
+ "<td>%s</td>"
+ "<td>%s</td>"
+#if HAVE_FPM_LQ
+ "<td>%.2f</td>"
+#endif
+ "<td>%zu</td>"
+ "</tr>\n";
+
+ full_post = "</table></body></html>";
+ }
+
/* XML */
} else if (SG(request_info).request_uri && strstr(SG(request_info).query_string, "xml")) {
sapi_add_header_ex(ZEND_STRL("Content-Type: text/xml"), 1, 1 TSRMLS_CC);
time_format = "%s";
+ encode = 1;
- syntax =
+ short_syntax =
"<?xml version=\"1.0\" ?>\n"
"<status>\n"
"<pool>%s</pool>\n"
@@ -163,14 +227,40 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
"<active-processes>%d</active-processes>\n"
"<total-processes>%d</total-processes>\n"
"<max-active-processes>%d</max-active-processes>\n"
- "<max-children-reached>%u</max-children-reached>\n"
- "</status>";
+ "<max-children-reached>%u</max-children-reached>\n";
+
+ if (!full) {
+ short_post = "</status>";
+ } else {
+ full_pre = "<processes>\n";
+ full_syntax =
+ "<process>"
+ "<pid>%d</pid>"
+ "<state>%s</state>"
+ "<start-time>%s</start-time>"
+ "<start-since>%lu</start-since>"
+ "<requests>%lu</requests>"
+ "<request-duration>%lu</request-duration>"
+ "<request-method>%s</request-method>"
+ "<request-uri>%s%s%s</request-uri>"
+ "<content-length>%zu</content-length>"
+ "<user>%s</user>"
+ "<script>%s</script>"
+#if HAVE_FPM_LQ
+ "<last-request-cpu>%.2f</last-request-cpu>"
+#endif
+ "<last-request-memory>%zu</last-request-memory>"
+ "</process>\n"
+ ;
+ full_post = "</processes>\n</status>";
+ }
/* JSON */
} else if (SG(request_info).request_uri && strstr(SG(request_info).query_string, "json")) {
sapi_add_header_ex(ZEND_STRL("Content-Type: application/json"), 1, 1 TSRMLS_CC);
time_format = "%s";
- syntax =
+
+ short_syntax =
"{"
"\"pool\":\"%s\","
"\"process manager\":\"%s\","
@@ -186,14 +276,41 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
"\"active processes\":%d,"
"\"total processes\":%d,"
"\"max active processes\":%d,"
- "\"max children reached\":%u"
- "}";
+ "\"max children reached\":%u";
+
+ if (!full) {
+ short_post = "}";
+ } else {
+ full_separator = ",";
+ full_pre = ", \"processes\":[";
+
+ full_syntax = "{"
+ "\"pid\":%d,"
+ "\"state\":\"%s\","
+ "\"start time\":%s,"
+ "\"start since\":%lu,"
+ "\"requests\":%lu,"
+ "\"request duration\":%lu,"
+ "\"request method\":\"%s\","
+ "\"request uri\":\"%s%s%s\","
+ "\"content length\":%zu,"
+ "\"user\":\"%s\","
+ "\"script\":\"%s\","
+#if HAVE_FPM_LQ
+ "\"last request cpu\":%.2f,"
+#endif
+ "\"last request memory\":%zu"
+ "}";
+
+ full_post = "]}";
+ }
/* TEXT */
} else {
sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC);
time_format = "%d/%b/%Y:%H:%M:%S %z";
- syntax =
+
+ short_syntax =
"pool: %s\n"
"process manager: %s\n"
"start time: %s\n"
@@ -209,13 +326,34 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
"total processes: %d\n"
"max active processes: %d\n"
"max children reached: %u\n";
+
+ if (full) {
+ full_syntax =
+ "\n"
+ "************************\n"
+ "pid: %d\n"
+ "state: %s\n"
+ "start time: %s\n"
+ "start since: %lu\n"
+ "requests: %lu\n"
+ "request duration: %lu\n"
+ "request method: %s\n"
+ "request URI: %s%s%s\n"
+ "content length: %zu\n"
+ "user: %s\n"
+ "script: %s\n"
+#ifdef HAVE_FPM_LQ
+ "last request cpu: %.2f\n"
+#endif
+ "last request memory: %zu\n";
+ }
}
strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&scoreboard.start_epoch));
now_epoch = time(NULL);
- spprintf(&buffer, 0, syntax,
+ spprintf(&buffer, 0, short_syntax,
scoreboard.pool,
- scoreboard.pm == PM_STYLE_STATIC ? "static" : "dynamic",
+ PM2STR(scoreboard.pm),
time_buffer,
now_epoch - scoreboard.start_epoch,
scoreboard.requests,
@@ -233,6 +371,96 @@ int fpm_status_handle_request(TSRMLS_D) /* {{{ */
PUTS(buffer);
efree(buffer);
+ if (short_post) {
+ PUTS(short_post);
+ }
+
+ /* no need to test the var 'full' */
+ if (full_syntax) {
+ int i, len, first;
+ char *query_string;
+ struct timeval duration, now;
+#ifdef HAVE_FPM_LQ
+ float cpu;
+#endif
+
+ fpm_clock_get(&now);
+
+ if (full_pre) {
+ PUTS(full_pre);
+ }
+
+ first = 1;
+ for (i=0; i<scoreboard_p->nprocs; i++) {
+ if (!scoreboard_p->procs[i] || !scoreboard_p->procs[i]->used) {
+ continue;
+ }
+ proc = *scoreboard_p->procs[i];
+
+ if (first) {
+ first = 0;
+ } else {
+ if (full_separator) {
+ PUTS(full_separator);
+ }
+ }
+
+ query_string = NULL;
+ len = 0;
+ if (proc.query_string[0] != '\0') {
+ if (!encode) {
+ query_string = proc.query_string;
+ } else {
+ query_string = php_escape_html_entities_ex((unsigned char *)proc.query_string, strlen(proc.query_string), &len, 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, NULL, 1 TSRMLS_CC);
+ }
+ }
+
+#ifdef HAVE_FPM_LQ
+ /* prevent NaN */
+ if (proc.cpu_duration.tv_sec == 0 && proc.cpu_duration.tv_usec == 0) {
+ cpu = 0.;
+ } else {
+ cpu = (proc.last_request_cpu.tms_utime + proc.last_request_cpu.tms_stime + proc.last_request_cpu.tms_cutime + proc.last_request_cpu.tms_cstime) / fpm_scoreboard_get_tick() / (proc.cpu_duration.tv_sec + proc.cpu_duration.tv_usec / 1000000.) * 100.;
+ }
+#endif
+
+ if (proc.request_stage == FPM_REQUEST_ACCEPTING) {
+ duration = proc.duration;
+ } else {
+ timersub(&now, &proc.accepted, &duration);
+ }
+ strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&proc.start_epoch));
+ spprintf(&buffer, 0, full_syntax,
+ proc.pid,
+ fpm_request_get_stage_name(proc.request_stage),
+ time_buffer,
+ now_epoch - proc.start_epoch,
+ proc.requests,
+ duration.tv_sec * 1000000UL + duration.tv_usec,
+ proc.request_method[0] != '\0' ? proc.request_method : "-",
+ proc.request_uri[0] != '\0' ? proc.request_uri : "-",
+ query_string ? "?" : "",
+ query_string ? query_string : "",
+ proc.content_length,
+ proc.auth_user[0] != '\0' ? proc.auth_user : "-",
+ proc.script_filename[0] != '\0' ? proc.script_filename : "-",
+#ifdef HAVE_FPM_LQ
+ proc.request_stage == FPM_REQUEST_ACCEPTING ? cpu : 0.,
+#endif
+ proc.request_stage == FPM_REQUEST_ACCEPTING ? proc.memory : 0);
+ PUTS(buffer);
+ efree(buffer);
+
+ if (len > 0 && query_string) {
+ efree(query_string);
+ }
+ }
+
+ if (full_post) {
+ PUTS(full_post);
+ }
+ }
+
return 1;
}
diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c
index 571f3074b..6a587d00e 100644
--- a/sapi/fpm/fpm/fpm_stdio.c
+++ b/sapi/fpm/fpm/fpm_stdio.c
@@ -11,6 +11,8 @@
#include <unistd.h>
#include <errno.h>
+#include "php_syslog.h"
+
#include "fpm.h"
#include "fpm_children.h"
#include "fpm_events.h"
@@ -26,12 +28,12 @@ int fpm_stdio_init_main() /* {{{ */
int fd = open("/dev/null", O_RDWR);
if (0 > fd) {
- zlog(ZLOG_SYSERROR, "open(\"/dev/null\") failed");
+ zlog(ZLOG_SYSERROR, "failed to init stdio: open(\"/dev/null\")");
return -1;
}
if (0 > dup2(fd, STDIN_FILENO) || 0 > dup2(fd, STDOUT_FILENO)) {
- zlog(ZLOG_SYSERROR, "dup2() failed");
+ zlog(ZLOG_SYSERROR, "failed to init stdio: dup2()");
return -1;
}
close(fd);
@@ -42,10 +44,12 @@ int fpm_stdio_init_main() /* {{{ */
int fpm_stdio_init_final() /* {{{ */
{
if (fpm_global_config.daemonize) {
- if (fpm_globals.error_log_fd != STDERR_FILENO) {
- /* there might be messages to stderr from libevent, we need to log them all */
+ /* prevent duping if logging to syslog */
+ if (fpm_globals.error_log_fd > 0 && fpm_globals.error_log_fd != STDERR_FILENO) {
+
+ /* there might be messages to stderr from other parts of the code, we need to log them all */
if (0 > dup2(fpm_globals.error_log_fd, STDERR_FILENO)) {
- zlog(ZLOG_SYSERROR, "dup2() failed");
+ zlog(ZLOG_SYSERROR, "failed to init stdio: dup2()");
return -1;
}
}
@@ -57,13 +61,20 @@ int fpm_stdio_init_final() /* {{{ */
int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
{
- close(fpm_globals.error_log_fd);
+#ifdef HAVE_SYSLOG_H
+ if (fpm_globals.error_log_fd == ZLOG_SYSLOG) {
+ closelog(); /* ensure to close syslog not to interrupt with PHP syslog code */
+ } else
+#endif
+ if (fpm_globals.error_log_fd > 0) {
+ close(fpm_globals.error_log_fd);
+ }
fpm_globals.error_log_fd = -1;
zlog_set_fd(-1);
if (wp->listening_socket != STDIN_FILENO) {
if (0 > dup2(wp->listening_socket, STDIN_FILENO)) {
- zlog(ZLOG_SYSERROR, "dup2() failed");
+ zlog(ZLOG_SYSERROR, "failed to init child stdio: dup2()");
return -1;
}
}
@@ -105,7 +116,7 @@ static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg)
} else { /* error or pipe is closed */
if (res < 0) { /* error */
- zlog(ZLOG_SYSERROR, "read() failed");
+ zlog(ZLOG_SYSERROR, "unable to read what child say");
}
fpm_event_del(event);
@@ -175,20 +186,23 @@ int fpm_stdio_prepare_pipes(struct fpm_child_s *child) /* {{{ */
}
if (0 > pipe(fd_stdout)) {
- zlog(ZLOG_SYSERROR, "pipe() failed");
+ zlog(ZLOG_SYSERROR, "failed to prepare the stdout pipe");
return -1;
}
if (0 > pipe(fd_stderr)) {
- zlog(ZLOG_SYSERROR, "pipe() failed");
- close(fd_stdout[0]); close(fd_stdout[1]);
+ zlog(ZLOG_SYSERROR, "failed to prepare the stderr pipe");
+ close(fd_stdout[0]);
+ close(fd_stdout[1]);
return -1;
}
if (0 > fd_set_blocked(fd_stdout[0], 0) || 0 > fd_set_blocked(fd_stderr[0], 0)) {
- zlog(ZLOG_SYSERROR, "fd_set_blocked() failed");
- close(fd_stdout[0]); close(fd_stdout[1]);
- close(fd_stderr[0]); close(fd_stderr[1]);
+ zlog(ZLOG_SYSERROR, "failed to unblock pipes");
+ close(fd_stdout[0]);
+ close(fd_stdout[1]);
+ close(fd_stderr[0]);
+ close(fd_stderr[1]);
return -1;
}
return 0;
@@ -249,9 +263,20 @@ int fpm_stdio_open_error_log(int reopen) /* {{{ */
{
int fd;
+#ifdef HAVE_SYSLOG_H
+ if (!strcasecmp(fpm_global_config.error_log, "syslog")) {
+ openlog(fpm_global_config.syslog_ident, LOG_PID | LOG_CONS, fpm_global_config.syslog_facility);
+ fpm_globals.error_log_fd = ZLOG_SYSLOG;
+ if (fpm_global_config.daemonize) {
+ zlog_set_fd(fpm_globals.error_log_fd);
+ }
+ return 0;
+ }
+#endif
+
fd = open(fpm_global_config.error_log, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
if (0 > fd) {
- zlog(ZLOG_SYSERROR, "open(\"%s\") failed", fpm_global_config.error_log);
+ zlog(ZLOG_SYSERROR, "failed to open error_log (%s)", fpm_global_config.error_log);
return -1;
}
diff --git a/sapi/fpm/fpm/fpm_trace_mach.c b/sapi/fpm/fpm/fpm_trace_mach.c
index fe26fd9e2..3b85e6a34 100644
--- a/sapi/fpm/fpm/fpm_trace_mach.c
+++ b/sapi/fpm/fpm/fpm_trace_mach.c
@@ -37,7 +37,7 @@ static int fpm_mach_vm_read_page(vm_offset_t page) /* {{{ */
kr = mach_vm_read(target, page, fpm_pagesize, &local_page, &local_size);
if (kr != KERN_SUCCESS) {
- zlog(ZLOG_ERROR, "mach_vm_read() failed: %s (%d)", mach_error_string(kr), kr);
+ zlog(ZLOG_ERROR, "failed to read vm page: mach_vm_read(): %s (%d)", mach_error_string(kr), kr);
return -1;
}
return 0;
@@ -47,7 +47,7 @@ static int fpm_mach_vm_read_page(vm_offset_t page) /* {{{ */
int fpm_trace_signal(pid_t pid) /* {{{ */
{
if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) {
- zlog(ZLOG_SYSERROR, "kill(SIGSTOP) failed");
+ zlog(ZLOG_SYSERROR, "failed to send SIGSTOP to %d", pid);
return -1;
}
return 0;
diff --git a/sapi/fpm/fpm/fpm_trace_pread.c b/sapi/fpm/fpm/fpm_trace_pread.c
index eda84928e..6a6155740 100644
--- a/sapi/fpm/fpm/fpm_trace_pread.c
+++ b/sapi/fpm/fpm/fpm_trace_pread.c
@@ -26,7 +26,7 @@ static int mem_file = -1;
int fpm_trace_signal(pid_t pid) /* {{{ */
{
if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) {
- zlog(ZLOG_SYSERROR, "kill(SIGSTOP) failed");
+ zlog(ZLOG_SYSERROR, "failed to send SIGSTOP to %d", pid);
return -1;
}
return 0;
@@ -40,7 +40,7 @@ int fpm_trace_ready(pid_t pid) /* {{{ */
sprintf(buf, "/proc/%d/" PROC_MEM_FILE, (int) pid);
mem_file = open(buf, O_RDONLY);
if (0 > mem_file) {
- zlog(ZLOG_SYSERROR, "open(%s) failed", buf);
+ zlog(ZLOG_SYSERROR, "failed to open %s", buf);
return -1;
}
return 0;
diff --git a/sapi/fpm/fpm/fpm_trace_ptrace.c b/sapi/fpm/fpm/fpm_trace_ptrace.c
index 395c1ac08..838c61867 100644
--- a/sapi/fpm/fpm/fpm_trace_ptrace.c
+++ b/sapi/fpm/fpm/fpm_trace_ptrace.c
@@ -29,7 +29,7 @@ static pid_t traced_pid;
int fpm_trace_signal(pid_t pid) /* {{{ */
{
if (0 > ptrace(PTRACE_ATTACH, pid, 0, 0)) {
- zlog(ZLOG_SYSERROR, "ptrace(ATTACH) failed");
+ zlog(ZLOG_SYSERROR, "failed to ptrace(ATTACH) child %d", pid);
return -1;
}
return 0;
@@ -46,7 +46,7 @@ int fpm_trace_ready(pid_t pid) /* {{{ */
int fpm_trace_close(pid_t pid) /* {{{ */
{
if (0 > ptrace(PTRACE_DETACH, pid, (void *) 1, 0)) {
- zlog(ZLOG_SYSERROR, "ptrace(DETACH) failed");
+ zlog(ZLOG_SYSERROR, "failed to ptrace(DETACH) child %d", pid);
return -1;
}
traced_pid = 0;
@@ -65,14 +65,14 @@ int fpm_trace_get_long(long addr, long *data) /* {{{ */
};
if (0 > ptrace(PT_IO, traced_pid, (void *) &ptio, 0)) {
- zlog(ZLOG_SYSERROR, "ptrace(PT_IO) failed");
+ zlog(ZLOG_SYSERROR, "failed to ptrace(PT_IO) pid %d", traced_pid);
return -1;
}
#else
errno = 0;
*data = ptrace(PTRACE_PEEKDATA, traced_pid, (void *) addr, 0);
if (errno) {
- zlog(ZLOG_SYSERROR, "ptrace(PEEKDATA) failed");
+ zlog(ZLOG_SYSERROR, "failed to ptrace(PEEKDATA) pid %d", traced_pid);
return -1;
}
#endif
diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c
index d29d38799..17d0b8125 100644
--- a/sapi/fpm/fpm/fpm_unix.c
+++ b/sapi/fpm/fpm/fpm_unix.c
@@ -73,6 +73,7 @@ int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp) /* {{{ */
static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */
{
+ struct passwd *pwd;
int is_root = !geteuid();
if (is_root) {
@@ -119,23 +120,20 @@ static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */
#endif
} else { /* not root */
if (wp->config->user && *wp->config->user) {
- zlog(ZLOG_WARNING, "[pool %s] 'user' directive is ignored", wp->config->name);
+ zlog(ZLOG_WARNING, "[pool %s] 'user' directive is ignored when FPM is not running as root", wp->config->name);
}
if (wp->config->group && *wp->config->group) {
- zlog(ZLOG_WARNING, "[pool %s] 'group' directive is ignored", wp->config->name);
+ zlog(ZLOG_WARNING, "[pool %s] 'group' directive is ignored when FPM is not running as root", wp->config->name);
}
if (wp->config->chroot && *wp->config->chroot) {
- zlog(ZLOG_WARNING, "[pool %s] 'chroot' directive is ignored", wp->config->name);
+ zlog(ZLOG_WARNING, "[pool %s] 'chroot' directive is ignored when FPM is not running as root", wp->config->name);
}
- { /* set up HOME and USER anyway */
- struct passwd *pwd;
-
- pwd = getpwuid(getuid());
- if (pwd) {
- wp->user = strdup(pwd->pw_name);
- wp->home = strdup(pwd->pw_dir);
- }
+ /* set up HOME and USER anyway */
+ pwd = getpwuid(getuid());
+ if (pwd) {
+ wp->user = strdup(pwd->pw_name);
+ wp->home = strdup(pwd->pw_dir);
}
}
return 0;
@@ -153,7 +151,7 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
r.rlim_max = r.rlim_cur = (rlim_t) wp->config->rlimit_files;
if (0 > setrlimit(RLIMIT_NOFILE, &r)) {
- zlog(ZLOG_SYSERROR, "[pool %s] unable to set rlimit_files for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d) failed (%d)", wp->config->name, wp->config->rlimit_files, errno);
+ zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_files for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d)", wp->config->name, wp->config->rlimit_files);
}
}
@@ -163,13 +161,13 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
r.rlim_max = r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core;
if (0 > setrlimit(RLIMIT_CORE, &r)) {
- zlog(ZLOG_SYSERROR, "[pool %s] unable to set rlimit_core for this pool. Please check your system limits or decrease rlimit_core. setrlimit(RLIMIT_CORE, %d) failed (%d)", wp->config->name, wp->config->rlimit_core, errno);
+ zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_core. setrlimit(RLIMIT_CORE, %d)", wp->config->name, wp->config->rlimit_core);
}
}
if (is_root && wp->config->chroot && *wp->config->chroot) {
if (0 > chroot(wp->config->chroot)) {
- zlog(ZLOG_SYSERROR, "[pool %s] chroot(%s) failed", wp->config->name, wp->config->chroot);
+ zlog(ZLOG_SYSERROR, "[pool %s] failed to chroot(%s)", wp->config->name, wp->config->chroot);
return -1;
}
made_chroot = 1;
@@ -177,7 +175,7 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
if (wp->config->chdir && *wp->config->chdir) {
if (0 > chdir(wp->config->chdir)) {
- zlog(ZLOG_SYSERROR, "[pool %s] chdir(%s) failed", wp->config->name, wp->config->chdir);
+ zlog(ZLOG_SYSERROR, "[pool %s] failed to chdir(%s)", wp->config->name, wp->config->chdir);
return -1;
}
} else if (made_chroot) {
@@ -187,17 +185,17 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
if (is_root) {
if (wp->set_gid) {
if (0 > setgid(wp->set_gid)) {
- zlog(ZLOG_SYSERROR, "[pool %s] setgid(%d) failed", wp->config->name, wp->set_gid);
+ zlog(ZLOG_SYSERROR, "[pool %s] failed to setgid(%d)", wp->config->name, wp->set_gid);
return -1;
}
}
if (wp->set_uid) {
if (0 > initgroups(wp->config->user, wp->set_gid)) {
- zlog(ZLOG_SYSERROR, "[pool %s] initgroups(%s, %d) failed", wp->config->name, wp->config->user, wp->set_gid);
+ zlog(ZLOG_SYSERROR, "[pool %s] failed to initgroups(%s, %d)", wp->config->name, wp->config->user, wp->set_gid);
return -1;
}
if (0 > setuid(wp->set_uid)) {
- zlog(ZLOG_SYSERROR, "[pool %s] setuid(%d) failed", wp->config->name, wp->set_uid);
+ zlog(ZLOG_SYSERROR, "[pool %s] failed to setuid(%d)", wp->config->name, wp->set_uid);
return -1;
}
}
@@ -205,7 +203,7 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
#ifdef HAVE_PRCTL
if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) {
- zlog(ZLOG_SYSERROR, "[pool %s] prctl(PR_SET_DUMPABLE) failed", wp->config->name);
+ zlog(ZLOG_SYSERROR, "[pool %s] failed to prctl(PR_SET_DUMPABLE)", wp->config->name);
}
#endif
@@ -226,7 +224,7 @@ int fpm_unix_init_main() /* {{{ */
r.rlim_max = r.rlim_cur = (rlim_t) fpm_global_config.rlimit_files;
if (0 > setrlimit(RLIMIT_NOFILE, &r)) {
- zlog(ZLOG_SYSERROR, "unable to set rlimit_core for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d) failed (%d)", fpm_global_config.rlimit_files, errno);
+ zlog(ZLOG_SYSERROR, "failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d)", fpm_global_config.rlimit_files);
return -1;
}
}
@@ -237,7 +235,7 @@ int fpm_unix_init_main() /* {{{ */
r.rlim_max = r.rlim_cur = fpm_global_config.rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) fpm_global_config.rlimit_core;
if (0 > setrlimit(RLIMIT_CORE, &r)) {
- zlog(ZLOG_SYSERROR, "unable to set rlimit_core for this pool. Please check your system limits or decrease rlimit_core. setrlimit(RLIMIT_CORE, %d) failed (%d)", fpm_global_config.rlimit_core, errno);
+ zlog(ZLOG_SYSERROR, "failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_core. setrlimit(RLIMIT_CORE, %d)", fpm_global_config.rlimit_core);
return -1;
}
}
@@ -246,7 +244,7 @@ int fpm_unix_init_main() /* {{{ */
if (fpm_global_config.daemonize) {
switch (fork()) {
case -1 :
- zlog(ZLOG_SYSERROR, "daemonized fork() failed");
+ zlog(ZLOG_SYSERROR, "failed to daemonize");
return -1;
case 0 :
break;
diff --git a/sapi/fpm/fpm/fpm_worker_pool.c b/sapi/fpm/fpm/fpm_worker_pool.c
index 6c6d9cce0..123f9893f 100644
--- a/sapi/fpm/fpm/fpm_worker_pool.c
+++ b/sapi/fpm/fpm/fpm_worker_pool.c
@@ -15,7 +15,6 @@
#include "fpm_shm.h"
#include "fpm_scoreboard.h"
#include "fpm_conf.h"
-#include "zlog.h"
struct fpm_worker_pool_s *fpm_worker_all_pools;
diff --git a/sapi/fpm/fpm/fpm_worker_pool.h b/sapi/fpm/fpm/fpm_worker_pool.h
index 098def5b7..6688e6d3b 100644
--- a/sapi/fpm/fpm/fpm_worker_pool.h
+++ b/sapi/fpm/fpm/fpm_worker_pool.h
@@ -37,6 +37,11 @@ struct fpm_worker_pool_s {
#endif
struct fpm_scoreboard_s *scoreboard;
int log_fd;
+ char **limit_extensions;
+
+ /* for ondemand PM */
+ struct fpm_event_s *ondemand_event;
+ int socket_event_set;
};
struct fpm_worker_pool_s *fpm_worker_pool_alloc();
diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c
index 6b062eb8a..b127ec16f 100644
--- a/sapi/fpm/fpm/zlog.c
+++ b/sapi/fpm/fpm/zlog.c
@@ -12,6 +12,8 @@
#include <sys/time.h>
#include <errno.h>
+#include "php_syslog.h"
+
#include "zlog.h"
#include "fpm.h"
@@ -22,12 +24,22 @@ static int zlog_level = ZLOG_NOTICE;
static int launched = 0;
static const char *level_names[] = {
- [ZLOG_DEBUG] = "DEBUG",
- [ZLOG_NOTICE] = "NOTICE",
- [ZLOG_WARNING] = "WARNING",
- [ZLOG_ERROR] = "ERROR",
- [ZLOG_ALERT] = "ALERT",
+ [ZLOG_DEBUG] = "DEBUG",
+ [ZLOG_NOTICE] = "NOTICE",
+ [ZLOG_WARNING] = "WARNING",
+ [ZLOG_ERROR] = "ERROR",
+ [ZLOG_ALERT] = "ALERT",
+};
+
+#ifdef HAVE_SYSLOG_H
+const int syslog_priorities[] = {
+ [ZLOG_DEBUG] = LOG_DEBUG,
+ [ZLOG_NOTICE] = LOG_NOTICE,
+ [ZLOG_WARNING] = LOG_WARNING,
+ [ZLOG_ERROR] = LOG_ERR,
+ [ZLOG_ALERT] = LOG_ALERT,
};
+#endif
const char *zlog_get_level_name(int log_level) /* {{{ */
{
@@ -94,18 +106,30 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /*
}
saved_errno = errno;
- if (!fpm_globals.is_child) {
- gettimeofday(&tv, 0);
- len = zlog_print_time(&tv, buf, buf_size);
- }
- if (zlog_level == ZLOG_DEBUG) {
+#ifdef HAVE_SYSLOG_H
+ if (zlog_fd == ZLOG_SYSLOG /* && !fpm_globals.is_child */) {
+ len = 0;
+ if (zlog_level == ZLOG_DEBUG) {
+ len += snprintf(buf, buf_size, "[%s] %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line);
+ } else {
+ len += snprintf(buf, buf_size, "[%s] ", level_names[flags & ZLOG_LEVEL_MASK]);
+ }
+ } else
+#endif
+ {
if (!fpm_globals.is_child) {
- len += snprintf(buf + len, buf_size - len, "%s: pid %d, %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], getpid(), function, line);
+ gettimeofday(&tv, 0);
+ len = zlog_print_time(&tv, buf, buf_size);
+ }
+ if (zlog_level == ZLOG_DEBUG) {
+ if (!fpm_globals.is_child) {
+ len += snprintf(buf + len, buf_size - len, "%s: pid %d, %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], getpid(), function, line);
+ } else {
+ len += snprintf(buf + len, buf_size - len, "%s: %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line);
+ }
} else {
- len += snprintf(buf + len, buf_size - len, "%s: %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], function, line);
+ len += snprintf(buf + len, buf_size - len, "%s: ", level_names[flags & ZLOG_LEVEL_MASK]);
}
- } else {
- len += snprintf(buf + len, buf_size - len, "%s: ", level_names[flags & ZLOG_LEVEL_MASK]);
}
if (len > buf_size - 1) {
@@ -135,9 +159,19 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /*
len = buf_size - 1;
}
- buf[len++] = '\n';
- write(zlog_fd > -1 ? zlog_fd : STDERR_FILENO, buf, len);
- if (zlog_fd != STDERR_FILENO && zlog_fd > -1 && !launched && (flags & ZLOG_LEVEL_MASK) >= ZLOG_NOTICE) {
+#ifdef HAVE_SYSLOG_H
+ if (zlog_fd == ZLOG_SYSLOG) {
+ buf[len] = '\0';
+ php_syslog(syslog_priorities[zlog_level], "%s", buf);
+ buf[len++] = '\n';
+ } else
+#endif
+ {
+ buf[len++] = '\n';
+ write(zlog_fd > -1 ? zlog_fd : STDERR_FILENO, buf, len);
+ }
+
+ if (zlog_fd != STDERR_FILENO && zlog_fd != -1 && !launched && (flags & ZLOG_LEVEL_MASK) >= ZLOG_NOTICE) {
write(STDERR_FILENO, buf, len);
}
}
diff --git a/sapi/fpm/fpm/zlog.h b/sapi/fpm/fpm/zlog.h
index a83e32902..e6a5c019a 100644
--- a/sapi/fpm/fpm/zlog.h
+++ b/sapi/fpm/fpm/zlog.h
@@ -19,6 +19,10 @@ size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len);
void zlog_ex(const char *function, int line, int flags, const char *fmt, ...)
__attribute__ ((format(printf,4,5)));
+#ifdef HAVE_SYSLOG_H
+extern const int syslog_priorities[];
+#endif
+
enum {
ZLOG_DEBUG = 1,
ZLOG_NOTICE = 2,
@@ -33,4 +37,8 @@ enum {
#define ZLOG_SYSERROR (ZLOG_ERROR | ZLOG_HAVE_ERRNO)
+#ifdef HAVE_SYSLOG_H
+#define ZLOG_SYSLOG -2
+#endif
+
#endif
diff --git a/sapi/fpm/php-fpm.conf.in b/sapi/fpm/php-fpm.conf.in
index fe2f1a6dc..4e7952bdd 100644
--- a/sapi/fpm/php-fpm.conf.in
+++ b/sapi/fpm/php-fpm.conf.in
@@ -25,10 +25,25 @@
;pid = run/php-fpm.pid
; Error log file
+; If it's set to "syslog", log is sent to syslogd instead of being written
+; in a local file.
; Note: the default prefix is @EXPANDED_LOCALSTATEDIR@
; Default Value: log/php-fpm.log
;error_log = log/php-fpm.log
+; syslog_facility is used to specify what type of program is logging the
+; message. This lets syslogd specify that messages from different facilities
+; will be handled differently.
+; See syslog(3) for possible values (ex daemon equiv LOG_DAEMON)
+; Default Value: daemon
+;syslog.facility = daemon
+
+; syslog_ident is prepended to every message. If you have multiple FPM
+; instances running on the same server, you can change the default value
+; which must suit common needs.
+; Default Value: php-fpm
+;syslog.ident = php-fpm
+
; Log level
; Possible Values: alert, error, warning, notice, debug
; Default Value: notice
@@ -54,6 +69,13 @@
; Default Value: 0
;process_control_timeout = 0
+; The maximum number of processes FPM will fork. This has been design to control
+; the global number of processes when using dynamic PM within a lot of pools.
+; Use it with caution.
+; Note: A value of 0 indicates no limit
+; Default Value: 0
+; process.max = 128
+
; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging.
; Default Value: yes
;daemonize = yes
@@ -67,6 +89,16 @@
; Default Value: system defined value
;rlimit_core = 0
+; Specify the event mechanism FPM will use. The following is available:
+; - select (any POSIX os)
+; - poll (any POSIX os)
+; - epoll (linux >= 2.5.44)
+; - kqueue (FreeBSD >= 4.1, OpenBSD >= 2.9, NetBSD >= 2.0)
+; - /dev/poll (Solaris >= 7)
+; - port (Solaris >= 10)
+; Default Value: not set (auto detection)
+; events.mechanism = epoll
+
;;;;;;;;;;;;;;;;;;;;
; Pool Definitions ;
;;;;;;;;;;;;;;;;;;;;
@@ -94,6 +126,12 @@
; Default Value: none
;prefix = /path/to/pools/$pool
+; Unix user/group of processes
+; Note: The user is mandatory. If the group is not set, the default user's group
+; will be used.
+user = @php_fpm_user@
+group = @php_fpm_group@
+
; The address on which to accept FastCGI requests.
; Valid syntaxes are:
; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on
@@ -107,14 +145,6 @@ listen = 127.0.0.1:9000
; Set listen(2) backlog. A value of '-1' means unlimited.
; Default Value: 128 (-1 on FreeBSD and OpenBSD)
;listen.backlog = -1
-
-; List of ipv4 addresses of FastCGI clients which are allowed to connect.
-; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
-; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
-; must be separated by a comma. If this value is left blank, connections will be
-; accepted from any ip address.
-; Default Value: any
-;listen.allowed_clients = 127.0.0.1
; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
@@ -124,18 +154,21 @@ listen = 127.0.0.1:9000
;listen.owner = @php_fpm_user@
;listen.group = @php_fpm_group@
;listen.mode = 0666
-
-; Unix user/group of processes
-; Note: The user is mandatory. If the group is not set, the default user's group
-; will be used.
-user = @php_fpm_user@
-group = @php_fpm_group@
+
+; List of ipv4 addresses of FastCGI clients which are allowed to connect.
+; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
+; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
+; must be separated by a comma. If this value is left blank, connections will be
+; accepted from any ip address.
+; Default Value: any
+;listen.allowed_clients = 127.0.0.1
; Choose how the process manager will control the number of child processes.
; Possible Values:
; static - a fixed number (pm.max_children) of child processes;
; dynamic - the number of child processes are set dynamically based on the
-; following directives:
+; following directives. With this process management, there will be
+; always at least 1 children.
; pm.max_children - the maximum number of children that can
; be alive at the same time.
; pm.start_servers - the number of children created on startup.
@@ -147,33 +180,45 @@ group = @php_fpm_group@
; state (waiting to process). If the number
; of 'idle' processes is greater than this
; number then some children will be killed.
+; ondemand - no children are created at startup. Children will be forked when
+; new requests will connect. The following parameter are used:
+; pm.max_children - the maximum number of children that
+; can be alive at the same time.
+; pm.process_idle_timeout - The number of seconds after which
+; an idle process will be killed.
; Note: This value is mandatory.
pm = dynamic
; The number of child processes to be created when pm is set to 'static' and the
-; maximum number of child processes to be created when pm is set to 'dynamic'.
+; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
-; CGI.
-; Note: Used when pm is set to either 'static' or 'dynamic'
+; CGI. The below defaults are based on a server without much resources. Don't
+; forget to tweak pm.* to fit your needs.
+; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
; Note: This value is mandatory.
-pm.max_children = 50
+pm.max_children = 5
; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
-;pm.start_servers = 20
+pm.start_servers = 2
; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
-;pm.min_spare_servers = 5
+pm.min_spare_servers = 1
; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
-;pm.max_spare_servers = 35
+pm.max_spare_servers = 3
+
+; The number of seconds after which an idle process will be killed.
+; Note: Used only when pm is set to 'ondemand'
+; Default Value: 10s
+;pm.process_idle_timeout = 10s;
; The number of requests each child process should execute before respawning.
; This can be useful to work around memory leaks in 3rd party libraries. For
@@ -182,34 +227,98 @@ pm.max_children = 50
;pm.max_requests = 500
; The URI to view the FPM status page. If this value is not set, no URI will be
-; recognized as a status page. By default, the status page shows the following
-; information:
-; accepted conn - the number of request accepted by the pool;
+; recognized as a status page. It shows the following informations:
; pool - the name of the pool;
-; process manager - static or dynamic;
+; process manager - static, dynamic or ondemand;
+; start time - the date and time FPM has started;
+; start since - number of seconds since FPM has started;
+; accepted conn - the number of request accepted by the pool;
+; listen queue - the number of request in the queue of pending
+; connections (see backlog in listen(2));
+; max listen queue - the maximum number of requests in the queue
+; of pending connections since FPM has started;
+; listen queue len - the size of the socket queue of pending connections;
; idle processes - the number of idle processes;
; active processes - the number of active processes;
-; total processes - the number of idle + active processes.
+; total processes - the number of idle + active processes;
+; max active processes - the maximum number of active processes since FPM
+; has started;
; max children reached - number of times, the process limit has been reached,
; when pm tries to start more children (works only for
-; pm 'dynamic')
-; The values of 'idle processes', 'active processes' and 'total processes' are
-; updated each second. The value of 'accepted conn' is updated in real time.
+; pm 'dynamic' and 'ondemand');
+; Value are updated in real time.
; Example output:
-; accepted conn: 12073
; pool: www
; process manager: static
-; idle processes: 35
-; active processes: 65
-; total processes: 100
-; max children reached: 1
+; start time: 01/Jul/2011:17:53:49 +0200
+; start since: 62636
+; accepted conn: 190460
+; listen queue: 0
+; max listen queue: 1
+; listen queue len: 42
+; idle processes: 4
+; active processes: 11
+; total processes: 15
+; max active processes: 12
+; max children reached: 0
+;
; By default the status page output is formatted as text/plain. Passing either
-; 'html', 'xml' or 'json' as a query string will return the corresponding output
-; syntax. Example:
+; 'html', 'xml' or 'json' in the query string will return the corresponding
+; output syntax. Example:
; http://www.foo.bar/status
; http://www.foo.bar/status?json
; http://www.foo.bar/status?html
; http://www.foo.bar/status?xml
+;
+; By default the status page only outputs short status. Passing 'full' in the
+; query string will also return status for each pool process.
+; Example:
+; http://www.foo.bar/status?full
+; http://www.foo.bar/status?json&full
+; http://www.foo.bar/status?html&full
+; http://www.foo.bar/status?xml&full
+; The Full status returns for each process:
+; pid - the PID of the process;
+; state - the state of the process (Idle, Running, ...);
+; start time - the date and time the process has started;
+; start since - the number of seconds since the process has started;
+; requests - the number of requests the process has served;
+; request duration - the duration in µs of the requests;
+; request method - the request method (GET, POST, ...);
+; request URI - the request URI with the query string;
+; content length - the content length of the request (only with POST);
+; user - the user (PHP_AUTH_USER) (or '-' if not set);
+; script - the main script called (or '-' if not set);
+; last request cpu - the %cpu the last request consumed
+; it's always 0 if the process is not in Idle state
+; because CPU calculation is done when the request
+; processing has terminated;
+; last request memory - the max amount of memory the last request consumed
+; it's always 0 if the process is not in Idle state
+; because memory calculation is done when the request
+; processing has terminated;
+; If the process is in Idle state, then informations are related to the
+; last request the process has served. Otherwise informations are related to
+; the current request being served.
+; Example output:
+; ************************
+; pid: 31330
+; state: Running
+; start time: 01/Jul/2011:17:53:49 +0200
+; start since: 63087
+; requests: 12808
+; request duration: 1250261
+; request method: GET
+; request URI: /test_mem.php?N=10000
+; content length: 0
+; user: -
+; script: /home/fat/web/docs/php/test_mem.php
+; last request cpu: 0.00
+; last request memory: 0
+;
+; Note: There is a real-time FPM status monitoring sample web page available
+; It's available in: @EXPANDED_DATADIR@/fpm/status.html
+;
; Note: The value must start with a leading slash (/). The value can be
; anything, but it may not be a good idea to use the .php extension or it
; may conflict with a real PHP file.
@@ -292,12 +401,10 @@ pm.max_children = 50
; Default: "%R - %u %t \"%m %r\" %s"
;access.format = %R - %u %t "%m %r%Q%q" %s %f %{mili}d %{kilo}M %C%%
-; The timeout for serving a single request after which the worker process will
-; be killed. This option should be used when the 'max_execution_time' ini option
-; does not stop script execution for some reason. A value of '0' means 'off'.
-; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
-; Default Value: 0
-;request_terminate_timeout = 0
+; The log file for slow requests
+; Default Value: not set
+; Note: slowlog is mandatory if request_slowlog_timeout is set
+;slowlog = log/$pool.log.slow
; The timeout for serving a single request after which a PHP backtrace will be
; dumped to the 'slowlog' file. A value of '0s' means 'off'.
@@ -305,10 +412,12 @@ pm.max_children = 50
; Default Value: 0
;request_slowlog_timeout = 0
-; The log file for slow requests
-; Default Value: not set
-; Note: slowlog is mandatory if request_slowlog_timeout is set
-;slowlog = log/$pool.log.slow
+; The timeout for serving a single request after which the worker process will
+; be killed. This option should be used when the 'max_execution_time' ini option
+; does not stop script execution for some reason. A value of '0' means 'off'.
+; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
+; Default Value: 0
+;request_terminate_timeout = 0
; Set open file descriptor rlimit.
; Default Value: system defined value
@@ -341,6 +450,14 @@ pm.max_children = 50
; process time (several ms).
; Default Value: no
;catch_workers_output = yes
+
+; Limits the extensions of the main script FPM will allow to parse. This can
+; prevent configuration mistakes on the web server side. You should only limit
+; FPM to .php extensions to prevent malicious users to use other extensions to
+; exectute php code.
+; Note: set an empty value to allow all extensions.
+; Default Value: .php
+;security.limit_extensions = .php .php3 .php4 .php5
; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
diff --git a/sapi/fpm/status.html.in b/sapi/fpm/status.html.in
new file mode 100644
index 000000000..86492d73d
--- /dev/null
+++ b/sapi/fpm/status.html.in
@@ -0,0 +1,459 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+ $Id$
+ (c) 2011 Jerome Loyet
+ The PHP License, version 3.01
+ This is sample real-time status page for FPM. You can change it to better feet your needs.
+-->
+ <head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+ <style type="text/css">
+ body {background-color: #ffffff; color: #000000;}
+ body, td, th, h1, h2 {font-family: sans-serif;}
+ pre {margin: 0px; font-family: monospace;}
+ a:link {color: #000099; text-decoration: none; background-color: #ffffff;}
+ a:hover {text-decoration: underline;}
+ table {border-collapse: collapse;}
+ .center {text-align: center;}
+ .center table { margin-left: auto; margin-right: auto; text-align: left;}
+ .center th { text-align: center !important; }
+ td, th { border: 1px solid #000000; font-size: 75%; vertical-align: baseline;}
+ h1 {font-size: 150%;}
+ h2 {font-size: 125%;}
+ .p {text-align: left;}
+ .e {background-color: #ccccff; font-weight: bold; color: #000000;}
+ .h {background-color: #9999cc; font-weight: bold; color: #000000;}
+
+ .v {background-color: #cccccc; color: #000000;}
+ .w {background-color: #ccccff; color: #000000;}
+
+ .h th {
+ cursor: pointer;
+ }
+ img {float: right; border: 0px;}
+ hr {width: 600px; background-color: #cccccc; border: 0px; height: 1px; color: #000000;}
+ </style>
+ <title>PHP-FPM status page</title>
+ <meta name="ROBOTS" content="NOINDEX,NOFOLLOW,NOARCHIVE" /></head>
+ <body>
+ <div class="center">
+ <table border="0" cellpadding="3" width="95%">
+ <tr class="h">
+ <td>
+ <a href="http://www.php.net/"><img border="0" src="https://static.php.net/www.php.net/images/php.gif" alt="PHP Logo" /></a><h1 class="p">PHP-FPM real-time status page</h1>
+ </td>
+ </tr>
+ </table>
+ <br />
+ <table border="0" cellpadding="3" width="95%">
+ <tr><td class="e">Status URL</td><td class="v"><input type="text" id="url" size="45" /></td></tr>
+ <tr><td class="e">Ajax status</td><td class="v" id="status"></td></tr>
+ <tr><td class="e">Refresh Rate</td><td class="v"><input type="text" id="rate" value="1" /></td></tr>
+ <tr>
+ <td class="e">Actions</td>
+ <td class="v">
+ <button onclick="javascript:refresh();">Manual Refresh</button>
+ <button id="play" onclick="javascript:playpause();">Play</button>
+ </td>
+ </tr>
+ </table>
+ <h1>Pool Status</h1>
+ <table border="0" cellpadding="3" width="95%" id="short">
+ <tr style="display: none;"><td>&nbsp;</td></tr>
+ </table>
+ <h1>Active Processes status</h1>
+ <table border="0" cellpadding="3" width="95%" id="active">
+ <tr class="h"><th>PID&darr;</th><th>Start Time</th><th>Start Since</th><th>Requests Served</th><th>Request Duration</th><th>Request method</th><th>Request URI</th><th>Content Length</th><th>User</th><th>Script</th></tr>
+ </table>
+ <h1>Idle Processes status</h1>
+ <table border="0" cellpadding="3" width="95%" id="idle">
+ <tr class="h"><th>PID&darr;</th><th>Start Time</th><th>Start Since</th><th>Requests Served</th><th>Request Duration</th><th>Request method</th><th>Request URI</th><th>Content Length</th><th>User</th><th>Script</th><th>Last Request %CPU</th><th>Last Request Memory</th></tr>
+ </table>
+ </div>
+ <p>
+ <a href="http://validator.w3.org/check?uri=referer">
+ <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0 Transitional" height="31" width="88" />
+ </a>
+ </p>
+ <script type="text/javascript">
+<!--
+ var xhr_object = null;
+ var doc_url = document.getElementById("url");
+ var doc_rate = document.getElementById("rate");
+ var doc_status = document.getElementById("status");
+ var doc_play = document.getElementById("play");
+ var doc_short = document.getElementById("short");
+ var doc_active = document.getElementById("active");
+ var doc_idle = document.getElementById("idle");
+ var rate = 0;
+ var play=0;
+ var delay = 1000;
+ var order_active_index = 0;
+ var order_active_reverse = 0;
+ var order_idle_index = 0;
+ var order_idle_reverse = 0;
+ var sort_index;
+ var sort_order;
+
+ doc_url.value = location.protocol + '//' + location.host + "/status?json&full";
+
+ ths = document.getElementsByTagName("th");
+ for (var i=0; i<ths.length; i++) {
+ var th = ths[i];
+ if (th.parentNode.className == "h") {
+ th.onclick = function() { order(this); return false; };
+ }
+ }
+
+ xhr_object = create_ajax();
+
+ function create_ajax() {
+ if (window.XMLHttpRequest) {
+ return new XMLHttpRequest();
+ }
+ var names = [
+ "Msxml2.XMLHTTP.6.0",
+ "Msxml2.XMLHTTP.3.0",
+ "Msxml2.XMLHTTP",
+ "Microsoft.XMLHTTP"
+ ];
+ for(var i in names)
+ {
+ try {
+ return new ActiveXObject(names[i]);
+ } catch(e){}
+ }
+ alert("Browser not compatible ...");
+ }
+
+ function order(cell) {
+ var table;
+
+ if (cell.constructor != HTMLTableCellElement && cell.constructor != HTMLTableHeaderCellElement) {
+ return;
+ }
+
+ table = cell.parentNode.parentNode.parentNode;
+
+ if (table == doc_active) {
+ if (order_active_index == cell.cellIndex) {
+ if (order_active_reverse == 0) {
+ cell.innerHTML = cell.innerHTML.replace(/.$/, "&uarr;");
+ order_active_reverse = 1;
+ } else {
+ cell.innerHTML = cell.innerHTML.replace(/.$/, "&darr;");
+ order_active_reverse = 0;
+ }
+ } else {
+ var c = doc_active.rows[0].cells[order_active_index];
+ c.innerHTML = c.innerHTML.replace(/.$/, "");
+ cell.innerHTML = cell.innerHTML.replace(/$/, order_active_reverse == 0 ? "&darr;" : "&uarr;");
+ order_active_index = cell.cellIndex;
+ }
+ reorder(table, order_active_index, order_active_reverse);
+ return;
+ }
+
+ if (table == doc_idle) {
+ if (order_idle_index == cell.cellIndex) {
+ if (order_idle_reverse == 0) {
+ cell.innerHTML = cell.innerHTML.replace(/.$/, "&uarr;");
+ order_idle_reverse = 1;
+ } else {
+ cell.innerHTML = cell.innerHTML.replace(/.$/, "&darr;");
+ order_idle_reverse = 0;
+ }
+ } else {
+ var c = doc_idle.rows[0].cells[order_idle_index];
+ c.innerHTML = c.innerHTML.replace(/.$/, "");
+ cell.innerHTML = cell.innerHTML.replace(/$/, order_idle_reverse == 0 ? "&darr;" : "&uarr;");
+ order_idle_index = cell.cellIndex;
+ }
+ reorder(table, order_idle_index, order_idle_reverse);
+ return;
+ }
+ }
+
+ function reorder(table, index, order) {
+ var rows = [];
+ while (table.rows.length > 1) {
+ rows.push(table.rows[1]);
+ table.deleteRow(1);
+ }
+ sort_index = index;
+ sort_order = order;
+ rows.sort(sort_table);
+ for (var i in rows) {
+ table.appendChild(rows[i]);
+ }
+ var odd = 1;
+ for (var i=1; i<table.rows.length; i++) {
+ table.rows[i].className = odd++ % 2 == 0 ? "v" : "w";
+ }
+ return;
+ }
+
+ function sort_table(a, b) {
+ if (a.cells[0].tagName == "TH") return -1;
+ if (b.cells[0].tagName == "TH") return 1;
+
+ if (a.cells[sort_index].__search_t == 0) { /* integer */
+ if (!sort_order) return a.cells[sort_index].__search_v - b.cells[sort_index].__search_v;
+ return b.cells[sort_index].__search_v - a.cells[sort_index].__search_v;;
+ }
+
+ /* string */
+ if (!sort_order) return a.cells[sort_index].__search_v.localeCompare(b.cells[sort_index].__search_v);
+ else return b.cells[sort_index].__search_v.localeCompare(a.cells[sort_index].__search_v);
+ }
+
+ function playpause() {
+ rate = 0;
+ if (play) {
+ play = 0;
+ doc_play.innerHTML = "Play";
+ doc_rate.disabled = false;
+ } else {
+ delay = parseInt(doc_rate.value);
+ if (!delay || delay < 1) {
+ doc_status.innerHTML = "Not valid 'refresh' value";
+ return;
+ }
+ play = 1;
+ doc_rate.disabled = true;
+ doc_play.innerHTML = "Pause";
+ setTimeout("callback()", delay * 1000);
+ }
+ }
+
+ function refresh() {
+ if (xhr_object == null) return;
+ if (xhr_object.readyState > 0 && xhr_object.readyState < 4) {
+ return; /* request is running */
+ }
+ xhr_object.open("GET", doc_url.value, true);
+ xhr_object.onreadystatechange = function() {
+ switch(xhr_object.readyState) {
+ case 0:
+ doc_status.innerHTML = "uninitialized";
+ break;
+ case 1:
+ doc_status.innerHTML = "loading ...";
+ break;
+ case 2:
+ doc_status.innerHTML = "loaded";
+ break;
+ case 3:
+ doc_status.innerHTML = "interactive";
+ break;
+ case 4:
+ doc_status.innerHTML = "complete";
+ if (xhr_object.status == 200) {
+ fpm_status(xhr_object.responseText);
+ } else {
+ doc_status.innerHTML = "Error " + xhr_object.status;
+ }
+ break;
+ }
+ }
+ xhr_object.send();
+ }
+
+ function callback() {
+ if (!play) return;
+ refresh();
+ setTimeout("callback()", delay * 1000);
+ }
+
+ function fpm_status(txt) {
+ var json = null;
+
+ while (doc_short.rows.length > 0) {
+ doc_short.deleteRow(0);
+ }
+
+ while (doc_active.rows.length > 1) {
+ doc_active.deleteRow(1);
+ }
+
+ while (doc_idle.rows.length > 1) {
+ doc_idle.deleteRow(1);
+ }
+
+ try {
+ json = JSON.parse(txt);
+ } catch (e) {
+ doc_status.innerHTML = "Error while parsing json: '" + e + "': <br /><pre>" + txt + "</pre>";
+ return;
+ }
+
+ for (var key in json) {
+ if (key == "processes") continue;
+ if (key == "state") continue;
+ var row = doc_short.insertRow(doc_short.rows.length);
+ var value = json[key];
+ if (key == "start time") {
+ value = new Date(value * 1000).toLocaleString();
+ }
+ if (key == "start since") {
+ value = time_s(value);
+ }
+ var cell = row.insertCell(row.cells.length);
+ cell.className = "e";
+ cell.innerHTML = key;
+
+ cell = row.insertCell(row.cells.length);
+ cell.className = "v";
+ cell.innerHTML = value;
+ }
+
+ if (json.processes) {
+ process_full(json.processes, doc_active, "Idle", 0, 0);
+ reorder(doc_active, order_active_index, order_active_reverse);
+
+ process_full(json.processes, doc_idle, "Idle", 1, 1);
+ reorder(doc_idle, order_idle_index, order_idle_reverse);
+ }
+ }
+
+ function process_full(processes, table, state, equal, cpumem) {
+ var odd = 1;
+
+ for (var i in processes) {
+ var proc = processes[i];
+ if ((equal && proc.state == state) || (!equal && proc.state != state)) {
+ var c = odd++ % 2 == 0 ? "v" : "w";
+ var row = table.insertRow(-1);
+ row.className = c;
+ row.insertCell(-1).innerHTML = proc.pid;
+ row.cells[row.cells.length - 1].__search_v = proc.pid;
+ row.cells[row.cells.length - 1].__search_t = 0;
+
+ row.insertCell(-1).innerHTML = date(proc['start time'] * 1000);;
+ row.cells[row.cells.length - 1].__search_v = proc['start time'];
+ row.cells[row.cells.length - 1].__search_t = 0;
+
+ row.insertCell(-1).innerHTML = time_s(proc['start since']);
+ row.cells[row.cells.length - 1].__search_v = proc['start since'];
+ row.cells[row.cells.length - 1].__search_t = 0;
+
+ row.insertCell(-1).innerHTML = proc.requests;
+ row.cells[row.cells.length - 1].__search_v = proc.requests;
+ row.cells[row.cells.length - 1].__search_t = 0;
+
+ row.insertCell(-1).innerHTML = time_u(proc['request duration']);
+ row.cells[row.cells.length - 1].__search_v = proc['request duration'];
+ row.cells[row.cells.length - 1].__search_t = 0;
+
+ row.insertCell(-1).innerHTML = proc['request method'];
+ row.cells[row.cells.length - 1].__search_v = proc['request method'];
+ row.cells[row.cells.length - 1].__search_t = 1;
+
+ row.insertCell(-1).innerHTML = proc['request uri'];
+ row.cells[row.cells.length - 1].__search_v = proc['request uri'];
+ row.cells[row.cells.length - 1].__search_t = 1;
+
+ row.insertCell(-1).innerHTML = proc['content length'];
+ row.cells[row.cells.length - 1].__search_v = proc['content length'];
+ row.cells[row.cells.length - 1].__search_t = 0;
+
+ row.insertCell(-1).innerHTML = proc.user;
+ row.cells[row.cells.length - 1].__search_v = proc.user;
+ row.cells[row.cells.length - 1].__search_t = 1;
+
+ row.insertCell(-1).innerHTML = proc.script;
+ row.cells[row.cells.length - 1].__search_v = proc.script;
+ row.cells[row.cells.length - 1].__search_t = 1;
+
+ if (cpumem) {
+ row.insertCell(-1).innerHTML = cpu(proc['last request cpu']);
+ row.cells[row.cells.length - 1].__search_v = proc['last request cpu'];
+ row.cells[row.cells.length - 1].__search_t = 0;
+
+ row.insertCell(-1).innerHTML = memory(proc['last request memory']);
+ row.cells[row.cells.length - 1].__search_v = proc['last request memory'];
+ row.cells[row.cells.length - 1].__search_t = 0;
+ }
+ }
+ }
+ }
+
+ function date(d) {
+ var t = new Date(d);
+ var r = "";
+
+ r += (t.getDate() < 10 ? '0' : '') + t.getDate();
+ r += '/';
+ r += (t.getMonth() + 1 < 10 ? '0' : '') + (t.getMonth() + 1);
+ r += '/';
+ r += t.getFullYear();
+ r += ' ';
+ r += (t.getHours() < 10 ? '0' : '') + t.getHours();
+ r += ':';
+ r += (t.getMinutes() < 10 ? '0' : '') + t.getMinutes();
+ r += ':';
+ r += (t.getSeconds() < 10 ? '0' : '') + t.getSeconds();
+
+
+ return r;
+ }
+
+ function cpu(c) {
+ if (c == 0) return 0;
+ return c + "%";
+ }
+
+ function memory(mem) {
+ if (mem == 0) return 0;
+ if (mem < 1024) {
+ return mem + "B";
+ }
+ if (mem < 1024 * 1024) {
+ return mem/1024 + "KB";
+ }
+ if (mem < 1024*1024*1024) {
+ return mem/1024/1024 + "MB";
+ }
+ }
+
+ function time_s(t) {
+ var r = "";
+ if (t < 60) {
+ return t + 's';
+ }
+
+ r = (t % 60) + 's';
+ t = Math.floor(t / 60);
+ if (t < 60) {
+ return t + 'm ' + r;
+ }
+
+ r = (t % 60) + 'm ' + r;
+ t = Math.floor(t/60);
+
+ if (t < 24) {
+ return t + 'h ' + r;
+ }
+
+ return Math.floor(t/24) + 'd ' + (t % 24) + 'h ' + t;
+ }
+
+ function time_u(t) {
+ var r = "";
+ if (t < 1000) {
+ return t + '&micro;s'
+ }
+
+ r = (t % 1000) + '&micro;s';
+ t = Math.floor(t / 1000);
+ if (t < 1000) {
+ return t + 'ms ' + r;
+ }
+
+ return time_s(Math.floor(t/1000)) + ' ' + (t%1000) + 'ms ' + r;
+ }
+-->
+ </script>
+ </body>
+</html>
diff --git a/sapi/isapi/php5isapi.c b/sapi/isapi/php5isapi.c
index b013ba286..9dac7d901 100644
--- a/sapi/isapi/php5isapi.c
+++ b/sapi/isapi/php5isapi.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
| Ben Mansell <ben@zeus.com> (Zeus Support) |
+----------------------------------------------------------------------+
*/
-/* $Id: php5isapi.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: php5isapi.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php.h"
#include <httpext.h>
diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c
index 0a2f04a28..1796f6382 100644
--- a/sapi/litespeed/lsapi_main.c
+++ b/sapi/litespeed/lsapi_main.c
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: lsapi_main.c 311680 2011-05-31 22:40:42Z gwang $ */
+/* $Id: lsapi_main.c 321616 2011-12-31 18:15:06Z gwang $ */
#include "php.h"
#include "SAPI.h"
@@ -225,6 +225,7 @@ static int add_variable( const char * pKey, int keyLen, const char * pValue, int
}
+#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5)
static int add_variable_magic_quote( const char * pKey, int keyLen, const char * pValue, int valLen,
void * arg )
{
@@ -244,6 +245,8 @@ static int add_variable_magic_quote( const char * pKey, int keyLen, const char *
return 1;
}
+#endif
+
/* {{{ sapi_lsapi_register_variables
*/
static void sapi_lsapi_register_variables(zval *track_vars_array TSRMLS_DC)
@@ -253,15 +256,19 @@ static void sapi_lsapi_register_variables(zval *track_vars_array TSRMLS_DC)
if ( (SG(request_info).request_uri ) )
php_self = (SG(request_info).request_uri );
+#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5)
if (!PG(magic_quotes_gpc)) {
+#endif
LSAPI_ForeachHeader( add_variable, track_vars_array );
LSAPI_ForeachEnv( add_variable, track_vars_array );
add_variable("PHP_SELF", 8, php_self, strlen( php_self ), track_vars_array );
+#if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || PHP_MAJOR_VERSION < 5)
} else {
LSAPI_ForeachHeader( add_variable_magic_quote, track_vars_array );
LSAPI_ForeachEnv( add_variable_magic_quote, track_vars_array );
add_variable_magic_quote("PHP_SELF", 8, php_self, strlen( php_self ), track_vars_array );
}
+#endif
php_import_environment_variables(track_vars_array TSRMLS_CC);
} else {
php_import_environment_variables(track_vars_array TSRMLS_CC);
@@ -344,7 +351,7 @@ static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC)
/* {{{ sapi_lsapi_send_headers
*/
-static void sapi_lsapi_log_message(char *message)
+static void sapi_lsapi_log_message(char *message TSRMLS_DC)
{
int len = strlen( message );
LSAPI_Write_Stderr( message, len);
@@ -979,11 +986,17 @@ int main( int argc, char * argv[] )
/* LiteSpeed PHP module starts here */
+#if PHP_MAJOR_VERSION > 4
+
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO(arginfo_litespeed__void, 0)
ZEND_END_ARG_INFO()
/* }}} */
+#else
+#define arginfo_litespeed__void NULL
+#endif
+
PHP_FUNCTION(litespeed_request_headers);
PHP_FUNCTION(litespeed_response_headers);
@@ -1042,7 +1055,8 @@ PHP_FUNCTION(litespeed_request_headers)
}
array_init(return_value);
- LSAPI_ForeachOrgHeader( add_associate_array, return_value );
+ if ( lsapi_mode )
+ LSAPI_ForeachOrgHeader( add_associate_array, return_value );
}
/* }}} */
diff --git a/sapi/milter/php_milter.c b/sapi/milter/php_milter.c
index 188aa68bb..ce39501be 100644
--- a/sapi/milter/php_milter.c
+++ b/sapi/milter/php_milter.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_milter.c 314352 2011-08-06 01:22:27Z felipe $ */
+/* $Id: php_milter.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php.h"
#include "php_globals.h"
@@ -1111,7 +1111,7 @@ int main(int argc, char *argv[])
}
SG(headers_sent) = 1;
SG(request_info).no_headers = 1;
- php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2011 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
+ php_printf("PHP %s (%s) (built: %s %s)\nCopyright (c) 1997-2012 The PHP Group\n%s", PHP_VERSION, sapi_module.name, __DATE__, __TIME__, get_zend_version());
php_end_ob_buffers(1 TSRMLS_CC);
exit(1);
break;
diff --git a/sapi/nsapi/nsapi.c b/sapi/nsapi/nsapi.c
index b770f2dcc..353de227f 100644
--- a/sapi/nsapi/nsapi.c
+++ b/sapi/nsapi/nsapi.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: nsapi.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: nsapi.c 321634 2012-01-01 13:15:04Z felipe $ */
/*
* PHP includes
@@ -312,7 +312,7 @@ PHP_MSHUTDOWN_FUNCTION(nsapi)
PHP_MINFO_FUNCTION(nsapi)
{
php_info_print_table_start();
- php_info_print_table_row(2, "NSAPI Module Revision", "$Revision: 306939 $");
+ php_info_print_table_row(2, "NSAPI Module Revision", "$Revision: 321634 $");
php_info_print_table_row(2, "Server Software", system_version());
php_info_print_table_row(2, "Sub-requests with nsapi_virtual()",
(nsapi_servact_service)?((zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0))?"not supported with zlib.output_compression":"enabled"):"not supported on this platform" );
@@ -727,7 +727,9 @@ static void sapi_nsapi_register_server_variables(zval *track_vars_array TSRMLS_D
nsapi_free(value);
php_register_variable("SERVER_SOFTWARE", system_version(), track_vars_array TSRMLS_CC);
- php_register_variable("HTTPS", (security_active ? "ON" : "OFF"), track_vars_array TSRMLS_CC);
+ if (security_active) {
+ php_register_variable("HTTPS", "ON", track_vars_array TSRMLS_CC);
+ }
php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array TSRMLS_CC);
/* DOCUMENT_ROOT */
diff --git a/sapi/phttpd/php_phttpd.h b/sapi/phttpd/php_phttpd.h
index 0a0d2e53c..71cff9e37 100644
--- a/sapi/phttpd/php_phttpd.h
+++ b/sapi/phttpd/php_phttpd.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/sapi/phttpd/phttpd.c b/sapi/phttpd/phttpd.c
index 65773dda2..3aa196446 100644
--- a/sapi/phttpd/phttpd.c
+++ b/sapi/phttpd/phttpd.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/sapi/pi3web/pi3web_sapi.c b/sapi/pi3web/pi3web_sapi.c
index f0135af33..b099898f0 100644
--- a/sapi/pi3web/pi3web_sapi.c
+++ b/sapi/pi3web/pi3web_sapi.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -21,7 +21,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: pi3web_sapi.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: pi3web_sapi.c 321634 2012-01-01 13:15:04Z felipe $ */
#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
@@ -57,7 +57,7 @@ static void php_info_pi3web(ZEND_MODULE_INFO_FUNC_ARGS)
PUTS("<table border=0 cellpadding=3 cellspacing=1 width=600 align=center>\n");
PUTS("<tr><th colspan=2 bgcolor=\"" PHP_HEADER_COLOR "\">Pi3Web Server Information</th></tr>\n");
php_info_print_table_header(2, "Information Field", "Value");
- php_info_print_table_row(2, "Pi3Web SAPI module version", "$Id: pi3web_sapi.c 306939 2011-01-01 02:19:59Z felipe $");
+ php_info_print_table_row(2, "Pi3Web SAPI module version", "$Id: pi3web_sapi.c 321634 2012-01-01 13:15:04Z felipe $");
php_info_print_table_row(2, "Server Name Stamp", HTTPCore_getServerStamp());
snprintf(variable_buf, 511, "%d", HTTPCore_debugEnabled());
php_info_print_table_row(2, "Debug Enabled", variable_buf);
diff --git a/sapi/roxen/roxen.c b/sapi/roxen/roxen.c
index 723ffdd47..1031f46e0 100644
--- a/sapi/roxen/roxen.c
+++ b/sapi/roxen/roxen.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: roxen.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: roxen.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php.h"
#ifdef HAVE_ROXEN
@@ -438,7 +438,7 @@ static void php_info_roxen(ZEND_MODULE_INFO_FUNC_ARGS)
{
/* char buf[512]; */
php_info_print_table_start();
- php_info_print_table_row(2, "SAPI module version", "$Id: roxen.c 306939 2011-01-01 02:19:59Z felipe $");
+ php_info_print_table_row(2, "SAPI module version", "$Id: roxen.c 321634 2012-01-01 13:15:04Z felipe $");
/* php_info_print_table_row(2, "Build date", Ns_InfoBuildDate());
php_info_print_table_row(2, "Config file path", Ns_InfoConfigFile());
php_info_print_table_row(2, "Error Log path", Ns_InfoErrorLog());
diff --git a/sapi/thttpd/README b/sapi/thttpd/README
index 7529b7ecf..b0245841a 100644
--- a/sapi/thttpd/README
+++ b/sapi/thttpd/README
@@ -1,5 +1,5 @@
README FOR THTTPD MODULE (by Sascha Schumann)
-($Date: 2003-02-19 05:57:21 -0500 (Wed, 19 Feb 2003) $)
+($Date: 2003-02-19 11:57:21 +0100 (Wed, 19 Feb 2003) $)
This is a SAPI module for PHP 4.x supporting thttpd, the tiny,
turbo, throttling HTTP server by Jef Poskanzer.
diff --git a/sapi/thttpd/php_thttpd.h b/sapi/thttpd/php_thttpd.h
index e5d1c56e5..39a699c3c 100644
--- a/sapi/thttpd/php_thttpd.h
+++ b/sapi/thttpd/php_thttpd.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/sapi/thttpd/thttpd.c b/sapi/thttpd/thttpd.c
index 0e78c49e5..adddb2dba 100644
--- a/sapi/thttpd/thttpd.c
+++ b/sapi/thttpd/thttpd.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: thttpd.c 306939 2011-01-01 02:19:59Z felipe $ */
+/* $Id: thttpd.c 321634 2012-01-01 13:15:04Z felipe $ */
#include "php.h"
#include "SAPI.h"
diff --git a/sapi/tux/README b/sapi/tux/README
index cf2a6a0a9..3a5294c77 100644
--- a/sapi/tux/README
+++ b/sapi/tux/README
@@ -1,5 +1,5 @@
README FOR THE TUX MODULE (by Sascha Schumann)
-($Date: 2004-01-17 08:00:38 -0500 (Sat, 17 Jan 2004) $)
+($Date: 2004-01-17 14:00:38 +0100 (Sat, 17 Jan 2004) $)
This is a SAPI module for the TUX web-server by Ingo Molnar.
diff --git a/sapi/tux/php_tux.c b/sapi/tux/php_tux.c
index 8a1f44e15..cf11856f5 100644
--- a/sapi/tux/php_tux.c
+++ b/sapi/tux/php_tux.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/sapi/webjames/php_webjames.h b/sapi/webjames/php_webjames.h
index 1860352fc..163e753a2 100644
--- a/sapi/webjames/php_webjames.h
+++ b/sapi/webjames/php_webjames.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
diff --git a/sapi/webjames/webjames.c b/sapi/webjames/webjames.c
index 5a975ecd3..b7a7a2182 100644
--- a/sapi/webjames/webjames.c
+++ b/sapi/webjames/webjames.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2011 The PHP Group |
+ | Copyright (c) 1997-2012 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |