diff options
| author | Ondřej Surý <ondrej@sury.org> | 2011-08-19 10:22:38 +0200 |
|---|---|---|
| committer | Ondřej Surý <ondrej@sury.org> | 2011-08-19 10:22:38 +0200 |
| commit | f452a2b3e4e4279b27594a8ddb66525442d59227 (patch) | |
| tree | d05cb62c5515ada33076d3cc3e49b664733a478c /sapi | |
| parent | 038ba12e8724d537040e88ec794354b0c063f0a6 (diff) | |
| download | php-upstream/5.3.7.tar.gz | |
Imported Upstream version 5.3.7upstream/5.3.7
Diffstat (limited to 'sapi')
51 files changed, 1840 insertions, 907 deletions
diff --git a/sapi/apache2handler/apache_config.c b/sapi/apache2handler/apache_config.c index 3e97b5957..c7eafeb96 100644 --- a/sapi/apache2handler/apache_config.c +++ b/sapi/apache2handler/apache_config.c @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: apache_config.c 306939 2011-01-01 02:19:59Z felipe $ */ +/* $Id: apache_config.c 311342 2011-05-23 01:47:06Z felipe $ */ #define ZEND_INCLUDE_FULL_WINDOWS_HEADERS @@ -192,11 +192,12 @@ void apply_config(void *dummy) zend_hash_get_current_key_ex(&d->config, &str, &str_len, NULL, 0, NULL) == HASH_KEY_IS_STRING; zend_hash_move_forward(&d->config)) { - zend_hash_get_current_data(&d->config, (void **) &data); - phpapdebug((stderr, "APPLYING (%s)(%s)\n", str, data->value)); - if (zend_alter_ini_entry(str, str_len, data->value, data->value_len, data->status, data->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE) == FAILURE) { - phpapdebug((stderr, "..FAILED\n")); - } + if (zend_hash_get_current_data(&d->config, (void **) &data) == SUCCESS) { + phpapdebug((stderr, "APPLYING (%s)(%s)\n", str, data->value)); + if (zend_alter_ini_entry(str, str_len, data->value, data->value_len, data->status, data->htaccess?PHP_INI_STAGE_HTACCESS:PHP_INI_STAGE_ACTIVATE) == FAILURE) { + phpapdebug((stderr, "..FAILED\n")); + } + } } } diff --git a/sapi/apache_hooks/php_apache.c b/sapi/apache_hooks/php_apache.c index 8be927699..8a4920920 100644 --- a/sapi/apache_hooks/php_apache.c +++ b/sapi/apache_hooks/php_apache.c @@ -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 314352 2011-08-06 01:22:27Z felipe $ */ #include "php_apache_http.h" @@ -1384,7 +1384,7 @@ const static zend_function_entry php_apache_request_class_functions[] = { PHP_FALIAS(method_uri, apache_request_sub_req_method_uri, NULL) PHP_FALIAS(run, apache_request_run, NULL) PHP_FALIAS(internal_redirect, apache_request_internal_redirect, NULL) - { NULL, NULL, NULL } + PHP_FE_END }; /* }}} */ diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index 1ecbcb142..590419ee8 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: cgi_main.c 306939 2011-01-01 02:19:59Z felipe $ */ +/* $Id: cgi_main.c 314773 2011-08-11 06:38:42Z dmitry $ */ #include "php.h" #include "php_globals.h" @@ -725,7 +725,7 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha /* Check whether cache entry has expired and rescan if it is */ if (request_time > entry->expires) { - char * real_path; + char *real_path = NULL; int real_path_len; char *s1, *s2; int s_len; @@ -774,6 +774,9 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha php_parse_user_ini_file(path, PG(user_ini_filename), entry->user_config TSRMLS_CC); } + if (real_path) { + free(real_path); + } entry->expires = request_time + PG(user_ini_cache_ttl); } diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index 1d0a0ed1a..c80d46490 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -20,7 +20,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_cli.c 306939 2011-01-01 02:19:59Z felipe $ */ +/* $Id: php_cli.c 314468 2011-08-08 07:12:12Z laruence $ */ #include "php.h" #include "php_globals.h" @@ -29,9 +29,7 @@ #include "zend_modules.h" #include "zend_interfaces.h" -#ifdef HAVE_REFLECTION #include "ext/reflection/php_reflection.h" -#endif #include "SAPI.h" @@ -159,14 +157,12 @@ static const opt_struct OPTIONS[] = { {'?', 0, "usage"},/* help alias (both '?' and 'usage') */ {'v', 0, "version"}, {'z', 1, "zend-extension"}, -#ifdef HAVE_REFLECTION {10, 1, "rf"}, {10, 1, "rfunction"}, {11, 1, "rc"}, {11, 1, "rclass"}, {12, 1, "re"}, {12, 1, "rextension"}, -#endif {13, 1, "ri"}, {13, 1, "rextinfo"}, {14, 0, "ini"}, @@ -519,11 +515,9 @@ static void php_cli_usage(char *argv0) "\n" " --ini Show configuration file names\n" "\n" -#if (HAVE_REFLECTION) " --rf <name> Show information about function <name>.\n" " --rc <name> Show information about class <name>.\n" " --re <name> Show information about extension <name>.\n" -#endif " --ri <name> Show configuration for extension <name>.\n" "\n" , prog, prog, prog, prog, prog, prog); @@ -602,7 +596,7 @@ static const char *param_mode_conflict = "Either execute direct code, process st */ static int cli_seek_file_begin(zend_file_handle *file_handle, char *script_file, int *lineno TSRMLS_DC) { - char c; + int c; *lineno = 1; @@ -799,7 +793,7 @@ int main(int argc, char *argv[]) request_started = 1; php_cli_usage(argv[0]); php_end_ob_buffers(1 TSRMLS_CC); - exit_status=0; + exit_status = (c == '?' && argc > 1 && !strchr(argv[1], c)); goto out; case 'i': /* php info & quit */ @@ -1005,8 +999,6 @@ int main(int argc, char *argv[]) case 'H': hide_argv = 1; break; - -#ifdef HAVE_REFLECTION case 10: behavior=PHP_MODE_REFLECTION_FUNCTION; reflection_what = php_optarg; @@ -1019,7 +1011,6 @@ int main(int argc, char *argv[]) behavior=PHP_MODE_REFLECTION_EXTENSION; reflection_what = php_optarg; break; -#endif case 13: behavior=PHP_MODE_REFLECTION_EXT_INFO; reflection_what = php_optarg; @@ -1285,7 +1276,6 @@ int main(int argc, char *argv[]) break; } -#ifdef HAVE_REFLECTION case PHP_MODE_REFLECTION_FUNCTION: case PHP_MODE_REFLECTION_CLASS: case PHP_MODE_REFLECTION_EXTENSION: @@ -1336,7 +1326,6 @@ int main(int argc, char *argv[]) break; } -#endif /* reflection */ case PHP_MODE_REFLECTION_EXT_INFO: { int len = strlen(reflection_what); @@ -1361,7 +1350,7 @@ int main(int argc, char *argv[]) { zend_printf("Configuration File (php.ini) Path: %s\n", PHP_CONFIG_FILE_PATH); zend_printf("Loaded Configuration File: %s\n", php_ini_opened_path ? php_ini_opened_path : "(none)"); - zend_printf("Scan for additional .ini files in: %s\n", *PHP_CONFIG_FILE_SCAN_DIR ? PHP_CONFIG_FILE_SCAN_DIR : "(none)"); + zend_printf("Scan for additional .ini files in: %s\n", php_ini_scanned_path ? php_ini_scanned_path : "(none)"); zend_printf("Additional .ini files parsed: %s\n", php_ini_scanned_files ? php_ini_scanned_files : "(none)"); break; } diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4 index 6899ea790..1105ec8d2 100644 --- a/sapi/fpm/config.m4 +++ b/sapi/fpm/config.m4 @@ -340,6 +340,33 @@ AC_DEFUN([AC_FPM_LQ], ]) dnl }}} +AC_DEFUN([AC_FPM_SYSCONF], +[ + AC_MSG_CHECKING([for sysconf]) + + AC_TRY_COMPILE([ #include <unistd.h> ], [sysconf(_SC_CLK_TCK);], [ + AC_DEFINE([HAVE_SYSCONF], 1, [do we have sysconf?]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) +]) +dnl }}} + +AC_DEFUN([AC_FPM_TIMES], +[ + AC_MSG_CHECKING([for times]) + + AC_TRY_COMPILE([ #include <sys/times.h> ], [struct tms t; times(&t);], [ + AC_DEFINE([HAVE_TIMES], 1, [do we have times?]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) +]) +dnl }}} + + AC_MSG_CHECKING(for FPM build) if test "$PHP_FPM" != "no"; then AC_MSG_RESULT($PHP_FPM) @@ -350,6 +377,8 @@ if test "$PHP_FPM" != "no"; then AC_FPM_TRACE AC_FPM_BUILTIN_ATOMIC AC_FPM_LQ + AC_FPM_SYSCONF + AC_FPM_TIMES PHP_ARG_WITH(fpm-user,, [ --with-fpm-user[=USER] Set the user for php-fpm to run as. (default: nobody)], nobody, no) @@ -403,13 +432,14 @@ if test "$PHP_FPM" != "no"; then fpm/fpm_conf.c \ fpm/fpm_env.c \ fpm/fpm_events.c \ + fpm/fpm_log.c \ fpm/fpm_main.c \ fpm/fpm_php.c \ fpm/fpm_php_trace.c \ fpm/fpm_process_ctl.c \ fpm/fpm_request.c \ fpm/fpm_shm.c \ - fpm/fpm_shm_slots.c \ + fpm/fpm_scoreboard.c \ fpm/fpm_signals.c \ fpm/fpm_sockets.c \ fpm/fpm_status.c \ diff --git a/sapi/fpm/fpm/fastcgi.c b/sapi/fpm/fpm/fastcgi.c index a1644ed12..22a8f3a2f 100644 --- a/sapi/fpm/fpm/fastcgi.c +++ b/sapi/fpm/fpm/fastcgi.c @@ -28,13 +28,10 @@ #include <errno.h> #include <limits.h> -#ifdef FPM_AUTOCONFIG_H -#include <fpm_autoconfig.h> -#else #include <php_config.h> -#endif #include <fpm/fpm.h> #include <fpm/fpm_request.h> +#include <fpm/zlog.h> #ifdef _WIN32 @@ -149,6 +146,8 @@ static int is_fastcgi = 0; static int in_shutdown = 0; static in_addr_t *allowed_clients = NULL; +static sa_t client_sa; + #ifdef _WIN32 static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg) @@ -192,7 +191,7 @@ int fcgi_init(void) 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); + fcgi_set_mgmt_var("FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS") - 1, "0", sizeof("0")-1); is_initialized = 1; #ifdef _WIN32 @@ -833,7 +832,9 @@ int fcgi_accept_request(fcgi_request *req) FCGI_LOCK(req->listen_socket); req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len); FCGI_UNLOCK(req->listen_socket); - if (req->fd >= 0 && allowed_clients) { + + client_sa = sa; + if (sa.sa.sa_family == AF_INET && req->fd >= 0 && allowed_clients) { int n = 0; int allowed = 0; @@ -1118,6 +1119,14 @@ void fcgi_free_mgmt_var_cb(void * ptr) pefree(*var, 1); } +char *fcgi_get_last_client_ip() /* {{{ */ +{ + if (client_sa.sa.sa_family == AF_UNIX) { + return NULL; + } + return inet_ntoa(client_sa.sa_inet.sin_addr); +} +/* }}} */ /* * Local variables: * tab-width: 4 diff --git a/sapi/fpm/fpm/fastcgi.h b/sapi/fpm/fpm/fastcgi.h index 565fd3fb1..4129def05 100644 --- a/sapi/fpm/fpm/fastcgi.h +++ b/sapi/fpm/fpm/fastcgi.h @@ -135,6 +135,8 @@ 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); void fcgi_free_mgmt_var_cb(void * ptr); +char *fcgi_get_last_client_ip(); + /* * Local variables: * tab-width: 4 diff --git a/sapi/fpm/fpm/fpm.c b/sapi/fpm/fpm/fpm.c index 0cfaabd41..57efcfd75 100644 --- a/sapi/fpm/fpm/fpm.c +++ b/sapi/fpm/fpm/fpm.c @@ -18,25 +18,28 @@ #include "fpm_process_ctl.h" #include "fpm_conf.h" #include "fpm_worker_pool.h" +#include "fpm_scoreboard.h" #include "fpm_stdio.h" +#include "fpm_log.h" #include "zlog.h" struct fpm_globals_s fpm_globals = { - .parent_pid = 0, - .argc = 0, - .argv = NULL, - .config = NULL, - .prefix = NULL, - .running_children = 0, - .error_log_fd = 0, - .log_level = 0, - .listening_socket = 0, - .max_requests = 0, - .is_child = 0, - .test_successful = 0 - }; - -int fpm_init(int argc, char **argv, char *config, char *prefix, int test_conf) /* {{{ */ + .parent_pid = 0, + .argc = 0, + .argv = NULL, + .config = NULL, + .prefix = NULL, + .pid = NULL, + .running_children = 0, + .error_log_fd = 0, + .log_level = 0, + .listening_socket = 0, + .max_requests = 0, + .is_child = 0, + .test_successful = 0 +}; + +int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int test_conf) /* {{{ */ { fpm_globals.argc = argc; fpm_globals.argv = argv; @@ -44,19 +47,22 @@ int fpm_init(int argc, char **argv, char *config, char *prefix, int test_conf) / fpm_globals.config = strdup(config); } fpm_globals.prefix = prefix; + fpm_globals.pid = pid; + + 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() || + 0 > fpm_pctl_init_main() || + 0 > fpm_env_init_main() || + 0 > fpm_signals_init_main() || + 0 > fpm_children_init_main() || + 0 > fpm_sockets_init_main() || + 0 > fpm_worker_pool_init_main() || + 0 > fpm_event_init_main()) { - if (0 > fpm_php_init_main() || - 0 > fpm_stdio_init_main() || - 0 > fpm_conf_init_main(test_conf) || - 0 > fpm_unix_init_main() || - 0 > fpm_pctl_init_main() || - 0 > fpm_env_init_main() || - 0 > fpm_signals_init_main() || - 0 > fpm_children_init_main() || - 0 > fpm_sockets_init_main() || - 0 > fpm_worker_pool_init_main() || - 0 > fpm_event_init_main()) { - if (fpm_globals.test_successful) { exit(0); } else { @@ -90,10 +96,16 @@ int fpm_run(int *max_requests) /* {{{ */ if (!is_parent) { goto run_child; } + + /* handle error */ + if (is_parent == 2) { + fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET); + fpm_event_loop(1); + } } /* run event loop forever */ - fpm_event_loop(); + fpm_event_loop(0); run_child: /* only workers reach this point */ diff --git a/sapi/fpm/fpm/fpm.h b/sapi/fpm/fpm/fpm.h index f06d9ed6a..3c6f798fb 100644 --- a/sapi/fpm/fpm/fpm.h +++ b/sapi/fpm/fpm/fpm.h @@ -8,7 +8,7 @@ #include <unistd.h> int fpm_run(int *max_requests); -int fpm_init(int argc, char **argv, char *config, char *prefix, int test_conf); +int fpm_init(int argc, char **argv, char *config, char *prefix, char *pid, int test_conf); struct fpm_globals_s { pid_t parent_pid; @@ -16,6 +16,7 @@ struct fpm_globals_s { char **argv; char *config; char *prefix; + char *pid; int running_children; int error_log_fd; int log_level; diff --git a/sapi/fpm/fpm/fpm_atomic.h b/sapi/fpm/fpm/fpm_atomic.h index 638bafddc..662dd4726 100644 --- a/sapi/fpm/fpm/fpm_atomic.h +++ b/sapi/fpm/fpm/fpm_atomic.h @@ -146,7 +146,7 @@ static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, at static inline int fpm_spinlock(atomic_t *lock, int try_once) /* {{{ */ { if (try_once) { - return atomic_cmp_set(lock, 0, 1) ? 0 : -1; + return atomic_cmp_set(lock, 0, 1) ? 1 : 0; } for (;;) { @@ -158,9 +158,11 @@ static inline int fpm_spinlock(atomic_t *lock, int try_once) /* {{{ */ sched_yield(); } - return 0; + return 1; } /* }}} */ +#define fpm_unlock(lock) lock = 0 + #endif diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c index 499ad08e8..94580194f 100644 --- a/sapi/fpm/fpm/fpm_children.c +++ b/sapi/fpm/fpm/fpm_children.c @@ -25,8 +25,9 @@ #include "fpm_stdio.h" #include "fpm_unix.h" #include "fpm_env.h" -#include "fpm_shm_slots.h" +#include "fpm_scoreboard.h" #include "fpm_status.h" +#include "fpm_log.h" #include "zlog.h" @@ -50,6 +51,7 @@ static struct fpm_child_s *fpm_child_alloc() /* {{{ */ } memset(ret, 0, sizeof(*ret)); + ret->scoreboard_i = -1; return ret; } /* }}} */ @@ -146,6 +148,7 @@ 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() || @@ -236,7 +239,7 @@ void fpm_children_bury() /* {{{ */ fpm_child_unlink(child); - fpm_shm_slots_discard_slot(child); + fpm_scoreboard_proc_free(wp->scoreboard, child->scoreboard_i); fpm_clock_get(&tv1); @@ -314,7 +317,7 @@ static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) / return 0; } - if (0 > fpm_shm_slots_prepare_slot(c)) { + if (0 > fpm_scoreboard_proc_alloc(wp->scoreboard, &c->scoreboard_i)) { fpm_stdio_discard_pipes(c); fpm_child_free(c); return 0; @@ -326,7 +329,7 @@ static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) / static void fpm_resources_discard(struct fpm_child_s *child) /* {{{ */ { - fpm_shm_slots_discard_slot(child); + fpm_scoreboard_proc_free(child->wp->scoreboard, child->scoreboard_i); fpm_stdio_discard_pipes(child); fpm_child_free(child); } @@ -334,7 +337,14 @@ static void fpm_resources_discard(struct fpm_child_s *child) /* {{{ */ static void fpm_child_resources_use(struct fpm_child_s *child) /* {{{ */ { - fpm_shm_slots_child_use_slot(child); + struct fpm_worker_pool_s *wp; + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { + if (wp == child->wp) { + continue; + } + 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); } @@ -342,7 +352,6 @@ static void fpm_child_resources_use(struct fpm_child_s *child) /* {{{ */ static void fpm_parent_resources_use(struct fpm_child_s *child) /* {{{ */ { - fpm_shm_slots_parent_use_slot(child); fpm_stdio_parent_use_pipes(child); fpm_child_link(child); } @@ -350,7 +359,6 @@ static void fpm_parent_resources_use(struct fpm_child_s *child) /* {{{ */ int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to_spawn, int is_debug) /* {{{ */ { - int enough = 0; pid_t pid; struct fpm_child_s *child; int max; @@ -365,12 +373,11 @@ int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to max = wp->config->pm_max_children; } - while (!enough && fpm_pctl_can_spawn_children() && wp->running_children < max) { + while (fpm_pctl_can_spawn_children() && wp->running_children < max) { child = fpm_resources_prepare(wp); if (!child) { - enough = 1; - break; + return 2; } pid = fork(); @@ -385,11 +392,9 @@ int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to case -1 : zlog(ZLOG_SYSERROR, "fork() failed"); - enough = 1; fpm_resources_discard(child); - - break; /* dont try any more on error */ + return 2; default : child->pid = pid; diff --git a/sapi/fpm/fpm/fpm_children.h b/sapi/fpm/fpm/fpm_children.h index 4010a4f3b..9c79f234e 100644 --- a/sapi/fpm/fpm/fpm_children.h +++ b/sapi/fpm/fpm/fpm_children.h @@ -30,6 +30,7 @@ struct fpm_child_s { struct timeval slow_logged; int idle_kill; pid_t pid; + int scoreboard_i; }; #endif diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c index 5d6fe770c..6a37ae27f 100644 --- a/sapi/fpm/fpm/fpm_conf.c +++ b/sapi/fpm/fpm/fpm_conf.c @@ -41,8 +41,15 @@ #include "fpm_sockets.h" #include "fpm_shm.h" #include "fpm_status.h" +#include "fpm_log.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_time(zval *value, void **config, intptr_t offset); @@ -59,47 +66,48 @@ static char *ini_filename = NULL; static int ini_lineno = 0; static char *ini_include = NULL; -#define GO(field) offsetof(struct fpm_global_config_s, field) -#define WPO(field) offsetof(struct fpm_worker_pool_config_s, field) - 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 }, + { "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) }, { 0, 0, 0 } }; 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.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.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) }, + { "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.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.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) }, { 0, 0, 0 } }; @@ -115,6 +123,9 @@ static int fpm_conf_is_dir(char *path) /* {{{ */ } /* }}} */ +/* + * Expands the '$pool' token in a dynamically allocated string + */ static int fpm_conf_expand_pool_name(char **value) { char *token; @@ -122,15 +133,23 @@ static int fpm_conf_expand_pool_name(char **value) { return 0; } - while ((token = strstr(*value, "$pool"))) { + while (*value && (token = strstr(*value, "$pool"))) { char *buf; - char *p1 = *value; char *p2 = token + strlen("$pool"); + + /* If we are not in a pool, we cannot expand this name now */ if (!current_wp || !current_wp->config || !current_wp->config->name) { return -1; } + + /* "aaa$poolbbb" becomes "aaa\0oolbbb" */ token[0] = '\0'; - spprintf(&buf, 0, "%s%s%s", p1, current_wp->config->name, p2); + + /* Build a brand new string with the expanded token */ + spprintf(&buf, 0, "%s%s%s", *value, current_wp->config->name, p2); + + /* Free the previous value and save the new one */ + free(*value); *value = strdup(buf); efree(buf); } @@ -179,7 +198,7 @@ static char *fpm_conf_set_integer(zval *value, void **config, intptr_t offset) / char *val = Z_STRVAL_P(value); char *p; - for(p=val; *p; 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)"; @@ -255,10 +274,10 @@ 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) /* {{{ */ { char *val = Z_STRVAL_P(value); - struct fpm_worker_pool_config_s *c = *config; + int *ptr = (int *) ((char *) *config + offset); if (!strcasecmp(val, "unlimited")) { - c->rlimit_core = -1; + *ptr = -1; } else { int int_value; void *subconf = &int_value; @@ -274,7 +293,7 @@ static char *fpm_conf_set_rlimit_core(zval *value, void **config, intptr_t offse return "must be greater than zero or 'unlimited'"; } - c->rlimit_core = int_value; + *ptr = int_value; } return NULL; @@ -412,6 +431,8 @@ int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc) /* {{{ */ free(wpc->chdir); free(wpc->slowlog); free(wpc->prefix); + free(wpc->access_log); + free(wpc->access_format); return 0; } @@ -606,7 +627,7 @@ static int fpm_conf_process_all_pools() /* {{{ */ return -1; } - for (i=0; i<strlen(ping); i++) { + for (i = 0; i < strlen(ping); i++) { if (!isalnum(ping[i]) && ping[i] != '/' && ping[i] != '-' && ping[i] != '_' && ping[i] != '.') { zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' must containt only the following characters '[alphanum]/_-.'", wp->config->name, ping); return -1; @@ -643,22 +664,19 @@ static int fpm_conf_process_all_pools() /* {{{ */ return -1; } - for (i=0; i<strlen(status); i++) { + 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; } } - wp->shm_status = fpm_shm_alloc(sizeof(struct fpm_status_s)); - if (!wp->shm_status) { - zlog(ZLOG_ERROR, "[pool %s] unable to allocate shared memory for status page '%s'", wp->config->name, status); - return -1; + } + + 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_status_update_accepted_conn(wp->shm_status, 0); - fpm_status_update_activity(wp->shm_status, -1, -1, -1, 0, -1, 1); - fpm_status_update_max_children_reached(wp->shm_status, 0); - fpm_status_set_pm(wp->shm_status, wp->config->pm); - /* memset(&fpm_status.last_update, 0, sizeof(fpm_status.last_update)); */ } if (wp->config->chroot && *wp->config->chroot) { @@ -709,14 +727,14 @@ static int fpm_conf_process_all_pools() /* {{{ */ char **p; for (kv = wp->config->php_values; kv; kv = kv->next) { - for (p=options; *p; p++) { + for (p = options; *p; p++) { if (!strcasecmp(kv->key, *p)) { fpm_evaluate_full_path(&kv->value, wp, NULL, 0); } } } for (kv = wp->config->php_admin_values; kv; kv = kv->next) { - for (p=options; *p; p++) { + for (p = options; *p; p++) { if (!strcasecmp(kv->key, *p)) { fpm_evaluate_full_path(&kv->value, wp, NULL, 0); } @@ -768,8 +786,10 @@ int fpm_conf_write_pid() /* {{{ */ } /* }}} */ -static int fpm_conf_post_process() /* {{{ */ +static int fpm_conf_post_process(TSRMLS_D) /* {{{ */ { + struct fpm_worker_pool_s *wp; + if (fpm_global_config.pid_file) { fpm_evaluate_full_path(&fpm_global_config.pid_file, NULL, PHP_LOCALSTATEDIR, 0); } @@ -784,7 +804,25 @@ static int fpm_conf_post_process() /* {{{ */ return -1; } - return fpm_conf_process_all_pools(); + if (0 > fpm_log_open(0)) { + return -1; + } + + if (0 > fpm_conf_process_all_pools()) { + return -1; + } + + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { + if (!wp->config->access_log || !*wp->config->access_log) { + continue; + } + if (0 > fpm_log_write(wp->config->access_format TSRMLS_CC)) { + zlog(ZLOG_ERROR, "[pool %s] wrong format for access.format '%s'", wp->config->name, wp->config->access_format); + return -1; + } + } + + return 0; } /* }}} */ @@ -826,7 +864,7 @@ static void fpm_conf_ini_parser_include(char *inc, void *arg TSRMLS_DC) /* {{{ * return; } - for(i=0; i<g.gl_pathc; i++) { + for (i = 0; i < g.gl_pathc; i++) { int len = strlen(g.gl_pathv[i]); if (len < 1) continue; if (g.gl_pathv[i][len - 1] == '/') continue; /* don't parse directories */ @@ -920,7 +958,7 @@ static void fpm_conf_ini_parser_entry(zval *name, zval *value, void *arg TSRMLS_ config = current_wp->config; } - for (;parser->name; parser++) { + for (; parser->name; parser++) { if (!strcasecmp(parser->name, Z_STRVAL_P(name))) { char *ret; if (!parser->parser) { @@ -1069,7 +1107,7 @@ int fpm_conf_load_ini_file(char *filename TSRMLS_DC) /* {{{ */ while (nb_read > 0) { int tmp; memset(buf, 0, sizeof(char) * (1024 + 1)); - for (n=0; n<1024 && (nb_read = read(fd, &c, sizeof(char))) == sizeof(char) && c != '\n'; n++) { + for (n = 0; n < 1024 && (nb_read = read(fd, &c, sizeof(char))) == sizeof(char) && c != '\n'; n++) { buf[n] = c; } buf[n++] = '\n'; @@ -1110,45 +1148,49 @@ static void fpm_conf_dump() /* {{{ */ struct fpm_worker_pool_s *wp; 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)); - zlog(ZLOG_NOTICE, "\tlog_level = %s", zlog_get_level_name()); - zlog(ZLOG_NOTICE, "\tprocess_control_timeout = %ds", fpm_global_config.process_control_timeout); + 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)); + 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, "\trlimit_files = %d", fpm_global_config.rlimit_files); + zlog(ZLOG_NOTICE, "\trlimit_core = %d", fpm_global_config.rlimit_core); zlog(ZLOG_NOTICE, " "); for (wp = fpm_worker_all_pools; wp; wp = wp->next) { struct key_value_s *kv; if (!wp->config) continue; - zlog(ZLOG_NOTICE, "[%s]", STR2STR(wp->config->name)); - 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)); - zlog(ZLOG_NOTICE, "\tlisten.group = %s", STR2STR(wp->config->listen_group)); - zlog(ZLOG_NOTICE, "\tlisten.mode = %s", STR2STR(wp->config->listen_mode)); - 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.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, "\tcatch_workers_output = %s", BOOL2STR(wp->config->catch_workers_output)); + zlog(ZLOG_NOTICE, "[%s]", STR2STR(wp->config->name)); + 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)); + zlog(ZLOG_NOTICE, "\tlisten.group = %s", STR2STR(wp->config->listen_group)); + zlog(ZLOG_NOTICE, "\tlisten.mode = %s", STR2STR(wp->config->listen_mode)); + 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.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, "\trlimit_files = %d", wp->config->rlimit_files); - zlog(ZLOG_NOTICE, "\trlimit_core = %d", wp->config->rlimit_core); + zlog(ZLOG_NOTICE, "\trequest_slowlog_timeout = %ds", wp->config->request_slowlog_timeout); + zlog(ZLOG_NOTICE, "\tslowlog = %s", STR2STR(wp->config->slowlog)); + zlog(ZLOG_NOTICE, "\trlimit_files = %d", wp->config->rlimit_files); + zlog(ZLOG_NOTICE, "\trlimit_core = %d", wp->config->rlimit_core); for (kv = wp->config->env; kv; kv = kv->next) { zlog(ZLOG_NOTICE, "\tenv[%s] = %s", kv->key, kv->value); @@ -1178,6 +1220,10 @@ int fpm_conf_init_main(int test_conf) /* {{{ */ } } + if (fpm_globals.pid && *fpm_globals.pid) { + fpm_global_config.pid_file = strdup(fpm_globals.pid); + } + if (fpm_globals.config == NULL) { char *tmp; @@ -1208,7 +1254,7 @@ int fpm_conf_init_main(int test_conf) /* {{{ */ return -1; } - if (0 > fpm_conf_post_process()) { + if (0 > fpm_conf_post_process(TSRMLS_C)) { zlog(ZLOG_ERROR, "failed to post process the configuration"); return -1; } diff --git a/sapi/fpm/fpm/fpm_conf.h b/sapi/fpm/fpm/fpm_conf.h index ac38ee2e9..2152527ee 100644 --- a/sapi/fpm/fpm/fpm_conf.h +++ b/sapi/fpm/fpm/fpm_conf.h @@ -10,10 +10,6 @@ #define FPM_CONF_MAX_PONG_LENGTH 64 -#define STR2STR(a) (a ? a : "undefined") -#define BOOL2STR(a) (a ? "yes" : "no") -#define PM2STR(a) (a == PM_STYLE_STATIC ? "static" : "dynamic") - struct key_value_s; struct key_value_s { @@ -29,6 +25,8 @@ struct fpm_global_config_s { int daemonize; char *pid_file; char *error_log; + int rlimit_files; + int rlimit_core; }; extern struct fpm_global_config_s fpm_global_config; @@ -55,6 +53,8 @@ struct fpm_worker_pool_config_s { int pm_max_spare_servers; char *ping_path; char *ping_response; + char *access_log; + char *access_format; char *listen_address; int listen_backlog; char *listen_owner; @@ -72,7 +72,10 @@ struct ini_value_parser_s { intptr_t offset; }; -enum { PM_STYLE_STATIC = 1, PM_STYLE_DYNAMIC = 2 }; +enum { + PM_STYLE_STATIC = 1, + PM_STYLE_DYNAMIC = 2 +}; int fpm_conf_init_main(int test_conf); int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc); diff --git a/sapi/fpm/fpm/fpm_config.h b/sapi/fpm/fpm/fpm_config.h index 3637f376c..856414a92 100644 --- a/sapi/fpm/fpm/fpm_config.h +++ b/sapi/fpm/fpm/fpm_config.h @@ -3,10 +3,6 @@ #include <php_config.h> -#ifdef FPM_AUTOCONFIG_H -# include <fpm_autoconfig.h> -#endif - /* Solaris does not have it */ #ifndef INADDR_NONE # define INADDR_NONE (-1) diff --git a/sapi/fpm/fpm/fpm_env.c b/sapi/fpm/fpm/fpm_env.c index aa647d15b..03bf82340 100644 --- a/sapi/fpm/fpm/fpm_env.c +++ b/sapi/fpm/fpm/fpm_env.c @@ -141,7 +141,7 @@ int fpm_env_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ struct key_value_s *kv; char *title; spprintf(&title, 0, "pool %s", wp->config->name); - fpm_env_setproctitle(title); + fpm_env_setproctitle(title); efree(title); clearenv(); diff --git a/sapi/fpm/fpm/fpm_events.c b/sapi/fpm/fpm/fpm_events.c index 66ff393e2..8ae9ad2e2 100644 --- a/sapi/fpm/fpm/fpm_events.c +++ b/sapi/fpm/fpm/fpm_events.c @@ -21,6 +21,7 @@ #include "fpm_children.h" #include "zlog.h" #include "fpm_clock.h" +#include "fpm_log.h" #define fpm_event_set_timeout(ev, now) timeradd(&(now), &(ev)->frequency, &(ev)->timeout); @@ -55,8 +56,8 @@ static void fpm_event_cleanup(int which, void *arg) /* {{{ */ static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg) /* {{{ */ { char c; - int res; - int fd = ev->fd;; + int res, ret; + int fd = ev->fd; do { do { @@ -93,10 +94,19 @@ static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg) /* {{ case '1' : /* SIGUSR1 */ zlog(ZLOG_DEBUG, "received SIGUSR1"); if (0 == fpm_stdio_open_error_log(1)) { - zlog(ZLOG_NOTICE, "log file re-opened"); + zlog(ZLOG_NOTICE, "error log file re-opened"); } else { - zlog(ZLOG_ERROR, "unable to re-opened log file"); + zlog(ZLOG_ERROR, "unable to re-opened error log file"); } + + ret = fpm_log_open(1); + if (ret == 0) { + zlog(ZLOG_NOTICE, "access log file re-opened"); + } else if (ret == -1) { + zlog(ZLOG_ERROR, "unable to re-opened access log file"); + } + /* else no access log are set */ + break; case '2' : /* SIGUSR2 */ zlog(ZLOG_DEBUG, "received SIGUSR2"); @@ -235,7 +245,7 @@ int fpm_event_init_main() /* {{{ */ } /* }}} */ -void fpm_event_loop() /* {{{ */ +void fpm_event_loop(int err) /* {{{ */ { static struct fpm_event_s signal_fd_event; @@ -249,9 +259,13 @@ void fpm_event_loop() /* {{{ */ /* add timers */ fpm_pctl_heartbeat(NULL, 0, NULL); - fpm_pctl_perform_idle_server_maintenance_heartbeat(NULL, 0, NULL); - zlog(ZLOG_NOTICE, "ready to handle connections"); + if (!err) { + fpm_pctl_perform_idle_server_maintenance_heartbeat(NULL, 0, NULL); + + zlog(ZLOG_DEBUG, "%zu bytes have been reserved in SHM", fpm_shm_get_size_allocated()); + zlog(ZLOG_NOTICE, "ready to handle connections"); + } while (1) { struct fpm_event_queue_s *q, *q2; diff --git a/sapi/fpm/fpm/fpm_events.h b/sapi/fpm/fpm/fpm_events.h index bec13ba5e..586b24283 100644 --- a/sapi/fpm/fpm/fpm_events.h +++ b/sapi/fpm/fpm/fpm_events.h @@ -22,7 +22,7 @@ struct fpm_event_s { short which; /* type of event */ }; -void fpm_event_loop(); +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); diff --git a/sapi/fpm/fpm/fpm_log.c b/sapi/fpm/fpm/fpm_log.c new file mode 100644 index 000000000..ef1c0c3be --- /dev/null +++ b/sapi/fpm/fpm/fpm_log.c @@ -0,0 +1,494 @@ + + /* $Id: fpm_status.c 312262 2011-06-18 17:41:56Z felipe $ */ + /* (c) 2009 Jerome Loyet */ + +#include "php.h" +#include "SAPI.h" +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> + +#ifdef HAVE_TIMES +#include <sys/times.h> +#endif + +#include "fpm_config.h" +#include "fpm_log.h" +#include "fpm_clock.h" +#include "fpm_process_ctl.h" +#include "fpm_signals.h" +#include "fpm_scoreboard.h" +#include "fastcgi.h" +#include "zlog.h" + +#ifdef MAX_LINE_LENGTH +# define FPM_LOG_BUFFER MAX_LINE_LENGTH +#else +# define FPM_LOG_BUFFER 1024 +#endif + +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) /* {{{ */ +{ + struct fpm_worker_pool_s *wp; + int ret = 1; + + int fd; + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { + if (!wp->config->access_log) { + continue; + } + ret = 0; + + 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); + return -1; + } + + if (reopen) { + dup2(fd, wp->log_fd); + close(fd); + fd = wp->log_fd; + fpm_pctl_kill_all(SIGQUIT); + } else { + wp->log_fd = fd; + } + + fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); + } + + return ret; +} +/* }}} */ + +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) /* {{{ */ +{ + if (!wp || !wp->config) { + return -1; + } + + if (wp->config->access_log && *wp->config->access_log) { + if (wp->config->access_format) { + fpm_log_format = strdup(wp->config->access_format); + } + } + + if (fpm_log_fd == -1) { + fpm_log_fd = wp->log_fd; + } + + + for (wp = fpm_worker_all_pools; wp; wp = wp->next) { + if (wp->log_fd > -1 && wp->log_fd != fpm_log_fd) { + close(wp->log_fd); + wp->log_fd = -1; + } + } + + return 0; +} +/* }}} */ + +int fpm_log_write(char *log_format TSRMLS_DC) /* {{{ */ +{ + char *s, *b; + char buffer[FPM_LOG_BUFFER]; + int token, test; + 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; +#ifdef HAVE_TIMES + clock_t tms_total; +#endif + + if (!log_format && (!fpm_log_format || fpm_log_fd == -1)) { + return -1; + } + + if (!log_format) { + log_format = fpm_log_format; + test = 0; + } else { + 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"); + 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); + return -1; + } + proc = *proc_p; + fpm_scoreboard_proc_release(proc_p); + + timersub(&now, &proc.accepted, &uptime); + } + + token = 0; + + memset(buffer, '\0', sizeof(buffer)); + b = buffer; + len = 0; + + + s = log_format; + + 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); + len = FPM_LOG_BUFFER - 1; + break; + } + + if (!token && *s == '%') { + token = 1; + memset(format, '\0', sizeof(format)); /* reset format */ + s++; + continue; + } + + if (token) { + token = 0; + len2 = 0; + switch (*s) { + + case '%': /* '%' */ + *b = '%'; + len2 = 1; + break; + +#ifdef HAVE_TIMES + 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) + ; + } + } 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); + } + } 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); + } + } else { + zlog(ZLOG_WARNING, "only 'total', 'user' or 'system' are allowed as a modifier for %%%c ('%s')", *s, format); + return -1; + } + + 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.); + } + break; +#endif + + case 'd': /* duration µs */ + /* 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.); + } + + /* 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.); + } + + /* 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); + } + + } else { + zlog(ZLOG_WARNING, "only 'seconds', 'mili', 'miliseconds', 'micro' or 'microseconds' are allowed as a modifier for %%%c ('%s')", *s, format); + return -1; + } + format[0] = '\0'; + break; + + case 'e': /* fastcgi env */ + if (format[0] == '\0') { + zlog(ZLOG_WARNING, "the name of the environment variable must be set between embraces for %%%c", *s); + return -1; + } + + if (!test) { + char *env = fcgi_getenv((fcgi_request*) SG(server_context), format, strlen(format)); + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", env ? env : "-"); + } + format[0] = '\0'; + break; + + case 'f': /* script */ + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.script_filename && *proc.script_filename ? proc.script_filename : "-"); + } + break; + + case 'l': /* content length */ + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", proc.content_length); + } + break; + + case 'm': /* method */ + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.request_method && *proc.request_method ? proc.request_method : "-"); + } + break; + + case 'M': /* memory */ + /* seconds */ + if (format[0] == '\0' || !strcasecmp(format, "bytes")) { + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%zu", proc.memory); + } + + /* kilobytes */ + } else if (!strcasecmp(format, "kilobytes") || !strcasecmp(format, "kilo")) { + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", proc.memory / 1024); + } + + /* megabytes */ + } else if (!strcasecmp(format, "megabytes") || !strcasecmp(format, "mega")) { + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%lu", proc.memory / 1024 / 1024); + } + + } else { + zlog(ZLOG_WARNING, "only 'bytes', 'kilo', 'kilobytes', 'mega' or 'megabytes' are allowed as a modifier for %%%c ('%s')", *s, format); + return -1; + } + format[0] = '\0'; + break; + + case 'n': /* pool name */ + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", scoreboard->pool[0] ? scoreboard->pool : "-"); + } + break; + + case 'o': /* header output */ + if (format[0] == '\0') { + zlog(ZLOG_WARNING, "the name of the header must be set between embraces for %%%c", *s); + return -1; + } + if (!test) { + sapi_header_struct *h; + zend_llist_position pos; + sapi_headers_struct *sapi_headers = &SG(sapi_headers); + size_t format_len = strlen(format); + + h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos); + while (h) { + char *header; + if (!h->header_len) { + h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); + continue; + } + if (!strstr(h->header, format)) { + h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); + continue; + } + + /* test if enought char after the header name + ': ' */ + if (h->header_len <= format_len + 2) { + h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); + continue; + } + + if (h->header[format_len] != ':' || h->header[format_len + 1] != ' ') { + h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); + continue; + } + + header = h->header + format_len + 2; + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", header && *header ? header : "-"); + + /* found, done */ + break; + } + if (!len2) { + len2 = 1; + *b = '-'; + } + } + format[0] = '\0'; + break; + + case 'p': /* PID */ + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%ld", (long)getpid()); + } + break; + + case 'P': /* PID */ + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%ld", (long)getppid()); + } + break; + + case 'q': /* query_string */ + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.query_string ? proc.query_string : ""); + } + break; + + case 'Q': /* '?' */ + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.query_string && *proc.query_string ? "?" : ""); + } + break; + + case 'r': /* request URI */ + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.request_uri ? proc.request_uri : "-"); + } + break; + + case 'R': /* remote IP address */ + if (!test) { + char *tmp = fcgi_get_last_client_ip(); + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", tmp ? tmp : "-"); + } + break; + + case 's': /* status */ + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%d", SG(sapi_headers).http_response_code); + } + break; + + case 'T': + case 't': /* time */ + if (!test) { + time_t *t; + if (*s == 't') { + t = &proc.accepted_epoch; + } else { + t = &now_epoch; + } + if (format[0] == '\0') { + strftime(tmp, sizeof(tmp) - 1, "%d/%b/%Y:%H:%M:%S %z", localtime(t)); + } else { + strftime(tmp, sizeof(tmp) - 1, format, localtime(t)); + } + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", tmp); + } + format[0] = '\0'; + break; + + case 'u': /* remote user */ + if (!test) { + len2 = snprintf(b, FPM_LOG_BUFFER - len, "%s", proc.auth_user ? proc.auth_user : "-"); + } + break; + + case '{': /* complex var */ + token = 1; + { + char *start; + size_t l; + + start = ++s; + + while (*s != '\0') { + if (*s == '}') { + l = s - start; + + if (l >= sizeof(format) - 1) { + l = sizeof(format) - 1; + } + + memcpy(format, start, l); + format[l] = '\0'; + break; + } + s++; + } + if (s[1] == '\0') { + zlog(ZLOG_WARNING, "missing closing embrace in the access.format"); + return -1; + } + } + break; + + default: + zlog(ZLOG_WARNING, "Invalid token in the access.format (%%%c)", *s); + return -1; + } + + if (*s != '}' && format[0] != '\0') { + zlog(ZLOG_WARNING, "embrace is not allowed for modifier %%%c", *s); + return -1; + } + s++; + if (!test) { + b += len2; + len += len2; + } + continue; + } + + if (!test) { + // push the normal char to the output buffer + *b = *s; + b++; + len++; + } + s++; + } + + if (!test && strlen(buffer) > 0) { + buffer[len] = '\n'; + write(fpm_log_fd, buffer, len + 1); + } + + return 0; +} +/* }}} */ diff --git a/sapi/fpm/fpm/fpm_log.h b/sapi/fpm/fpm/fpm_log.h new file mode 100644 index 000000000..74f842646 --- /dev/null +++ b/sapi/fpm/fpm/fpm_log.h @@ -0,0 +1,14 @@ + + /* $Id: fpm_status.h 312263 2011-06-18 17:46:16Z felipe $ */ + /* (c) 2009 Jerome Loyet */ + +#ifndef FPM_LOG_H +#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); + +#endif diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index 13d21ecc3..c2db60f11 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -99,16 +99,13 @@ int __riscosify_control = __RISCOSIFY_STRICT_UNIX_SPECS; #include "fastcgi.h" -#ifdef FPM_AUTOCONFIG_H -#include <fpm_autoconfig.h> -#else #include <php_config.h> -#endif #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> #ifndef PHP_WIN32 /* XXX this will need to change later when threaded fastcgi is implemented. shane */ @@ -154,6 +151,7 @@ static const opt_struct OPTIONS[] = { {'y', 1, "fpm-config"}, {'t', 0, "test"}, {'p', 1, "prefix"}, + {'g', 1, "pid"}, {'-', 0, NULL} /* end of args */ }; @@ -420,8 +418,8 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) } else { h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos); while (h) { - if (h->header_len > sizeof("Status:")-1 && - strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0 + if (h->header_len > sizeof("Status:") - 1 && + strncasecmp(h->header, "Status:", sizeof("Status:") - 1) == 0 ) { has_status = 1; break; @@ -456,16 +454,16 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) while (h) { /* prevent CRLFCRLF */ if (h->header_len) { - if (h->header_len > sizeof("Status:")-1 && - strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0 + if (h->header_len > sizeof("Status:") - 1 && + strncasecmp(h->header, "Status:", sizeof("Status:") - 1) == 0 ) { if (!ignore_status) { ignore_status = 1; PHPWRITE_H(h->header, h->header_len); PHPWRITE_H("\r\n", 2); } - } else if (response_status == 304 && h->header_len > sizeof("Content-Type:")-1 && - strncasecmp(h->header, "Content-Type:", sizeof("Content-Type:")-1) == 0 + } else if (response_status == 304 && h->header_len > sizeof("Content-Type:") - 1 && + strncasecmp(h->header, "Content-Type:", sizeof("Content-Type:") - 1) == 0 ) { h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos); continue; @@ -496,7 +494,7 @@ static int sapi_cgi_read_post(char *buffer, uint count_bytes TSRMLS_DC) 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); + sizeof("REQUEST_BODY_FILE") - 1 TSRMLS_CC); if (request_body_filename && *request_body_filename) { request_body_fd = open(request_body_filename, O_RDONLY); @@ -603,7 +601,7 @@ static char *_sapi_cgibin_putenv(char *name, char *value TSRMLS_DC) static char *sapi_cgi_read_cookies(TSRMLS_D) { - return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE")-1 TSRMLS_CC); + return sapi_cgibin_getenv((char *) "HTTP_COOKIE", sizeof("HTTP_COOKIE") - 1 TSRMLS_CC); } void cgi_php_import_environment_variables(zval *array_ptr TSRMLS_DC) @@ -672,12 +670,13 @@ static void sapi_cgi_register_variables(zval *track_vars_array TSRMLS_DC) if (CGIG(fix_pathinfo)) { char *script_name = SG(request_info).request_uri; unsigned int script_name_len = script_name ? strlen(script_name) : 0; - char *path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC); + char *path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO") - 1 TSRMLS_CC); unsigned int path_info_len = path_info ? strlen(path_info) : 0; php_self_len = script_name_len + path_info_len; php_self = emalloc(php_self_len + 1); + /* Concat script_name and path_info into php_self */ if (script_name) { memcpy(php_self, script_name, script_name_len + 1); } @@ -960,7 +959,7 @@ static void php_cgi_usage(char *argv0) prog = "php"; } - php_printf( "Usage: %s [-n] [-e] [-h] [-i] [-m] [-v] [-t] [-p <prefix> ] [-c <file>] [-d foo[=bar]] [-y <file>]\n" + php_printf( "Usage: %s [-n] [-e] [-h] [-i] [-m] [-v] [-t] [-p <prefix>] [-g <pid>] [-c <file>] [-d foo[=bar]] [-y <file>]\n" " -c <path>|<file> Look for php.ini file in this directory\n" " -n No php.ini file will be used\n" " -d foo[=bar] Define INI entry foo with value 'bar'\n" @@ -971,6 +970,8 @@ static void php_cgi_usage(char *argv0) " -v Version number\n" " -p, --prefix <dir>\n" " Specify alternative prefix path to FastCGI process manager (default: %s).\n" + " -g, --pid <file>\n" + " Specify the PID file location.\n" " -y, --fpm-config <file>\n" " Specify alternative path to FastCGI process manager config file.\n" " -t, --test Test FPM configuration and exit\n", @@ -1081,8 +1082,8 @@ static int is_valid_path(const char *path) */ static void init_request_info(TSRMLS_D) { - char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME")-1 TSRMLS_CC); - char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED")-1 TSRMLS_CC); + char *env_script_filename = sapi_cgibin_getenv("SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME") - 1 TSRMLS_CC); + char *env_path_translated = sapi_cgibin_getenv("PATH_TRANSLATED", sizeof("PATH_TRANSLATED") - 1 TSRMLS_CC); char *script_path_translated = env_script_filename; char *ini; int apache_was_here = 0; @@ -1110,17 +1111,17 @@ static void init_request_info(TSRMLS_D) * of the script will be retreived later via argc/argv */ if (script_path_translated) { const char *auth; - char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH", sizeof("CONTENT_LENGTH")-1 TSRMLS_CC); - char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE")-1 TSRMLS_CC); - char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO")-1 TSRMLS_CC); - char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME")-1 TSRMLS_CC); + char *content_length = sapi_cgibin_getenv("CONTENT_LENGTH", sizeof("CONTENT_LENGTH") - 1 TSRMLS_CC); + char *content_type = sapi_cgibin_getenv("CONTENT_TYPE", sizeof("CONTENT_TYPE") - 1 TSRMLS_CC); + char *env_path_info = sapi_cgibin_getenv("PATH_INFO", sizeof("PATH_INFO") - 1 TSRMLS_CC); + char *env_script_name = sapi_cgibin_getenv("SCRIPT_NAME", sizeof("SCRIPT_NAME") - 1 TSRMLS_CC); /* Hack for buggy IIS that sets incorrect PATH_INFO */ - char *env_server_software = sapi_cgibin_getenv("SERVER_SOFTWARE", sizeof("SERVER_SOFTWARE")-1 TSRMLS_CC); + char *env_server_software = sapi_cgibin_getenv("SERVER_SOFTWARE", sizeof("SERVER_SOFTWARE") - 1 TSRMLS_CC); if (env_server_software && env_script_name && env_path_info && - strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS")-1) == 0 && + strncmp(env_server_software, "Microsoft-IIS", sizeof("Microsoft-IIS") - 1) == 0 && strncmp(env_path_info, env_script_name, strlen(env_script_name)) == 0 ) { env_path_info = _sapi_cgibin_putenv("ORIG_PATH_INFO", env_path_info TSRMLS_CC); @@ -1158,8 +1159,8 @@ static void init_request_info(TSRMLS_D) if (CGIG(fix_pathinfo)) { struct stat st; char *real_path = NULL; - char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL")-1 TSRMLS_CC); - char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC); + char *env_redirect_url = sapi_cgibin_getenv("REDIRECT_URL", sizeof("REDIRECT_URL") - 1 TSRMLS_CC); + char *env_document_root = sapi_cgibin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT") - 1 TSRMLS_CC); char *orig_path_translated = env_path_translated; char *orig_path_info = env_path_info; char *orig_script_name = env_script_name; @@ -1394,19 +1395,19 @@ static void init_request_info(TSRMLS_D) SG(request_info).path_translated = estrdup(script_path_translated); } - SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD")-1 TSRMLS_CC); + SG(request_info).request_method = sapi_cgibin_getenv("REQUEST_METHOD", sizeof("REQUEST_METHOD") - 1 TSRMLS_CC); /* 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).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); /* The CGI RFC allows servers to pass on unvalidated Authorization data */ - auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION")-1 TSRMLS_CC); + auth = sapi_cgibin_getenv("HTTP_AUTHORIZATION", sizeof("HTTP_AUTHORIZATION") - 1 TSRMLS_CC); php_handle_auth_data(auth TSRMLS_CC); } /* INI stuff */ - ini = sapi_cgibin_getenv("PHP_VALUE", sizeof("PHP_VALUE")-1 TSRMLS_CC); + ini = sapi_cgibin_getenv("PHP_VALUE", sizeof("PHP_VALUE") - 1 TSRMLS_CC); if (ini) { int mode = ZEND_INI_USER; char *tmp; @@ -1415,7 +1416,7 @@ static void init_request_info(TSRMLS_D) efree(tmp); } - ini = sapi_cgibin_getenv("PHP_ADMIN_VALUE", sizeof("PHP_ADMIN_VALUE")-1 TSRMLS_CC); + ini = sapi_cgibin_getenv("PHP_ADMIN_VALUE", sizeof("PHP_ADMIN_VALUE") - 1 TSRMLS_CC); if (ini) { int mode = ZEND_INI_SYSTEM; char *tmp; @@ -1429,22 +1430,28 @@ static void init_request_info(TSRMLS_D) static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg TSRMLS_DC) /* {{{ */ { int *mode = (int *)arg; - char *key = Z_STRVAL_P(arg1); - char *value = Z_STRVAL_P(arg2); + char *key; + char *value = NULL; struct key_value_s kv; - if (!mode) return; + if (!mode || !arg1) return; if (callback_type != ZEND_INI_PARSER_ENTRY) { fprintf(stderr, "Passing INI directive through FastCGI: only classic entries are allowed\n"); return; } + key = Z_STRVAL_P(arg1); + if (!key || strlen(key) < 1) { fprintf(stderr, "Passing INI directive through FastCGI: empty key\n"); return; } + if (arg2) { + value = Z_STRVAL_P(arg2); + } + if (!value) { fprintf(stderr, "Passing INI directive through FastCGI: empty value for key '%s'\n", key); return; @@ -1566,7 +1573,6 @@ static zend_module_entry cgi_module_entry = { */ int main(int argc, char *argv[]) { - int free_query_string = 0; int exit_status = SUCCESS; int cgi = 0, c; zend_file_handle file_handle; @@ -1587,6 +1593,7 @@ int main(int argc, char *argv[]) fcgi_request request; char *fpm_config = NULL; char *fpm_prefix = NULL; + char *fpm_pid = NULL; int test_conf = 0; fcgi_init(); @@ -1670,6 +1677,10 @@ int main(int argc, char *argv[]) fpm_prefix = php_optarg; break; + case 'g': + fpm_pid = php_optarg; + break; + case 'e': /* enable extended info output */ CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO; break; @@ -1815,7 +1826,7 @@ consult the installation file that came with this distribution, or visit \n\ } } - if (0 > fpm_init(argc, argv, fpm_config ? fpm_config : CGIG(fpm_config), fpm_prefix, test_conf)) { + if (0 > fpm_init(argc, argv, fpm_config ? fpm_config : CGIG(fpm_config), fpm_prefix, fpm_pid, test_conf)) { return FAILURE; } @@ -1832,7 +1843,6 @@ consult the installation file that came with this distribution, or visit \n\ zend_first_try { while (fcgi_accept_request(&request) >= 0) { - char *status_buffer, *status_content_type; request_body_fd = -1; SG(server_context) = (void *) &request; init_request_info(TSRMLS_C); @@ -1855,32 +1865,7 @@ consult the installation file that came with this distribution, or visit \n\ goto fastcgi_request_done; } - if (!strcasecmp(SG(request_info).request_method, "GET") && fpm_status_handle_status(SG(request_info).request_uri, SG(request_info).query_string, &status_buffer, &status_content_type)) { - if (status_buffer) { - if (status_content_type) { - sapi_add_header_ex(status_content_type, strlen(status_content_type), 1, 1 TSRMLS_CC); - } else { - sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC); - } - - SG(sapi_headers).http_response_code = 200; - PUTS(status_buffer); - efree(status_buffer); - if (status_content_type) { - efree(status_content_type); - } - } else { - sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC); - SG(sapi_headers).http_response_code = 500; - PUTS("Unable to retrieve status\n"); - } - goto fastcgi_request_done; - } - - if (!strcasecmp(SG(request_info).request_method, "GET") && (status_buffer = fpm_status_handle_ping(SG(request_info).request_uri))) { - sapi_add_header_ex(ZEND_STRL("Content-Type: text/plain"), 1, 1 TSRMLS_CC); - SG(sapi_headers).http_response_code = 200; - PUTS(status_buffer); + if (fpm_status_handle_request(TSRMLS_C)) { goto fastcgi_request_done; } @@ -1932,6 +1917,9 @@ fastcgi_request_done: } } + fpm_request_end(TSRMLS_C); + fpm_log_write(NULL TSRMLS_CC); + STR_FREE(SG(request_info).path_translated); SG(request_info).path_translated = NULL; @@ -1941,11 +1929,6 @@ fastcgi_request_done: exit_status = EG(exit_status); } - if (free_query_string && SG(request_info).query_string) { - free(SG(request_info).query_string); - SG(request_info).query_string = NULL; - } - requests++; if (max_requests && (requests == max_requests)) { fcgi_finish_request(&request, 1); diff --git a/sapi/fpm/fpm/fpm_php.c b/sapi/fpm/fpm/fpm_php.c index 384682b7e..33b9e410e 100644 --- a/sapi/fpm/fpm/fpm_php.c +++ b/sapi/fpm/fpm/fpm_php.c @@ -172,6 +172,18 @@ char *fpm_php_request_method(TSRMLS_D) /* {{{ */ } /* }}} */ +char *fpm_php_query_string(TSRMLS_D) /* {{{ */ +{ + return SG(request_info).query_string; +} +/* }}} */ + +char *fpm_php_auth_user(TSRMLS_D) /* {{{ */ +{ + return SG(request_info).auth_user; +} +/* }}} */ + size_t fpm_php_content_length(TSRMLS_D) /* {{{ */ { return SG(request_info).content_length; diff --git a/sapi/fpm/fpm/fpm_php.h b/sapi/fpm/fpm/fpm_php.h index 891e83bfc..62a47e7fd 100644 --- a/sapi/fpm/fpm/fpm_php.h +++ b/sapi/fpm/fpm/fpm_php.h @@ -37,6 +37,8 @@ int fpm_php_init_child(struct fpm_worker_pool_s *wp); char *fpm_php_script_filename(TSRMLS_D); char *fpm_php_request_uri(TSRMLS_D); char *fpm_php_request_method(TSRMLS_D); +char *fpm_php_query_string(TSRMLS_D); +char *fpm_php_auth_user(TSRMLS_D); size_t fpm_php_content_length(TSRMLS_D); void fpm_php_soft_quit(); int fpm_php_init_main(); diff --git a/sapi/fpm/fpm/fpm_process_ctl.c b/sapi/fpm/fpm/fpm_process_ctl.c index badda1408..0f2685c73 100644 --- a/sapi/fpm/fpm/fpm_process_ctl.c +++ b/sapi/fpm/fpm/fpm_process_ctl.c @@ -18,7 +18,7 @@ #include "fpm_cleanup.h" #include "fpm_request.h" #include "fpm_worker_pool.h" -#include "fpm_status.h" +#include "fpm_scoreboard.h" #include "fpm_sockets.h" #include "zlog.h" @@ -143,7 +143,7 @@ int fpm_pctl_kill(pid_t pid, int how) /* {{{ */ } /* }}} */ -static void fpm_pctl_kill_all(int signo) /* {{{ */ +void fpm_pctl_kill_all(int signo) /* {{{ */ { struct fpm_worker_pool_s *wp; int alive_children = 0; @@ -337,10 +337,24 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ } /* update status structure for all PMs */ - if (0 > fpm_socket_get_listening_queue(wp, &cur_lq, NULL)) { - cur_lq = 0; + if (wp->listen_address_domain == FPM_AF_INET) { + if (0 > fpm_socket_get_listening_queue(wp->listening_socket, &cur_lq, NULL)) { + cur_lq = 0; +#if 0 + } else { + if (cur_lq > 0) { + if (!wp->warn_lq) { + zlog(ZLOG_WARNING, "[pool %s] listening queue is not empty, #%d requests are waiting to be served, consider raising pm.max_children setting (%d)", wp->config->name, cur_lq, wp->config->pm_max_children); + wp->warn_lq = 1; + } + } else { + wp->warn_lq = 0; + } +#endif + } + fpm_scoreboard_update(idle, active, cur_lq, -1, -1, -1, FPM_SCOREBOARD_ACTION_SET, wp->scoreboard); } - fpm_status_update_activity(wp->shm_status, idle, active, idle + active, cur_lq, wp->listening_queue_len, 0); + /* the rest is only used by PM_STYLE_DYNAMIC */ if (wp->config->pm != PM_STYLE_DYNAMIC) continue; @@ -357,8 +371,8 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ if (idle < wp->config->pm_min_spare_servers) { if (wp->running_children >= wp->config->pm_max_children) { if (!wp->warn_max_children) { - fpm_status_increment_max_children_reached(wp->shm_status); - zlog(ZLOG_WARNING, "[pool %s] server reached max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children); + fpm_scoreboard_update(0, 0, 0, 0, 0, 1, FPM_SCOREBOARD_ACTION_INC, wp->scoreboard); + zlog(ZLOG_WARNING, "[pool %s] server reached pm.max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children); wp->warn_max_children = 1; } wp->idle_spawn_rate = 1; @@ -366,7 +380,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ } if (wp->idle_spawn_rate >= 8) { - zlog(ZLOG_WARNING, "[pool %s] seems busy (you may need to increase start_servers, or min/max_spare_servers), spawning %d children, there are %d idle, and %d total children", wp->config->name, wp->idle_spawn_rate, idle, wp->running_children); + zlog(ZLOG_WARNING, "[pool %s] seems busy (you may need to increase pm.start_servers, or pm.min/max_spare_servers), spawning %d children, there are %d idle, and %d total children", wp->config->name, wp->idle_spawn_rate, idle, wp->running_children); } /* compute the number of idle process to spawn */ @@ -376,8 +390,8 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ children_to_fork = MIN(children_to_fork, wp->config->pm_max_children - wp->running_children); if (children_to_fork <= 0) { if (!wp->warn_max_children) { - fpm_status_increment_max_children_reached(wp->shm_status); - zlog(ZLOG_WARNING, "[pool %s] server reached max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children); + fpm_scoreboard_update(0, 0, 0, 0, 0, 1, FPM_SCOREBOARD_ACTION_INC, wp->scoreboard); + zlog(ZLOG_WARNING, "[pool %s] server reached pm.max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_max_children); wp->warn_max_children = 1; } wp->idle_spawn_rate = 1; diff --git a/sapi/fpm/fpm/fpm_process_ctl.h b/sapi/fpm/fpm/fpm_process_ctl.h index 36577097c..6bfcfd8c6 100644 --- a/sapi/fpm/fpm/fpm_process_ctl.h +++ b/sapi/fpm/fpm/fpm_process_ctl.h @@ -19,6 +19,7 @@ struct fpm_child_s; void fpm_pctl(int new_state, int action); int fpm_pctl_can_spawn_children(); 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); int fpm_pctl_child_exited(); diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c index 6ba9e5170..e0d1815db 100644 --- a/sapi/fpm/fpm/fpm_request.c +++ b/sapi/fpm/fpm/fpm_request.c @@ -1,6 +1,9 @@ /* $Id: fpm_request.c,v 1.9.2.1 2008/11/15 00:57:24 anight Exp $ */ /* (c) 2007,2008 Andrei Nigmatulin */ +#ifdef HAVE_TIMES +#include <sys/times.h> +#endif #include "fpm_config.h" @@ -13,147 +16,247 @@ #include "fpm_php_trace.h" #include "fpm_process_ctl.h" #include "fpm_children.h" -#include "fpm_shm_slots.h" +#include "fpm_scoreboard.h" #include "fpm_status.h" #include "fpm_request.h" +#include "fpm_log.h" #include "zlog.h" void fpm_request_accepting() /* {{{ */ { - struct fpm_shm_slot_s *slot; - - slot = fpm_shm_slots_acquire(0, 0); - slot->request_stage = FPM_REQUEST_ACCEPTING; - fpm_clock_get(&slot->tv); - memset(slot->request_uri, 0, sizeof(slot->request_uri)); - memset(slot->request_method, 0, sizeof(slot->request_method)); - slot->content_length = 0; - memset(slot->script_filename, 0, sizeof(slot->script_filename)); - fpm_shm_slots_release(slot); + struct fpm_scoreboard_proc_s *proc; + struct timeval now; + + fpm_clock_get(&now); + + proc = fpm_scoreboard_proc_acquire(NULL, -1, 0); + if (proc == NULL) { + zlog(ZLOG_WARNING, "unable 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-- */ + fpm_scoreboard_update(1, -1, 0, 0, 0, 0, FPM_SCOREBOARD_ACTION_INC, NULL); } /* }}} */ void fpm_request_reading_headers() /* {{{ */ { - struct fpm_shm_slot_s *slot; + struct fpm_scoreboard_proc_s *proc; + + struct timeval now; + clock_t now_epoch; +#ifdef HAVE_TIMES + struct tms cpu; +#endif + + fpm_clock_get(&now); + now_epoch = time(NULL); +#ifdef HAVE_TIMES + times(&cpu); +#endif - slot = fpm_shm_slots_acquire(0, 0); - slot->request_stage = FPM_REQUEST_READING_HEADERS; - fpm_clock_get(&slot->tv); - slot->accepted = slot->tv; - fpm_shm_slots_release(slot); + proc = fpm_scoreboard_proc_acquire(NULL, -1, 0); + if (proc == NULL) { + zlog(ZLOG_WARNING, "unable to acquire proc scoreboard"); + return; + } + + proc->request_stage = FPM_REQUEST_READING_HEADERS; + proc->tv = now; + proc->accepted = now; + proc->accepted_epoch = now_epoch; +#ifdef HAVE_TIMES + proc->cpu_accepted = cpu; +#endif + fpm_scoreboard_proc_release(proc); - fpm_status_increment_accepted_conn(fpm_status_shm); + /* idle--, active++, request++ */ + fpm_scoreboard_update(-1, 1, 0, 0, 1, 0, FPM_SCOREBOARD_ACTION_INC, NULL); } /* }}} */ void fpm_request_info() /* {{{ */ { TSRMLS_FETCH(); - struct fpm_shm_slot_s *slot; + struct fpm_scoreboard_proc_s *proc; char *request_uri = fpm_php_request_uri(TSRMLS_C); char *request_method = fpm_php_request_method(TSRMLS_C); char *script_filename = fpm_php_script_filename(TSRMLS_C); + char *query_string = fpm_php_query_string(TSRMLS_C); + char *auth_user = fpm_php_auth_user(TSRMLS_C); + size_t content_length = fpm_php_content_length(TSRMLS_C); + struct timeval now; - slot = fpm_shm_slots_acquire(0, 0); - slot->request_stage = FPM_REQUEST_INFO; - fpm_clock_get(&slot->tv); + fpm_clock_get(&now); + + proc = fpm_scoreboard_proc_acquire(NULL, -1, 0); + if (proc == NULL) { + zlog(ZLOG_WARNING, "unable to acquire proc scoreboard"); + return; + } + + proc->request_stage = FPM_REQUEST_INFO; + proc->tv = now; if (request_uri) { - strlcpy(slot->request_uri, request_uri, sizeof(slot->request_uri)); + strlcpy(proc->request_uri, request_uri, sizeof(proc->request_uri)); } if (request_method) { - strlcpy(slot->request_method, request_method, sizeof(slot->request_method)); + strlcpy(proc->request_method, request_method, sizeof(proc->request_method)); } - slot->content_length = fpm_php_content_length(TSRMLS_C); + if (query_string) { + strlcpy(proc->query_string, query_string, sizeof(proc->query_string)); + } + + if (auth_user) { + strlcpy(proc->auth_user, auth_user, sizeof(proc->auth_user)); + } + + proc->content_length = content_length; /* if cgi.fix_pathinfo is set to "1" and script cannot be found (404) the sapi_globals.request_info.path_translated is set to NULL */ if (script_filename) { - strlcpy(slot->script_filename, script_filename, sizeof(slot->script_filename)); + strlcpy(proc->script_filename, script_filename, sizeof(proc->script_filename)); } - fpm_shm_slots_release(slot); + fpm_scoreboard_proc_release(proc); } /* }}} */ void fpm_request_executing() /* {{{ */ { - struct fpm_shm_slot_s *slot; + struct fpm_scoreboard_proc_s *proc; + struct timeval now; + + fpm_clock_get(&now); + + proc = fpm_scoreboard_proc_acquire(NULL, -1, 0); + if (proc == NULL) { + zlog(ZLOG_WARNING, "unable to acquire proc scoreboard"); + return; + } - slot = fpm_shm_slots_acquire(0, 0); - slot->request_stage = FPM_REQUEST_EXECUTING; - fpm_clock_get(&slot->tv); - fpm_shm_slots_release(slot); + proc->request_stage = FPM_REQUEST_EXECUTING; + proc->tv = now; + fpm_scoreboard_proc_release(proc); +} +/* }}} */ + +void fpm_request_end(TSRMLS_D) /* {{{ */ +{ + struct fpm_scoreboard_proc_s *proc; + struct timeval now; +#ifdef HAVE_TIMES + struct tms cpu; +#endif + size_t memory = zend_memory_peak_usage(1 TSRMLS_CC); + + fpm_clock_get(&now); +#ifdef HAVE_TIMES + times(&cpu); +#endif + + proc = fpm_scoreboard_proc_acquire(NULL, -1, 0); + if (proc == NULL) { + zlog(ZLOG_WARNING, "unable to acquire proc scoreboard"); + return; + } + proc->request_stage = FPM_REQUEST_FINISHED; + proc->tv = now; +#ifdef HAVE_TIMES + proc->cpu_finished = cpu; + timersub(&proc->tv, &proc->accepted, &proc->cpu_duration); +#endif + proc->memory = memory; + fpm_scoreboard_proc_release(proc); } /* }}} */ void fpm_request_finished() /* {{{ */ { - struct fpm_shm_slot_s *slot; + struct fpm_scoreboard_proc_s *proc; + struct timeval now; - slot = fpm_shm_slots_acquire(0, 0); - slot->request_stage = FPM_REQUEST_FINISHED; - fpm_clock_get(&slot->tv); - memset(&slot->accepted, 0, sizeof(slot->accepted)); - fpm_shm_slots_release(slot); + fpm_clock_get(&now); + + proc = fpm_scoreboard_proc_acquire(NULL, -1, 0); + if (proc == NULL) { + zlog(ZLOG_WARNING, "unable to acquire proc scoreboard"); + return; + } + + proc->request_stage = FPM_REQUEST_FINISHED; + proc->tv = now; + memset(&proc->accepted, 0, sizeof(proc->accepted)); + proc->accepted_epoch = 0; + fpm_scoreboard_proc_release(proc); } /* }}} */ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, int terminate_timeout, int slowlog_timeout) /* {{{ */ { - struct fpm_shm_slot_s *slot; - struct fpm_shm_slot_s slot_c; + struct fpm_scoreboard_proc_s proc, *proc_p; - slot = fpm_shm_slot(child); - if (!fpm_shm_slots_acquire(slot, 1)) { + proc_p = fpm_scoreboard_proc_acquire(child->wp->scoreboard, child->scoreboard_i, 1); + if (!proc_p) { + zlog(ZLOG_WARNING, "unable to acquire scoreboard"); return; } - slot_c = *slot; - fpm_shm_slots_release(slot); + proc = *proc_p; + fpm_scoreboard_proc_release(proc_p); #if HAVE_FPM_TRACE if (child->slow_logged.tv_sec) { - if (child->slow_logged.tv_sec != slot_c.accepted.tv_sec || child->slow_logged.tv_usec != slot_c.accepted.tv_usec) { + if (child->slow_logged.tv_sec != proc.accepted.tv_sec || child->slow_logged.tv_usec != proc.accepted.tv_usec) { child->slow_logged.tv_sec = 0; child->slow_logged.tv_usec = 0; } } #endif - if (slot_c.request_stage > FPM_REQUEST_ACCEPTING && slot_c.request_stage < FPM_REQUEST_FINISHED) { - char purified_script_filename[sizeof(slot_c.script_filename)]; + if (proc.request_stage > FPM_REQUEST_ACCEPTING && proc.request_stage < FPM_REQUEST_END) { + char purified_script_filename[sizeof(proc.script_filename)]; struct timeval tv; - timersub(now, &slot_c.accepted, &tv); + timersub(now, &proc.accepted, &tv); #if HAVE_FPM_TRACE if (child->slow_logged.tv_sec == 0 && slowlog_timeout && - slot_c.request_stage == FPM_REQUEST_EXECUTING && tv.tv_sec >= slowlog_timeout) { + proc.request_stage == FPM_REQUEST_EXECUTING && tv.tv_sec >= slowlog_timeout) { - str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename)); + str_purify_filename(purified_script_filename, proc.script_filename, sizeof(proc.script_filename)); - child->slow_logged = slot_c.accepted; + child->slow_logged = proc.accepted; child->tracer = fpm_php_trace; fpm_trace_signal(child->pid); zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' (request: \"%s %s\") executing too slow (%d.%06d sec), logging", - child->wp->config->name, (int) child->pid, purified_script_filename, slot_c.request_method, slot_c.request_uri, + child->wp->config->name, (int) child->pid, purified_script_filename, proc.request_method, proc.request_uri, (int) tv.tv_sec, (int) tv.tv_usec); } else #endif if (terminate_timeout && tv.tv_sec >= terminate_timeout) { - str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename)); + str_purify_filename(purified_script_filename, proc.script_filename, sizeof(proc.script_filename)); fpm_pctl_kill(child->pid, FPM_PCTL_TERM); zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' (request: \"%s %s\") execution timed out (%d.%06d sec), terminating", - child->wp->config->name, (int) child->pid, purified_script_filename, slot_c.request_method, slot_c.request_uri, + child->wp->config->name, (int) child->pid, purified_script_filename, proc.request_method, proc.request_uri, (int) tv.tv_sec, (int) tv.tv_usec); } } @@ -162,11 +265,14 @@ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now, int fpm_request_is_idle(struct fpm_child_s *child) /* {{{ */ { - struct fpm_shm_slot_s slot; + struct fpm_scoreboard_proc_s *proc; /* no need in atomicity here */ - slot = *fpm_shm_slot(child); + proc = fpm_scoreboard_proc_get(child->wp->scoreboard, child->scoreboard_i); + if (!proc) { + return 0; + } - return slot.request_stage == FPM_REQUEST_ACCEPTING; + return proc->request_stage == FPM_REQUEST_ACCEPTING; } /* }}} */ diff --git a/sapi/fpm/fpm/fpm_request.h b/sapi/fpm/fpm/fpm_request.h index 7bc9bc842..b3014a5f1 100644 --- a/sapi/fpm/fpm/fpm_request.h +++ b/sapi/fpm/fpm/fpm_request.h @@ -9,7 +9,8 @@ void fpm_request_accepting(); /* hanging in accept() */ void fpm_request_reading_headers(); /* start reading fastcgi request from very first byte */ void fpm_request_info(); /* not a stage really but a point in the php code, where all request params have become known to sapi */ void fpm_request_executing(); /* the script is executing */ -void fpm_request_finished(); /* request processed: script response have been sent to web server */ +void fpm_request_end(TSRMLS_D); /* request ended: script response have been sent to web server */ +void fpm_request_finished(); /* request processed: cleaning current request */ struct fpm_child_s; struct timeval; @@ -22,6 +23,7 @@ enum fpm_request_stage_e { FPM_REQUEST_READING_HEADERS, FPM_REQUEST_INFO, FPM_REQUEST_EXECUTING, + FPM_REQUEST_END, FPM_REQUEST_FINISHED }; diff --git a/sapi/fpm/fpm/fpm_scoreboard.c b/sapi/fpm/fpm/fpm_scoreboard.c new file mode 100644 index 000000000..5ff5e5f9f --- /dev/null +++ b/sapi/fpm/fpm/fpm_scoreboard.c @@ -0,0 +1,301 @@ + + /* $Id: fpm_status.c 312399 2011-06-23 08:03:52Z fat $ */ + /* (c) 2009 Jerome Loyet */ + +#include "php.h" +#include "SAPI.h" +#include <stdio.h> +#include <time.h> + +#include "fpm_config.h" +#include "fpm_scoreboard.h" +#include "fpm_shm.h" +#include "fpm_sockets.h" +#include "fpm_worker_pool.h" +#include "fpm_clock.h" +#include "zlog.h" + +static struct fpm_scoreboard_s *fpm_scoreboard = NULL; +static int fpm_scoreboard_i = -1; + +int fpm_scoreboard_init_main() /* {{{ */ +{ + struct fpm_worker_pool_s *wp; + int i; + + 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); + return -1; + } + + if (wp->scoreboard) { + zlog(ZLOG_ERROR, "[pool %s] Unable to create scoreboard SHM because it already exists", wp->config->name); + return -1; + } + + wp->scoreboard = fpm_shm_alloc(sizeof(struct fpm_scoreboard_s) + (wp->config->pm_max_children - 1) * sizeof(struct fpm_scoreboard_proc_s *)); + if (!wp->scoreboard) { + return -1; + } + wp->scoreboard->nprocs = wp->config->pm_max_children; + for (i = 0; i < wp->scoreboard->nprocs; i++) { + wp->scoreboard->procs[i] = fpm_shm_alloc(sizeof(struct fpm_scoreboard_proc_s)); + if (!wp->scoreboard->procs[i]) { + return -1; + } + memset(wp->scoreboard->procs[i], 0, sizeof(struct fpm_scoreboard_proc_s)); + } + + wp->scoreboard->pm = wp->config->pm; + wp->scoreboard->start_epoch = time(NULL); + strlcpy(wp->scoreboard->pool, wp->config->name, sizeof(wp->scoreboard->pool)); + } + return 0; +} +/* }}} */ + +void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int action, struct fpm_scoreboard_s *scoreboard) /* {{{ */ +{ + if (!scoreboard) { + scoreboard = fpm_scoreboard; + } + if (!scoreboard) { + zlog(ZLOG_WARNING, "Unable to update scoreboard: the SHM has not been found"); + return; + } + + + fpm_spinlock(&scoreboard->lock, 0); + if (action == FPM_SCOREBOARD_ACTION_SET) { + if (idle >= 0) { + scoreboard->idle = idle; + } + if (active >= 0) { + scoreboard->active = active; + } + if (lq >= 0) { + scoreboard->lq = lq; + } + if (lq_len >= 0) { + scoreboard->lq_len = lq_len; + } +#ifdef HAVE_FPM_LQ /* prevent unnecessary test */ + if (scoreboard->lq > scoreboard->lq_max) { + scoreboard->lq_max = scoreboard->lq; + } +#endif + if (requests >= 0) { + scoreboard->requests = requests; + } + + if (max_children_reached >= 0) { + scoreboard->max_children_reached = max_children_reached; + } + } else { + if (scoreboard->idle + idle > 0) { + scoreboard->idle += idle; + } else { + scoreboard->idle = 0; + } + + if (scoreboard->active + active > 0) { + scoreboard->active += active; + } else { + scoreboard->active = 0; + } + + if (scoreboard->requests + requests > 0) { + scoreboard->requests += requests; + } else { + scoreboard->requests = 0; + } + + if (scoreboard->max_children_reached + max_children_reached > 0) { + scoreboard->max_children_reached += max_children_reached; + } else { + scoreboard->max_children_reached = 0; + } + } + + if (scoreboard->active > scoreboard->active_max) { + scoreboard->active_max = scoreboard->active; + } + + fpm_unlock(scoreboard->lock); +} +/* }}} */ + +struct fpm_scoreboard_s *fpm_scoreboard_get() /* {{{*/ +{ + return fpm_scoreboard; +} +/* }}} */ + +struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{*/ +{ + if (!scoreboard) { + scoreboard = fpm_scoreboard; + } + + if (!scoreboard) { + return NULL; + } + + if (child_index < 0) { + child_index = fpm_scoreboard_i; + } + + if (child_index < 0 || child_index >= scoreboard->nprocs) { + return NULL; + } + + return scoreboard->procs[child_index]; +} +/* }}} */ + +struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang) /* {{{ */ +{ + struct fpm_scoreboard_s *s; + + s = scoreboard ? scoreboard : fpm_scoreboard; + if (!s) { + return NULL; + } + + if (!fpm_spinlock(&s->lock, nohang)) { + return NULL; + } + return s; +} +/* }}} */ + +void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard) { + if (!scoreboard) { + return; + } + + scoreboard->lock = 0; +} + +struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang) /* {{{ */ +{ + struct fpm_scoreboard_proc_s *proc; + + proc = fpm_scoreboard_proc_get(scoreboard, child_index); + if (!proc) { + return NULL; + } + + if (!fpm_spinlock(&proc->lock, nohang)) { + return NULL; + } + + return proc; +} +/* }}} */ + +void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc) /* {{{ */ +{ + if (!proc) { + return; + } + + proc->lock = 0; +} + +void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard) /* {{{ */ +{ + int i; + + if (!scoreboard) { + zlog(ZLOG_ERROR, "**scoreboard is NULL"); + return; + } + + for (i = 0; i < scoreboard->nprocs; i++) { + if (!scoreboard->procs[i]) { + continue; + } + fpm_shm_free(scoreboard->procs[i], sizeof(struct fpm_scoreboard_proc_s)); + } + fpm_shm_free(scoreboard, sizeof(struct fpm_scoreboard_s)); +} +/* }}} */ + +void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_index, pid_t pid) /* {{{ */ +{ + struct fpm_scoreboard_proc_s *proc; + fpm_scoreboard = scoreboard; + fpm_scoreboard_i = child_index; + proc = fpm_scoreboard_proc_get(scoreboard, child_index); + if (!proc) { + return; + } + proc->pid = pid; +} +/* }}} */ + +void fpm_scoreboard_proc_free(struct fpm_scoreboard_s *scoreboard, int child_index) /* {{{ */ +{ + if (!scoreboard) { + return; + } + + if (child_index < 0 || child_index >= scoreboard->nprocs) { + return; + } + + if (scoreboard->procs[child_index] && scoreboard->procs[child_index]->used > 0) { + memset(scoreboard->procs[child_index], 0, sizeof(struct fpm_scoreboard_proc_s)); + } + + /* set this slot as free to avoid search on next alloc */ + scoreboard->free_proc = child_index; +} +/* }}} */ + +int fpm_scoreboard_proc_alloc(struct fpm_scoreboard_s *scoreboard, int *child_index) /* {{{ */ +{ + int i = -1; + + if (!scoreboard || !child_index) { + return -1; + } + + /* first try the slot which is supposed to be free */ + if (scoreboard->free_proc >= 0 && scoreboard->free_proc < scoreboard->nprocs) { + if (scoreboard->procs[scoreboard->free_proc] && !scoreboard->procs[scoreboard->free_proc]->used) { + i = scoreboard->free_proc; + } + } + + if (i < 0) { /* the supposed free slot is not, let's search for a free slot */ + zlog(ZLOG_DEBUG, "[pool %s] the proc->free_slot was not free. Let's search", scoreboard->pool); + for (i = 0; i < scoreboard->nprocs; i++) { + if (scoreboard->procs[i] && !scoreboard->procs[i]->used) { /* found */ + break; + } + } + } + + /* no free slot */ + if (i < 0 || i >= scoreboard->nprocs) { + zlog(ZLOG_ERROR, "[pool %s] no free scoreboard slot", scoreboard->pool); + return -1; + } + + scoreboard->procs[i]->used = 1; + *child_index = i; + + /* supposed next slot is free */ + if (i + 1 >= scoreboard->nprocs) { + scoreboard->free_proc = 0; + } else { + scoreboard->free_proc = i + 1; + } + + return 0; +} +/* }}} */ + diff --git a/sapi/fpm/fpm/fpm_scoreboard.h b/sapi/fpm/fpm/fpm_scoreboard.h new file mode 100644 index 000000000..e62c42d98 --- /dev/null +++ b/sapi/fpm/fpm/fpm_scoreboard.h @@ -0,0 +1,85 @@ + + /* $Id: fpm_status.h 312263 2011-06-18 17:46:16Z felipe $ */ + /* (c) 2009 Jerome Loyet */ + +#ifndef FPM_SCOREBOARD_H +#define FPM_SCOREBOARD_H 1 + +#include <sys/time.h> +#ifdef HAVE_TIMES +#include <sys/times.h> +#endif + +#include "fpm_request.h" +#include "fpm_worker_pool.h" +#include "fpm_atomic.h" + +#define FPM_SCOREBOARD_ACTION_SET 0 +#define FPM_SCOREBOARD_ACTION_INC 1 + +struct fpm_scoreboard_proc_s { + union { + atomic_t lock; + char dummy[16]; + }; + int used; + pid_t pid; + enum fpm_request_stage_e request_stage; + struct timeval accepted; + time_t accepted_epoch; + struct timeval tv; + char request_uri[128]; + char query_string[512]; + char request_method[16]; + size_t content_length; /* used with POST only */ + char script_filename[256]; + char auth_user[32]; +#ifdef HAVE_TIMES + struct tms cpu_accepted; + struct tms cpu_finished; + struct timeval cpu_duration; +#endif + size_t memory; +}; + +struct fpm_scoreboard_s { + union { + atomic_t lock; + char dummy[16]; + }; + char pool[32]; + int pm; + time_t start_epoch; + int idle; + int active; + int active_max; + unsigned long int requests; + unsigned int max_children_reached; + int lq; + int lq_max; + unsigned int lq_len; + unsigned int nprocs; + int free_proc; + struct fpm_scoreboard_proc_s *procs[]; +}; + +int fpm_scoreboard_init_main(); +int fpm_scoreboard_init_child(struct fpm_worker_pool_s *wp); + +void fpm_scoreboard_update(int idle, int active, int lq, int lq_len, int requests, int max_children_reached, int action, struct fpm_scoreboard_s *scoreboard); +struct fpm_scoreboard_s *fpm_scoreboard_get(); +struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get(struct fpm_scoreboard_s *scoreboard, int child_index); + +struct fpm_scoreboard_s *fpm_scoreboard_acquire(struct fpm_scoreboard_s *scoreboard, int nohang); +void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard); +struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_acquire(struct fpm_scoreboard_s *scoreboard, int child_index, int nohang); +void fpm_scoreboard_proc_release(struct fpm_scoreboard_proc_s *proc); + +void fpm_scoreboard_free(struct fpm_scoreboard_s *scoreboard); + +void fpm_scoreboard_child_use(struct fpm_scoreboard_s *scoreboard, int child_index, pid_t pid); + +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); + +#endif diff --git a/sapi/fpm/fpm/fpm_shm.c b/sapi/fpm/fpm/fpm_shm.c index 5f4040990..a777612de 100644 --- a/sapi/fpm/fpm/fpm_shm.c +++ b/sapi/fpm/fpm/fpm_shm.c @@ -1,12 +1,10 @@ /* $Id: fpm_shm.c,v 1.3 2008/05/24 17:38:47 anight Exp $ */ - /* (c) 2007,2008 Andrei Nigmatulin */ + /* (c) 2007,2008 Andrei Nigmatulin, Jerome Loyet */ -#include "fpm_config.h" - -#include <unistd.h> #include <sys/mman.h> -#include <stdlib.h> +#include <errno.h> +#include <string.h> #include "fpm_shm.h" #include "zlog.h" @@ -17,85 +15,56 @@ #define MAP_ANONYMOUS MAP_ANON #endif -struct fpm_shm_s *fpm_shm_alloc(size_t sz) /* {{{ */ +static size_t fpm_shm_size = 0; + +void *fpm_shm_alloc(size_t size) /* {{{ */ { - struct fpm_shm_s *shm; + void *mem; - shm = malloc(sizeof(*shm)); + mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); - if (!shm) { - return 0; +#ifdef MAP_FAILED + if (mem == MAP_FAILED) { + zlog(ZLOG_SYSERROR, "unable to allocate %zu bytes in shared memory: %s", size, strerror(errno)); + return NULL; } +#endif - shm->mem = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); - - if (!shm->mem) { - zlog(ZLOG_SYSERROR, "mmap(MAP_ANONYMOUS | MAP_SHARED) failed"); - free(shm); - return 0; + if (!mem) { + zlog(ZLOG_SYSERROR, "unable to allocate %zu bytes in shared memory", size); + return NULL; } - shm->used = 0; - shm->sz = sz; - return shm; + memset(mem, size, 0); + fpm_shm_size += size; + return mem; } /* }}} */ -void fpm_shm_free(struct fpm_shm_s *shm, int do_unmap) /* {{{ */ +int fpm_shm_free(void *mem, size_t size) /* {{{ */ { - if (do_unmap) { - munmap(shm->mem, shm->sz); + if (!mem) { + zlog(ZLOG_ERROR, "mem is NULL"); + return 0; } - free(shm); -} -/* }}} */ -void fpm_shm_free_list(struct fpm_shm_s *shm, void *mem) /* {{{ */ -{ - struct fpm_shm_s *next; + if (munmap(mem, size) == -1) { + zlog(ZLOG_SYSERROR, "Unable to free shm: %s", strerror(errno)); + return 0; + } - for (; shm; shm = next) { - next = shm->next; - fpm_shm_free(shm, mem != shm->mem); + if (fpm_shm_size - size > 0) { + fpm_shm_size -= size; + } else { + fpm_shm_size = 0; } + + return 1; } /* }}} */ -void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem) /* {{{ */ +size_t fpm_shm_get_size_allocated() /* {{{*/ { - size_t pagesize = getpagesize(); - static const size_t cache_line_size = 16; - size_t aligned_sz; - struct fpm_shm_s *shm; - void *ret; - - sz = (sz + cache_line_size - 1) & -cache_line_size; - shm = *head; - - if (0 == shm || shm->sz - shm->used < sz) { - /* allocate one more shm segment */ - - aligned_sz = (sz + pagesize - 1) & -pagesize; - shm = fpm_shm_alloc(aligned_sz); - - if (!shm) { - return 0; - } - - shm->next = *head; - - if (shm->next) { - shm->next->prev = shm; - } - - shm->prev = 0; - *head = shm; - } - - *mem = shm->mem; - ret = (char *) shm->mem + shm->used; - shm->used += sz; - return ret; + return fpm_shm_size; } /* }}} */ - diff --git a/sapi/fpm/fpm/fpm_shm.h b/sapi/fpm/fpm/fpm_shm.h index bbff54c40..bcb609981 100644 --- a/sapi/fpm/fpm/fpm_shm.h +++ b/sapi/fpm/fpm/fpm_shm.h @@ -5,19 +5,9 @@ #ifndef FPM_SHM_H #define FPM_SHM_H 1 -struct fpm_shm_s; - -struct fpm_shm_s { - struct fpm_shm_s *prev, *next; - void *mem; - size_t sz; - size_t used; -}; - -struct fpm_shm_s *fpm_shm_alloc(size_t sz); -void fpm_shm_free(struct fpm_shm_s *shm, int do_unmap); -void fpm_shm_free_list(struct fpm_shm_s *, void *); -void *fpm_shm_alloc_chunk(struct fpm_shm_s **head, size_t sz, void **mem); +void *fpm_shm_alloc(size_t size); +int fpm_shm_free(void *mem, size_t size); +size_t fpm_shm_get_size_allocated(); #endif diff --git a/sapi/fpm/fpm/fpm_shm_slots.c b/sapi/fpm/fpm/fpm_shm_slots.c deleted file mode 100644 index 2c10d6bb9..000000000 --- a/sapi/fpm/fpm/fpm_shm_slots.c +++ /dev/null @@ -1,119 +0,0 @@ - - /* $Id: fpm_shm_slots.c,v 1.2 2008/05/24 17:38:47 anight Exp $ */ - /* (c) 2007,2008 Andrei Nigmatulin */ - -#include "fpm_config.h" - -#include "fpm_atomic.h" -#include "fpm_worker_pool.h" -#include "fpm_children.h" -#include "fpm_shm.h" -#include "fpm_shm_slots.h" -#include "zlog.h" - -static void *shm_mem; -static struct fpm_shm_slot_s *shm_slot; - -int fpm_shm_slots_prepare_slot(struct fpm_child_s *child) /* {{{ */ -{ - struct fpm_worker_pool_s *wp = child->wp; - struct fpm_shm_slot_ptr_s *shm_slot_ptr; - - child->shm_slot_i = wp->slots_used.used; - shm_slot_ptr = fpm_array_push(&wp->slots_used); - - if (0 == shm_slot_ptr) { - return -1; - } - - if (0 == wp->slots_free.used) { - shm_slot_ptr->shm_slot = fpm_shm_alloc_chunk(&wp->shm_list, sizeof(struct fpm_shm_slot_s), &shm_slot_ptr->mem); - if (!shm_slot_ptr->shm_slot) { - return -1; - } - } else { - *shm_slot_ptr = *(struct fpm_shm_slot_ptr_s *) fpm_array_item_last(&wp->slots_free); - --wp->slots_free.used; - } - - memset(shm_slot_ptr->shm_slot, 0, sizeof(struct fpm_shm_slot_s)); - shm_slot_ptr->child = child; - return 0; -} -/* }}} */ - -void fpm_shm_slots_discard_slot(struct fpm_child_s *child) /* {{{ */ -{ - struct fpm_shm_slot_ptr_s *shm_slot_ptr; - struct fpm_worker_pool_s *wp = child->wp; - int n; - - shm_slot_ptr = fpm_array_push(&wp->slots_free); - if (shm_slot_ptr) { - struct fpm_shm_slot_ptr_s *shm_slot_ptr_used; - - shm_slot_ptr_used = fpm_array_item(&wp->slots_used, child->shm_slot_i); - *shm_slot_ptr = *shm_slot_ptr_used; - shm_slot_ptr->child = 0; - } - - n = fpm_array_item_remove(&wp->slots_used, child->shm_slot_i); - if (n > -1) { - shm_slot_ptr = fpm_array_item(&wp->slots_used, n); - shm_slot_ptr->child->shm_slot_i = n; - } -} -/* }}} */ - -void fpm_shm_slots_child_use_slot(struct fpm_child_s *child) /* {{{ */ -{ - struct fpm_shm_slot_ptr_s *shm_slot_ptr; - struct fpm_worker_pool_s *wp = child->wp; - - shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i); - shm_slot = shm_slot_ptr->shm_slot; - shm_mem = shm_slot_ptr->mem; -} -/* }}} */ - -void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child) /* {{{ */ -{ - /* nothing to do */ -} -/* }}} */ - -void *fpm_shm_slots_mem() /* {{{ */ -{ - return shm_mem; -} -/* }}} */ - -struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child) /* {{{ */ -{ - struct fpm_shm_slot_ptr_s *shm_slot_ptr; - struct fpm_worker_pool_s *wp = child->wp; - - shm_slot_ptr = fpm_array_item(&wp->slots_used, child->shm_slot_i); - return shm_slot_ptr->shm_slot; -} -/* }}} */ - -struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *s, int nohang) /* {{{ */ -{ - if (s == 0) { - s = shm_slot; - } - - if (0 > fpm_spinlock(&s->lock, nohang)) { - return 0; - } - return s; -} -/* }}} */ - -void fpm_shm_slots_release(struct fpm_shm_slot_s *s) /* {{{ */ -{ - s->lock = 0; -} -/* }}} */ - diff --git a/sapi/fpm/fpm/fpm_shm_slots.h b/sapi/fpm/fpm/fpm_shm_slots.h deleted file mode 100644 index d74f17622..000000000 --- a/sapi/fpm/fpm/fpm_shm_slots.h +++ /dev/null @@ -1,44 +0,0 @@ - - /* $Id: fpm_shm_slots.h,v 1.2 2008/05/24 17:38:47 anight Exp $ */ - /* (c) 2007,2008 Andrei Nigmatulin */ - -#ifndef FPM_SHM_SLOTS_H -#define FPM_SHM_SLOTS_H 1 - -#include "fpm_atomic.h" -#include "fpm_worker_pool.h" -#include "fpm_request.h" - -struct fpm_child_s; - -struct fpm_shm_slot_s { - union { - atomic_t lock; - char dummy[16]; - }; - enum fpm_request_stage_e request_stage; - struct timeval accepted; - struct timeval tv; - char request_uri[128]; - char request_method[16]; - size_t content_length; /* used with POST only */ - char script_filename[256]; -}; - -struct fpm_shm_slot_ptr_s { - void *mem; - struct fpm_shm_slot_s *shm_slot; - struct fpm_child_s *child; -}; - -int fpm_shm_slots_prepare_slot(struct fpm_child_s *child); -void fpm_shm_slots_discard_slot(struct fpm_child_s *child); -void fpm_shm_slots_child_use_slot(struct fpm_child_s *child); -void fpm_shm_slots_parent_use_slot(struct fpm_child_s *child); -void *fpm_shm_slots_mem(); -struct fpm_shm_slot_s *fpm_shm_slot(struct fpm_child_s *child); -struct fpm_shm_slot_s *fpm_shm_slots_acquire(struct fpm_shm_slot_s *, int nohang); -void fpm_shm_slots_release(struct fpm_shm_slot_s *); - -#endif - diff --git a/sapi/fpm/fpm/fpm_signals.c b/sapi/fpm/fpm/fpm_signals.c index aea69750b..7c317e576 100644 --- a/sapi/fpm/fpm/fpm_signals.c +++ b/sapi/fpm/fpm/fpm_signals.c @@ -201,11 +201,11 @@ int fpm_signals_init_main() /* {{{ */ sigfillset(&act.sa_mask); if (0 > sigaction(SIGTERM, &act, 0) || - 0 > sigaction(SIGINT, &act, 0) || - 0 > sigaction(SIGUSR1, &act, 0) || - 0 > sigaction(SIGUSR2, &act, 0) || - 0 > sigaction(SIGCHLD, &act, 0) || - 0 > sigaction(SIGQUIT, &act, 0)) { + 0 > sigaction(SIGINT, &act, 0) || + 0 > sigaction(SIGUSR1, &act, 0) || + 0 > sigaction(SIGUSR2, &act, 0) || + 0 > sigaction(SIGCHLD, &act, 0) || + 0 > sigaction(SIGQUIT, &act, 0)) { zlog(ZLOG_SYSERROR, "sigaction() failed"); return -1; @@ -230,11 +230,11 @@ int fpm_signals_init_child() /* {{{ */ close(sp[1]); if (0 > sigaction(SIGTERM, &act_dfl, 0) || - 0 > sigaction(SIGINT, &act_dfl, 0) || - 0 > sigaction(SIGUSR1, &act_dfl, 0) || - 0 > sigaction(SIGUSR2, &act_dfl, 0) || - 0 > sigaction(SIGCHLD, &act_dfl, 0) || - 0 > sigaction(SIGQUIT, &act, 0)) { + 0 > sigaction(SIGINT, &act_dfl, 0) || + 0 > sigaction(SIGUSR1, &act_dfl, 0) || + 0 > sigaction(SIGUSR2, &act_dfl, 0) || + 0 > sigaction(SIGCHLD, &act_dfl, 0) || + 0 > sigaction(SIGQUIT, &act, 0)) { zlog(ZLOG_SYSERROR, "sigaction() failed"); return -1; diff --git a/sapi/fpm/fpm/fpm_sockets.c b/sapi/fpm/fpm/fpm_sockets.c index d89315026..08e2342e5 100644 --- a/sapi/fpm/fpm/fpm_sockets.c +++ b/sapi/fpm/fpm/fpm_sockets.c @@ -28,6 +28,7 @@ #include "fpm_str.h" #include "fpm_env.h" #include "fpm_cleanup.h" +#include "fpm_scoreboard.h" struct listening_socket_s { int refcount; @@ -207,6 +208,7 @@ static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct zlog(ZLOG_SYSERROR, "listen() for address '%s' failed", wp->config->listen_address); return -1; } + return sock; } /* }}} */ @@ -222,6 +224,7 @@ static int fpm_sockets_get_listening_socket(struct fpm_worker_pool_s *wp, struct sock = fpm_sockets_new_listening_socket(wp, sa, socklen); fpm_sockets_hash_op(sock, sa, 0, wp->listen_address_domain, FPM_STORE_USE_SOCKET); + return sock; } /* }}} */ @@ -294,7 +297,7 @@ static int fpm_socket_af_unix_listening_socket(struct fpm_worker_pool_s *wp) /* int fpm_sockets_init_main() /* {{{ */ { - unsigned i; + unsigned i, lq_len; struct fpm_worker_pool_s *wp; char *inherited = getenv("FPM_SOCKETS"); struct listening_socket_s *ls; @@ -344,13 +347,13 @@ int fpm_sockets_init_main() /* {{{ */ break; } - if (0 > fpm_socket_get_listening_queue(wp, NULL, (unsigned *) &wp->listening_queue_len)) { - wp->listening_queue_len = -1; - } - if (wp->listening_socket == -1) { return -1; } + + if (wp->listen_address_domain == FPM_AF_INET && fpm_socket_get_listening_queue(wp->listening_socket, NULL, &lq_len) >= 0) { + fpm_scoreboard_update(-1, -1, -1, (int)lq_len, -1, -1, FPM_SCOREBOARD_ACTION_SET, wp->scoreboard); + } } /* close unused sockets that was inherited */ @@ -383,16 +386,13 @@ int fpm_sockets_init_main() /* {{{ */ #include <netinet/tcp.h> -int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq) +int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq) { - if (wp->listen_address_domain != FPM_AF_INET) { - return -1; - } - struct tcp_info info; socklen_t len = sizeof(info); - if (0 > getsockopt(wp->listening_socket, IPPROTO_TCP, TCP_INFO, &info, &len)) { + if (0 > getsockopt(sock, IPPROTO_TCP, TCP_INFO, &info, &len)) { + zlog(ZLOG_SYSERROR, "unable to retrieve TCP_INFO for socket"); return -1; } @@ -416,13 +416,13 @@ int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_l #ifdef HAVE_LQ_SO_LISTENQ -int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq) +int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq) { int val; socklen_t len = sizeof(val); if (cur_lq) { - if (0 > getsockopt(wp->listening_socket, SOL_SOCKET, SO_LISTENQLEN, &val, &len)) { + if (0 > getsockopt(sock, SOL_SOCKET, SO_LISTENQLEN, &val, &len)) { return -1; } @@ -430,7 +430,7 @@ int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_l } if (max_lq) { - if (0 > getsockopt(wp->listening_socket, SOL_SOCKET, SO_LISTENQLIMIT, &val, &len)) { + if (0 > getsockopt(sock, SOL_SOCKET, SO_LISTENQLIMIT, &val, &len)) { return -1; } @@ -444,7 +444,7 @@ int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_l #else -int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq) +int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq) { return -1; } diff --git a/sapi/fpm/fpm/fpm_sockets.h b/sapi/fpm/fpm/fpm_sockets.h index b74fc234c..447fbff4b 100644 --- a/sapi/fpm/fpm/fpm_sockets.h +++ b/sapi/fpm/fpm/fpm_sockets.h @@ -21,7 +21,7 @@ enum fpm_address_domain fpm_sockets_domain_from_address(char *addr); int fpm_sockets_init_main(); -int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq); +int fpm_socket_get_listening_queue(int sock, unsigned *cur_lq, unsigned *max_lq); static inline int fd_set_blocked(int fd, int blocked) /* {{{ */ diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c index 76daf7d10..8d7b75997 100644 --- a/sapi/fpm/fpm/fpm_status.c +++ b/sapi/fpm/fpm/fpm_status.c @@ -1,20 +1,22 @@ - /* $Id: fpm_status.c 305281 2010-11-11 21:38:18Z fat $ */ + /* $Id: fpm_status.c 312914 2011-07-04 21:29:32Z fat $ */ /* (c) 2009 Jerome Loyet */ #include "php.h" +#include "SAPI.h" #include <stdio.h> #include "fpm_config.h" +#include "fpm_scoreboard.h" #include "fpm_status.h" #include "fpm_clock.h" +#include "fpm_scoreboard.h" #include "zlog.h" +#include "fpm_atomic.h" -struct fpm_shm_s *fpm_status_shm = NULL; -static char *fpm_status_pool = NULL; static char *fpm_status_uri = NULL; -static char *fpm_status_ping= NULL; -static char *fpm_status_pong= NULL; +static char *fpm_status_ping_uri = NULL; +static char *fpm_status_ping_response = NULL; int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ @@ -23,310 +25,218 @@ int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ zlog(ZLOG_ERROR, "unable to init fpm_status because conf structure is NULL"); return -1; } - if (wp->config->pm_status_path || wp->config->ping_path) { - if (wp->config->pm_status_path) { - if (!wp->shm_status) { - zlog(ZLOG_ERROR, "[pool %s] unable to init fpm_status because the dedicated SHM has not been set", wp->config->name); - return -1; - } - fpm_status_shm = wp->shm_status; - } - fpm_status_pool = strdup(wp->config->name); - if (wp->config->pm_status_path) { - fpm_status_uri = strdup(wp->config->pm_status_path); - } - 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); - return -1; - } - fpm_status_ping = strdup(wp->config->ping_path); - fpm_status_pong = strdup(wp->config->ping_response); - } - } - return 0; -} -/* }}} */ - -void fpm_status_set_pm(struct fpm_shm_s *shm, int pm) /* {{{ */ -{ - struct fpm_status_s status; - - if (!shm) shm = fpm_status_shm; - if (!shm || !shm->mem) return; - - /* one shot operation */ - status = *(struct fpm_status_s *)shm->mem; - - status.pm = pm; - - /* one shot operation */ - *(struct fpm_status_s *)shm->mem = status; -} -/* }}} */ - -void fpm_status_increment_accepted_conn(struct fpm_shm_s *shm) /* {{{ */ -{ - struct fpm_status_s status; - - if (!shm) shm = fpm_status_shm; - if (!shm || !shm->mem) return; - - /* one shot operation */ - status = *(struct fpm_status_s *)shm->mem; - - status.accepted_conn++; - - /* one shot operation */ - *(struct fpm_status_s *)shm->mem = status; -} -/* }}} */ - -void fpm_status_update_accepted_conn(struct fpm_shm_s *shm, unsigned long int accepted_conn) /* {{{ */ -{ - struct fpm_status_s status; - - if (!shm) shm = fpm_status_shm; - if (!shm || !shm->mem) return; - /* one shot operation */ - status = *(struct fpm_status_s *)shm->mem; - - status.accepted_conn = accepted_conn; - - /* one shot operation */ - *(struct fpm_status_s *)shm->mem = status; -} -/* }}} */ - -void fpm_status_increment_max_children_reached(struct fpm_shm_s *shm) /* {{{ */ -{ - struct fpm_status_s status; - - if (!shm) shm = fpm_status_shm; - if (!shm || !shm->mem) return; - - /* one shot operation */ - status = *(struct fpm_status_s *)shm->mem; + if (wp->config->pm_status_path) { + fpm_status_uri = strdup(wp->config->pm_status_path); + } - status.max_children_reached++; + 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); + return -1; + } + fpm_status_ping_uri = strdup(wp->config->ping_path); + fpm_status_ping_response = strdup(wp->config->ping_response); + } - /* one shot operation */ - *(struct fpm_status_s *)shm->mem = status; + return 0; } /* }}} */ -void fpm_status_update_max_children_reached(struct fpm_shm_s *shm, unsigned int max_children_reached) /* {{{ */ +int fpm_status_handle_request(TSRMLS_D) /* {{{ */ { - struct fpm_status_s status; - - if (!shm) shm = fpm_status_shm; - if (!shm || !shm->mem) return; + struct fpm_scoreboard_s scoreboard, *scoreboard_p; +// struct fpm_scoreboard_proc_s proc; + char *buffer, *syntax, *time_format, time_buffer[64]; + time_t now_epoch; - /* one shot operation */ - status = *(struct fpm_status_s *)shm->mem; + if (!SG(request_info).request_uri) { + return 0; + } - status.max_children_reached = max_children_reached; + /* PING */ + if (fpm_status_ping_uri && fpm_status_ping_response && !strcmp(fpm_status_ping_uri, SG(request_info).request_uri)) { + 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); + SG(sapi_headers).http_response_code = 200; - /* one shot operation */ - *(struct fpm_status_s *)shm->mem = status; -} -/* }}} */ - -void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int total, unsigned cur_lq, int max_lq, int clear_last_update) /* {{{ */ -{ - struct fpm_status_s status; + /* handle HEAD */ + if (SG(request_info).headers_only) { + return 1; + } - if (!shm) shm = fpm_status_shm; - if (!shm || !shm->mem) return; + PUTS(fpm_status_ping_response); + return 1; + } - /* one shot operation */ - status = *(struct fpm_status_s *)shm->mem; + /* STATUS */ + if (fpm_status_uri && !strcmp(fpm_status_uri, SG(request_info).request_uri)) { + + scoreboard_p = fpm_scoreboard_get(); + if (!scoreboard_p) { + zlog(ZLOG_ERROR, "status: unable to find or access status shared memory"); + SG(sapi_headers).http_response_code = 500; + 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); + PUTS("Internal error. Please review log file for errors."); + return 1; + } - status.idle = idle; - status.active = active; - status.total = total; - status.cur_lq = cur_lq; - status.max_lq = max_lq; - if (clear_last_update) { - memset(&status.last_update, 0, sizeof(status.last_update)); - } else { - fpm_clock_get(&status.last_update); - } + if (!fpm_spinlock(&scoreboard_p->lock, 1)) { + zlog(ZLOG_NOTICE, "[pool %s] status: scoreboard already in used.", scoreboard_p->pool); + SG(sapi_headers).http_response_code = 503; + 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); + PUTS("Server busy. Please try again later."); + return 1; + } + /* copy the scoreboard not to bother other processes */ + scoreboard = *scoreboard_p; + fpm_unlock(scoreboard_p->lock); + + if (scoreboard.idle < 0 || scoreboard.active < 0) { + zlog(ZLOG_ERROR, "[pool %s] invalid status values", scoreboard.pool); + SG(sapi_headers).http_response_code = 500; + 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); + PUTS("Internal error. Please review log file for errors."); + return 1; + } - /* one shot operation */ - *(struct fpm_status_s *)shm->mem = status; -} -/* }}} */ + /* send common headers */ + 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); + SG(sapi_headers).http_response_code = 200; -static void fpm_status_handle_status_txt(struct fpm_status_s *status, char **output, char **content_type) /* {{{ */ -{ - if (!status || !output || !content_type) { - return; - } + /* handle HEAD */ + if (SG(request_info).headers_only) { + return 1; + } - spprintf(output, 0, - "pool: %s\n" - "process manager: %s\n" - "accepted conn: %lu\n" + /* 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"; + + syntax = + "<table>\n" + "<tr><th>pool</th><td>%s</td></tr>\n" + "<tr><th>process manager</th><td>%s</td></tr>\n" + "<tr><th>start time</th><td>%s</td></tr>\n" + "<tr><th>start since</th><td>%lu</td></tr>\n" + "<tr><th>accepted conn</th><td>%lu</td></tr>\n" #if HAVE_FPM_LQ - "listen queue len: %u\n" - "max listen queue len: %d\n" + "<tr><th>listen queue</th><td>%u</td></tr>\n" + "<tr><th>max listen queue</th><td>%u</td></tr>\n" + "<tr><th>listen queue len</th><td>%d</td></tr>\n" #endif - "idle processes: %d\n" - "active processes: %d\n" - "total processes: %d\n" - "max children reached: %u\n", - fpm_status_pool, - status->pm == PM_STYLE_STATIC ? "static" : "dynamic", - status->accepted_conn, + "<tr><th>idle processes</th><td>%d</td></tr>\n" + "<tr><th>active processes</th><td>%d</td></tr>\n" + "<tr><th>total processes</th><td>%d</td></tr>\n" + "<tr><th>max active processes</th><td>%d</td></tr>\n" + "<tr><th>max children reached</th><td>%u</td></tr>\n" + "</table>\n"; + + /* 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"; + + syntax = + "<?xml version=\"1.0\" ?>\n" + "<status>\n" + "<pool>%s</pool>\n" + "<process-manager>%s</process-manager>\n" + "<start-time>%s</start-time>\n" + "<start-since>%lu</start-since>\n" + "<accepted-conn>%lu</accepted-conn>\n" #if HAVE_FPM_LQ - status->cur_lq, - status->max_lq, + "<listen-queue>%u</listen-queue>\n" + "<max-listen-queue>%u</max-listen-queue>\n" + "<listen-queue-len>%d</listen-queue-len>\n" #endif - status->idle, - status->active, - status->total, - status->max_children_reached); - - spprintf(content_type, 0, "Content-Type: text/plain"); -} -/* }}} */ - -static void fpm_status_handle_status_html(struct fpm_status_s *status, char **output, char **content_type) /* {{{ */ -{ - if (!status || !output || !content_type) { - return; - } - - spprintf(output, 0, - "<table>\n" - "<tr><th>pool</th><td>%s</td></tr>\n" - "<tr><th>process manager</th><td>%s</td></tr>\n" - "<tr><th>accepted conn</th><td>%lu</td></tr>\n" + "<idle-processes>%d</idle-processes>\n" + "<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>"; + + /* 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 = + "{" + "\"pool\":\"%s\"," + "\"process manager\":\"%s\"," + "\"start time\":%s," + "\"start since\":%lu," + "\"accepted conn\":%lu," #if HAVE_FPM_LQ - "<tr><th>listen queue len</th><td>%u</td></tr>\n" - "<tr><th>max listen queue len</th><td>%d</td></tr>\n" + "\"listen queue\":%u," + "\"max listen queue\":%u," + "\"listen queue len\":%d," #endif - "<tr><th>idle processes</th><td>%d</td></tr>\n" - "<tr><th>active processes</th><td>%d</td></tr>\n" - "<tr><th>total processes</th><td>%d</td></tr>\n" - "<tr><th>max children reached</th><td>%u</td></tr>\n" - "</table>", - fpm_status_pool, - status->pm == PM_STYLE_STATIC ? "static" : "dynamic", - status->accepted_conn, + "\"idle processes\":%d," + "\"active processes\":%d," + "\"total processes\":%d," + "\"max active processes\":%d," + "\"max children reached\":%u" + "}"; + + /* 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 = + "pool: %s\n" + "process manager: %s\n" + "start time: %s\n" + "start since: %lu\n" + "accepted conn: %lu\n" #if HAVE_FPM_LQ - status->cur_lq, - status->max_lq, + "listen queue: %u\n" + "max listen queue: %u\n" + "listen queue len: %d\n" #endif - status->idle, - status->active, - status->total, - status->max_children_reached); - - spprintf(content_type, 0, "Content-Type: text/html"); -} -/* }}} */ - -static void fpm_status_handle_status_json(struct fpm_status_s *status, char **output, char **content_type) /* {{{ */ -{ - if (!status || !output || !content_type) { - return; - } + "idle processes: %d\n" + "active processes: %d\n" + "total processes: %d\n" + "max active processes: %d\n" + "max children reached: %u\n"; + } - spprintf(output, 0, - "{" - "\"pool\":\"%s\"," - "\"process manager\":\"%s\"," - "\"accepted conn\":%lu," + strftime(time_buffer, sizeof(time_buffer) - 1, time_format, localtime(&scoreboard.start_epoch)); + now_epoch = time(NULL); + spprintf(&buffer, 0, syntax, + scoreboard.pool, + scoreboard.pm == PM_STYLE_STATIC ? "static" : "dynamic", + time_buffer, + now_epoch - scoreboard.start_epoch, + scoreboard.requests, #if HAVE_FPM_LQ - "\"listen queue len\":%u," - "\"max listen queue len\":%d," + scoreboard.lq, + scoreboard.lq_max, + scoreboard.lq_len, #endif - "\"idle processes\":%d," - "\"active processes\":%d," - "\"total processes\":%d," - "\"max children reached\":%u" - "}", - fpm_status_pool, - status->pm == PM_STYLE_STATIC ? "static" : "dynamic", - status->accepted_conn, -#if HAVE_FPM_LQ - status->cur_lq, - status->max_lq, -#endif - status->idle, - status->active, - status->total, - status->max_children_reached); - - spprintf(content_type, 0, "Content-Type: application/json"); -} -/* }}} */ - -/* return 0 if it's not the request page - * return 1 if ouput has been set) - * *output unchanged: error (return 500) - * *output changed: no error (return 200) - */ -int fpm_status_handle_status(char *uri, char *query_string, char **output, char **content_type) /* {{{ */ -{ - struct fpm_status_s status; + scoreboard.idle, + scoreboard.active, + scoreboard.idle + scoreboard.active, + scoreboard.active_max, + scoreboard.max_children_reached); - if (!fpm_status_uri || !uri) { - return 0; - } - - /* It's not the status page */ - if (strcmp(fpm_status_uri, uri)) { - return 0; - } - - if (!output || !content_type || !fpm_status_shm) { - return 1; - } - - if (!fpm_status_shm->mem) { - return 1; - } - - /* one shot operation */ - status = *(struct fpm_status_s *)fpm_status_shm->mem; - - if (status.idle < 0 || status.active < 0 || status.total < 0) { - return 1; - } - - if (query_string && strstr(query_string, "html")) { - fpm_status_handle_status_html(&status, output, content_type); - } else if (query_string && strstr(query_string, "json")) { - fpm_status_handle_status_json(&status, output, content_type); - } else { - fpm_status_handle_status_txt(&status, output, content_type); - } + PUTS(buffer); + efree(buffer); - if (!*output || !content_type) { - zlog(ZLOG_ERROR, "[pool %s] unable to allocate status ouput buffer", fpm_status_pool); return 1; } - return 1; -} -/* }}} */ - -char *fpm_status_handle_ping(char *uri) /* {{{ */ -{ - if (!fpm_status_ping || !fpm_status_pong || !uri) { - return NULL; - } - - /* It's not the status page */ - if (strcmp(fpm_status_ping, uri)) { - return NULL; - } - - return fpm_status_pong; + return 0; } /* }}} */ diff --git a/sapi/fpm/fpm/fpm_status.h b/sapi/fpm/fpm/fpm_status.h index 4e9c50705..fb199a932 100644 --- a/sapi/fpm/fpm/fpm_status.h +++ b/sapi/fpm/fpm/fpm_status.h @@ -1,5 +1,5 @@ - /* $Id: fpm_status.h 305267 2010-11-11 02:34:47Z fat $ */ + /* $Id: fpm_status.h 312263 2011-06-18 17:46:16Z felipe $ */ /* (c) 2009 Jerome Loyet */ #ifndef FPM_STATUS_H @@ -28,8 +28,7 @@ void fpm_status_increment_accepted_conn(struct fpm_shm_s *shm); void fpm_status_set_pm(struct fpm_shm_s *shm, int pm); void fpm_status_update_max_children_reached(struct fpm_shm_s *shm, unsigned int max_children_reached); void fpm_status_increment_max_children_reached(struct fpm_shm_s *shm); -int fpm_status_handle_status(char *uri, char *query_string, char **output, char **content_type); -char* fpm_status_handle_ping(char *uri); +int fpm_status_handle_request(TSRMLS_D); extern struct fpm_shm_s *fpm_status_shm; diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c index d63ea4d5b..d29d38799 100644 --- a/sapi/fpm/fpm/fpm_unix.c +++ b/sapi/fpm/fpm/fpm_unix.c @@ -153,7 +153,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] setrlimit(RLIMIT_NOFILE, %d) failed (%d)", wp->config->name, wp->config->rlimit_files, errno); + 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); } } @@ -163,7 +163,7 @@ 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] setrlimit(RLIMIT_CORE, %d) failed (%d)", wp->config->name, wp->config->rlimit_core, errno); + 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); } } @@ -220,6 +220,28 @@ int fpm_unix_init_main() /* {{{ */ { struct fpm_worker_pool_s *wp; + if (fpm_global_config.rlimit_files) { + struct rlimit r; + + 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); + return -1; + } + } + + if (fpm_global_config.rlimit_core) { + struct rlimit r; + + 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); + return -1; + } + } + fpm_pagesize = getpagesize(); if (fpm_global_config.daemonize) { switch (fork()) { diff --git a/sapi/fpm/fpm/fpm_worker_pool.c b/sapi/fpm/fpm/fpm_worker_pool.c index 53e3368fa..6c6d9cce0 100644 --- a/sapi/fpm/fpm/fpm_worker_pool.c +++ b/sapi/fpm/fpm/fpm_worker_pool.c @@ -13,8 +13,9 @@ #include "fpm_cleanup.h" #include "fpm_children.h" #include "fpm_shm.h" -#include "fpm_shm_slots.h" +#include "fpm_scoreboard.h" #include "fpm_conf.h" +#include "zlog.h" struct fpm_worker_pool_s *fpm_worker_all_pools; @@ -26,18 +27,15 @@ static void fpm_worker_pool_cleanup(int which, void *arg) /* {{{ */ wp_next = wp->next; fpm_worker_pool_config_free(wp->config); fpm_children_free(wp->children); - fpm_array_free(&wp->slots_used); - fpm_array_free(&wp->slots_free); - fpm_shm_free_list(wp->shm_list, which == FPM_CLEANUP_CHILD ? fpm_shm_slots_mem() : 0); - if (wp->shm_status && which != FPM_CLEANUP_CHILD) { - fpm_shm_free(wp->shm_status, !fpm_globals.is_child); + if ((which & FPM_CLEANUP_CHILD) == 0 && fpm_globals.parent_pid == getpid()) { + fpm_scoreboard_free(wp->scoreboard); } free(wp->config); free(wp->user); free(wp->home); free(wp); } - fpm_worker_all_pools = 0; + fpm_worker_all_pools = NULL; } /* }}} */ @@ -52,9 +50,8 @@ struct fpm_worker_pool_s *fpm_worker_pool_alloc() /* {{{ */ memset(ret, 0, sizeof(struct fpm_worker_pool_s)); - fpm_array_init(&ret->slots_used, sizeof(struct fpm_shm_slot_ptr_s), 50); - fpm_array_init(&ret->slots_free, sizeof(struct fpm_shm_slot_ptr_s), 50); ret->idle_spawn_rate = 1; + ret->log_fd = -1; return ret; } /* }}} */ diff --git a/sapi/fpm/fpm/fpm_worker_pool.h b/sapi/fpm/fpm/fpm_worker_pool.h index 7f240a20c..098def5b7 100644 --- a/sapi/fpm/fpm/fpm_worker_pool.h +++ b/sapi/fpm/fpm/fpm_worker_pool.h @@ -6,7 +6,6 @@ #define FPM_WORKER_POOL_H 1 #include "fpm_conf.h" -#include "fpm_arrays.h" #include "fpm_shm.h" struct fpm_worker_pool_s; @@ -25,20 +24,19 @@ struct fpm_worker_pool_s { char *user, *home; /* for setting env USER and HOME */ enum fpm_address_domain listen_address_domain; int listening_socket; - int listening_queue_len; int set_uid, set_gid; /* config uid and gid */ int socket_uid, socket_gid, socket_mode; - struct fpm_shm_s *shm_list; - struct fpm_array_s slots_used; - struct fpm_array_s slots_free; - /* runtime */ struct fpm_child_s *children; int running_children; int idle_spawn_rate; int warn_max_children; - struct fpm_shm_s *shm_status; +#if 0 + int warn_lq; +#endif + struct fpm_scoreboard_s *scoreboard; + int log_fd; }; struct fpm_worker_pool_s *fpm_worker_pool_alloc(); diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c index ddf552b50..6b062eb8a 100644 --- a/sapi/fpm/fpm/zlog.c +++ b/sapi/fpm/fpm/zlog.c @@ -13,6 +13,7 @@ #include <errno.h> #include "zlog.h" +#include "fpm.h" #define MAX_LINE_LENGTH 1024 @@ -28,9 +29,15 @@ static const char *level_names[] = { [ZLOG_ALERT] = "ALERT", }; -const char *zlog_get_level_name() /* {{{ */ +const char *zlog_get_level_name(int log_level) /* {{{ */ { - return level_names[zlog_level]; + if (log_level < 0) { + log_level = zlog_level; + } else if (log_level < ZLOG_DEBUG || log_level > ZLOG_ALERT) { + return "unknown value"; + } + + return level_names[log_level]; } /* }}} */ @@ -47,7 +54,7 @@ size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len) /* if (zlog_level == ZLOG_DEBUG) { len += snprintf(timebuf + len, timebuf_len - len, ".%06d", (int) tv->tv_usec); } - len += snprintf(timebuf + len, timebuf_len - len, "]"); + len += snprintf(timebuf + len, timebuf_len - len, "] "); return len; } /* }}} */ @@ -78,7 +85,7 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* char buf[MAX_LINE_LENGTH]; const size_t buf_size = MAX_LINE_LENGTH; va_list args; - size_t len; + size_t len = 0; int truncated = 0; int saved_errno; @@ -87,12 +94,18 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* } saved_errno = errno; - gettimeofday(&tv, 0); - len = zlog_print_time(&tv, buf, buf_size); + if (!fpm_globals.is_child) { + gettimeofday(&tv, 0); + len = zlog_print_time(&tv, buf, buf_size); + } if (zlog_level == ZLOG_DEBUG) { - len += snprintf(buf + len, buf_size - len, " %s: pid %d, %s(), line %d: ", level_names[flags & ZLOG_LEVEL_MASK], getpid(), function, line); + 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: ", level_names[flags & ZLOG_LEVEL_MASK]); + len += snprintf(buf + len, buf_size - len, "%s: ", level_names[flags & ZLOG_LEVEL_MASK]); } if (len > buf_size - 1) { diff --git a/sapi/fpm/fpm/zlog.h b/sapi/fpm/fpm/zlog.h index 598c075e3..a83e32902 100644 --- a/sapi/fpm/fpm/zlog.h +++ b/sapi/fpm/fpm/zlog.h @@ -11,7 +11,7 @@ struct timeval; int zlog_set_fd(int new_fd); int zlog_set_level(int new_value); -const char *zlog_get_level_name(); +const char *zlog_get_level_name(int log_level); void zlog_set_launched(void); size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len); diff --git a/sapi/fpm/init.d.php-fpm.in b/sapi/fpm/init.d.php-fpm.in index 766d10207..dc66310c3 100644 --- a/sapi/fpm/init.d.php-fpm.in +++ b/sapi/fpm/init.d.php-fpm.in @@ -84,7 +84,7 @@ case "$1" in wait_for_pid removed $php_fpm_PID if [ -n "$try" ] ; then - echo " failed. Use force-exit" + echo " failed. Use force-quit" exit 1 else echo " done" diff --git a/sapi/fpm/php-fpm.conf.in b/sapi/fpm/php-fpm.conf.in index 314b7e5c5..fe2f1a6dc 100644 --- a/sapi/fpm/php-fpm.conf.in +++ b/sapi/fpm/php-fpm.conf.in @@ -57,6 +57,15 @@ ; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging. ; Default Value: yes ;daemonize = yes + +; Set open file descriptor rlimit for the master process. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit for the master process. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 ;;;;;;;;;;;;;;;;;;;; ; Pool Definitions ; @@ -195,11 +204,12 @@ pm.max_children = 50 ; total processes: 100 ; max children reached: 1 ; By default the status page output is formatted as text/plain. Passing either -; 'html' or 'json' as a query string will return the corresponding output +; 'html', 'xml' or 'json' as a 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 ; 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. @@ -222,6 +232,65 @@ pm.max_children = 50 ; response is formatted as text/plain with a 200 response code. ; Default Value: pong ;ping.response = pong + +; The access log file +; Default: not set +;access.log = log/$pool.access.log + +; The access log format. +; The following syntax is allowed +; %%: the '%' character +; %C: %CPU used by the request +; it can accept the following format: +; - %{user}C for user CPU only +; - %{system}C for system CPU only +; - %{total}C for user + system CPU (default) +; %d: time taken to serve the request +; it can accept the following format: +; - %{seconds}d (default) +; - %{miliseconds}d +; - %{mili}d +; - %{microseconds}d +; - %{micro}d +; %e: an environment variable (same as $_ENV or $_SERVER) +; it must be associated with embraces to specify the name of the env +; variable. Some exemples: +; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e +; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e +; %f: script filename +; %l: content-length of the request (for POST request only) +; %m: request method +; %M: peak of memory allocated by PHP +; it can accept the following format: +; - %{bytes}M (default) +; - %{kilobytes}M +; - %{kilo}M +; - %{megabytes}M +; - %{mega}M +; %n: pool name +; %o: ouput header +; it must be associated with embraces to specify the name of the header: +; - %{Content-Type}o +; - %{X-Powered-By}o +; - %{Transfert-Encoding}o +; - .... +; %p: PID of the child that serviced the request +; %P: PID of the parent of the child that serviced the request +; %q: the query string +; %Q: the '?' character if query string exists +; %r: the request URI (without the query string, see %q and %Q) +; %R: remote IP address +; %s: status (response code) +; %t: server time the request was received +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; %T: time the log has been written (the request has finished) +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; %u: remote user +; +; 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 diff --git a/sapi/litespeed/README b/sapi/litespeed/README index 3f138c216..e548ec97d 100644 --- a/sapi/litespeed/README +++ b/sapi/litespeed/README @@ -20,7 +20,7 @@ server configuration to enhance server security when mod_php is used. usually, FastCGI PHP is not an option in shared hosting environment due to lacking of this flexibility. LiteSpeed SAPI is carefully designed to address this issue. PHP configurations can be modified the same way -as that in mod_php with the the same configuration directives. +as that in mod_php with the same configuration directives. PHP with LiteSpeed SAPI is highly recommended over FastCGI PHP for PHP scripting with LiteSpeed web server. diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c index f828b1fc3..0a2f04a28 100644 --- a/sapi/litespeed/lsapi_main.c +++ b/sapi/litespeed/lsapi_main.c @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: lsapi_main.c 306212 2010-12-10 22:51:08Z gwang $ */ +/* $Id: lsapi_main.c 311680 2011-05-31 22:40:42Z gwang $ */ #include "php.h" #include "SAPI.h" @@ -660,6 +660,7 @@ static int cli_main( int argc, char * argv[] ) "implicit_flush", "1", "output_buffering", "0", "max_execution_time", "0", + "max_input_time", "-1", NULL }; diff --git a/sapi/litespeed/lsapilib.c b/sapi/litespeed/lsapilib.c index 56ea94aad..ac5892cd6 100644 --- a/sapi/litespeed/lsapilib.c +++ b/sapi/litespeed/lsapilib.c @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: lsapilib.c 306212 2010-12-10 22:51:08Z gwang $ */ +/* $Id: lsapilib.c 311935 2011-06-08 16:51:59Z gwang $ */ /* Copyright (c) 2007, Lite Speed Technologies Inc. @@ -1453,7 +1453,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) return -1; } - while( isspace( *p ) ) { + while( isspace( *pBind ) ) { ++pBind; } @@ -1509,7 +1509,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) } port = atoi( pEnd ); - if (( port <= 0 )||( port > 655535 )) { + if (( port <= 0 )||( port > 65535 )) { return -1; } if ( doAddrInfo ) { diff --git a/sapi/milter/php_milter.c b/sapi/milter/php_milter.c index 89352073f..188aa68bb 100644 --- a/sapi/milter/php_milter.c +++ b/sapi/milter/php_milter.c @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_milter.c 306939 2011-01-01 02:19:59Z felipe $ */ +/* $Id: php_milter.c 314352 2011-08-06 01:22:27Z felipe $ */ #include "php.h" #include "php_globals.h" @@ -833,7 +833,7 @@ const static zend_function_entry milter_functions[] = { PHP_FE(smfi_addrcpt, arginfo_smfi_addrcpt) PHP_FE(smfi_delrcpt, arginfo_smfi_delrcpt) PHP_FE(smfi_replacebody, arginfo_smfi_replacebody) - { NULL, NULL, NULL } + PHP_FE_END }; /* }}} */ diff --git a/sapi/thttpd/README b/sapi/thttpd/README index b0245841a..7529b7ecf 100644 --- a/sapi/thttpd/README +++ b/sapi/thttpd/README @@ -1,5 +1,5 @@ README FOR THTTPD MODULE (by Sascha Schumann) -($Date: 2003-02-19 11:57:21 +0100 (Wed, 19 Feb 2003) $) +($Date: 2003-02-19 05:57:21 -0500 (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/tux/README b/sapi/tux/README index 3a5294c77..cf2a6a0a9 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 14:00:38 +0100 (Sat, 17 Jan 2004) $) +($Date: 2004-01-17 08:00:38 -0500 (Sat, 17 Jan 2004) $) This is a SAPI module for the TUX web-server by Ingo Molnar. |
