summaryrefslogtreecommitdiff
path: root/sapi/fpm
diff options
context:
space:
mode:
Diffstat (limited to 'sapi/fpm')
-rw-r--r--sapi/fpm/Makefile.frag6
-rw-r--r--sapi/fpm/config.m4287
-rw-r--r--sapi/fpm/fpm/fpm.c24
-rw-r--r--sapi/fpm/fpm/fpm.h7
-rw-r--r--sapi/fpm/fpm/fpm_atomic.h22
-rw-r--r--sapi/fpm/fpm/fpm_children.c46
-rw-r--r--sapi/fpm/fpm/fpm_children.h10
-rw-r--r--sapi/fpm/fpm/fpm_clock.c8
-rw-r--r--sapi/fpm/fpm/fpm_conf.c507
-rw-r--r--sapi/fpm/fpm/fpm_conf.h7
-rw-r--r--sapi/fpm/fpm/fpm_config.h75
-rw-r--r--sapi/fpm/fpm/fpm_env.c96
-rw-r--r--sapi/fpm/fpm/fpm_env.h3
-rw-r--r--sapi/fpm/fpm/fpm_events.c399
-rw-r--r--sapi/fpm/fpm/fpm_events.h28
-rw-r--r--sapi/fpm/fpm/fpm_main.c42
-rw-r--r--sapi/fpm/fpm/fpm_php.c2
-rw-r--r--sapi/fpm/fpm/fpm_php.h20
-rw-r--r--sapi/fpm/fpm/fpm_php_trace.c6
-rw-r--r--sapi/fpm/fpm/fpm_process_ctl.c141
-rw-r--r--sapi/fpm/fpm/fpm_process_ctl.h17
-rw-r--r--sapi/fpm/fpm/fpm_request.c17
-rw-r--r--sapi/fpm/fpm/fpm_shm.c2
-rw-r--r--sapi/fpm/fpm/fpm_signals.c10
-rw-r--r--sapi/fpm/fpm/fpm_sockets.c109
-rw-r--r--sapi/fpm/fpm/fpm_sockets.h10
-rw-r--r--sapi/fpm/fpm/fpm_status.c129
-rw-r--r--sapi/fpm/fpm/fpm_status.h9
-rw-r--r--sapi/fpm/fpm/fpm_stdio.c57
-rw-r--r--sapi/fpm/fpm/fpm_stdio.h2
-rw-r--r--sapi/fpm/fpm/fpm_trace_mach.c6
-rw-r--r--sapi/fpm/fpm/fpm_trace_pread.c6
-rw-r--r--sapi/fpm/fpm/fpm_trace_ptrace.c8
-rw-r--r--sapi/fpm/fpm/fpm_unix.c36
-rw-r--r--sapi/fpm/fpm/fpm_worker_pool.h1
-rw-r--r--sapi/fpm/fpm/zlog.c16
-rw-r--r--sapi/fpm/fpm/zlog.h6
-rw-r--r--sapi/fpm/init.d.php-fpm.in4
-rw-r--r--sapi/fpm/php-fpm.8.in (renamed from sapi/fpm/php-fpm.1.in)19
-rw-r--r--sapi/fpm/php-fpm.conf.in77
40 files changed, 1547 insertions, 730 deletions
diff --git a/sapi/fpm/Makefile.frag b/sapi/fpm/Makefile.frag
index 0f1964ee6..0859ef10c 100644
--- a/sapi/fpm/Makefile.frag
+++ b/sapi/fpm/Makefile.frag
@@ -22,7 +22,7 @@ install-fpm: install-sapi
@$(INSTALL_DATA) sapi/fpm/php-fpm.conf $(INSTALL_ROOT)$(sysconfdir)/php-fpm.conf.default || :
- @echo "Installing PHP FPM man page: $(INSTALL_ROOT)$(mandir)/man1/"
- @$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man1
- @$(INSTALL_DATA) sapi/fpm/php-fpm.1 $(INSTALL_ROOT)$(mandir)/man1/php-fpm$(program_suffix).1
+ @echo "Installing PHP FPM man page: $(INSTALL_ROOT)$(mandir)/man8/"
+ @$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man8
+ @$(INSTALL_DATA) sapi/fpm/php-fpm.8 $(INSTALL_ROOT)$(mandir)/man8/php-fpm$(program_suffix).8
diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4
index 0cefd968d..6899ea790 100644
--- a/sapi/fpm/config.m4
+++ b/sapi/fpm/config.m4
@@ -2,225 +2,13 @@ dnl
dnl $Id$
dnl
-fpm_version="0.6.5"
-minimum_libevent_version="1.4.11"
-
PHP_ARG_ENABLE(fpm,,
[ --enable-fpm EXPERIMENTAL: Enable building of the fpm SAPI executable], no, no)
-dnl libevent check function {{{
-dnl @synopsis AC_LIB_EVENT([MINIMUM-VERSION])
-dnl
-dnl Test for the libevent library of a particular version (or newer).
-dnl Source: http://svn.apache.org/repos/asf/incubator/thrift/trunk/aclocal/ax_lib_event.m4
-dnl Modified: This file was modified for autoconf-2.13 and the PHP_ARG_WITH macro.
-dnl
-dnl If no path to the installed libevent is given, the macro will first try
-dnl using no -I or -L flags, then searches under /usr, /usr/local, /opt,
-dnl and /opt/libevent.
-dnl If these all fail, it will try the $LIBEVENT_ROOT environment variable.
-dnl
-dnl This macro requires that #include <sys/types.h> works and defines u_char.
-dnl
-dnl This macro calls:
-dnl AC_SUBST(LIBEVENT_CFLAGS)
-dnl AC_SUBST(LIBEVENT_LIBS)
-dnl
-dnl And (if libevent is found):
-dnl AC_DEFINE(HAVE_LIBEVENT)
-dnl
-dnl It also leaves the shell variables "success" and "ac_have_libevent"
-dnl set to "yes" or "no".
-dnl
-dnl NOTE: This macro does not currently work for cross-compiling,
-dnl but it can be easily modified to allow it. (grep "cross").
-dnl
-dnl @category InstalledPackages
-dnl @category C
-dnl @version 2007-09-12
-dnl @license AllPermissive
-dnl
-dnl Copyright (C) 2009 David Reiss
-dnl Copying and distribution of this file, with or without modification,
-dnl are permitted in any medium without royalty provided the copyright
-dnl notice and this notice are preserved.
-
-AC_DEFUN([AC_LIB_EVENT_DO_CHECK],
-[
-# Save our flags.
-CPPFLAGS_SAVED="$CPPFLAGS"
-LDFLAGS_SAVED="$LDFLAGS"
-LIBS_SAVED="$LIBS"
-LD_LIBRARY_PATH_SAVED="$LD_LIBRARY_PATH"
-
-# Set our flags if we are checking a specific directory.
-if test -n "$ac_libevent_path" ; then
- LIBEVENT_CPPFLAGS="-I$ac_libevent_path/include"
-
- if test -z "$PHP_LIBDIR"; then
- LIBEVENT_LDFLAGS="-L$ac_libevent_path/lib"
- else
- LIBEVENT_LDFLAGS="-L$ac_libevent_path/$PHP_LIBDIR"
- fi
-
- LD_LIBRARY_PATH="$ac_libevent_path/lib:$LD_LIBRARY_PATH"
-else
- LIBEVENT_CPPFLAGS=""
- LIBEVENT_LDFLAGS=""
-fi
-
-# Required flag for libevent.
-LIBEVENT_LIBS="-levent"
-
-# Prepare the environment for compilation.
-CPPFLAGS="$CPPFLAGS $LIBEVENT_CPPFLAGS"
-LDFLAGS="$LDFLAGS $LIBEVENT_LDFLAGS"
-LIBS="$LIBS $LIBEVENT_LIBS"
-export CPPFLAGS
-export LDFLAGS
-export LIBS
-export LD_LIBRARY_PATH
-
-success=no
-
-# Compile, link, and run the program. This checks:
-# - event.h is available for including.
-# - event_get_version() is available for linking.
-# - The event version string is lexicographically greater
-# than the required version.
-AC_TRY_RUN([
-#include <sys/types.h>
-#include <event.h>
-
-int main(int argc, char *argv[])
-{
- const char* lib_version = event_get_version();
- const char* wnt_version = "$WANT_LIBEVENT_VERSION";
- for (;;) {
- /* If we reached the end of the want version. We have it. */
- if (*wnt_version == '\0' || *wnt_version == '-') {
- return 0;
- }
- /* If the want version continues but the lib version does not, */
- /* we are missing a letter. We don't have it. */
- if (*lib_version == '\0' || *lib_version == '-') {
- return 1;
- }
-
- /* In the 1.4 version numbering style, if there are more digits */
- /* in one version than the other, that one is higher. */
- int lib_digits;
- for (lib_digits = 0;
- lib_version[lib_digits] >= '0' &&
- lib_version[lib_digits] <= '9';
- lib_digits++)
- ;
- int wnt_digits;
- for (wnt_digits = 0;
- wnt_version[wnt_digits] >= '0' &&
- wnt_version[wnt_digits] <= '9';
- wnt_digits++)
- ;
- if (lib_digits > wnt_digits) {
- return 0;
- }
- if (lib_digits < wnt_digits) {
- return 1;
- }
- /* If we have greater than what we want. We have it. */
- if (*lib_version > *wnt_version) {
- return 0;
- }
- /* If we have less, we don't. */
- if (*lib_version < *wnt_version) {
- return 1;
- }
- lib_version++;
- wnt_version++;
- }
- return 0;
-}
-],[
-success=yes
-])
-
-# Restore flags.
-CPPFLAGS="$CPPFLAGS_SAVED"
-LDFLAGS="$LDFLAGS_SAVED"
-LIBS="$LIBS_SAVED"
-LD_LIBRARY_PATH="$LD_LIBRARY_PATH_SAVED"
-])
-
-AC_DEFUN([AC_LIB_EVENT],
-[
-
-PHP_ARG_WITH(libevent-dir,,
-[ --with-libevent-dir[=PATH] libevent install prefix, for fpm SAPI. (default: /usr/local)], /usr/local, yes)
-
-if test "$PHP_LIBEVENT_DIR" != "no"; then
- WANT_LIBEVENT_VERSION=ifelse([$1], ,1.2,$1)
-
- AC_MSG_CHECKING(for libevent >= $WANT_LIBEVENT_VERSION install prefix)
-
- libevent_prefix=$ac_default_prefix
- if test $prefix != "NONE" -a $prefix != "" -a $prefix != "no" ; then
- libevent_prefix=$prefix
- fi
-
- if test "$PHP_LIBEVENT_DIR" = "yes"; then
- PHP_LIBEVENT_DIR=$libevent_prefix
- fi
-
- if test "$PHP_LIBEVENT_DIR" != "yes" && test "$PHP_LIBEVENT_DIR" != "/usr/local"; then
- dnl don't try to be too smart, check only $PHP_LIBEVENT_DIR if specified
- ac_libevent_path=$PHP_LIBEVENT_DIR
- AC_LIB_EVENT_DO_CHECK
- if test "$success" = "no"; then
- AC_MSG_ERROR([Could not find libevent >= $WANT_LIBEVENT_VERSION in $PHP_LIBEVENT_DIR])
- fi
- else
- dnl check default prefixes then
- for ac_libevent_path in "" $PHP_LIBEVENT_DIR /usr /usr/local /opt /opt/local /opt/libevent ; do
- AC_LIB_EVENT_DO_CHECK
- if test "$success" = "yes"; then
- break;
- fi
- done
- fi
-
- if test "$success" != "yes" ; then
- AC_MSG_RESULT(no)
- ac_have_libevent=no
- AC_MSG_ERROR([libevent >= $WANT_LIBEVENT_VERSION could not be found])
- else
- AC_MSG_RESULT($ac_libevent_path)
- ac_have_libevent=yes
- AC_DEFINE(HAVE_LIBEVENT, 1, [define if libevent is available])
- fi
-
- LIBEVENT_LIBS="-levent"
-
- if test -n "$ac_libevent_path"; then
- LIBEVENT_CFLAGS="-I$ac_libevent_path/include"
- LIBEVENT_LIBS="-L$ac_libevent_path/$PHP_LIBDIR $LIBEVENT_LIBS"
- LIBEVENT_PATH="$ac_libevent_path/$PHP_LIBDIR"
- fi
-
- AC_SUBST(LIBEVENT_CFLAGS)
- AC_SUBST(LIBEVENT_LIBS)
- AC_SUBST(LIBEVENT_PATH)
-
-else
- AC_MSG_ERROR([FPM requires libevent >= $WANT_LIBEVENT_VERSION. Please specify libevent install prefix with --with-libevent-dir=yes])
-fi
-
-])
-dnl }}}
-
dnl configure checks {{{
AC_DEFUN([AC_FPM_STDLIBS],
[
- AC_CHECK_FUNCS(setenv clearenv)
+ AC_CHECK_FUNCS(setenv clearenv setproctitle)
AC_SEARCH_LIBS(socket, socket)
AC_SEARCH_LIBS(inet_addr, nsl)
@@ -499,25 +287,69 @@ AC_DEFUN([AC_FPM_TRACE],
fi
])
+
+AC_DEFUN([AC_FPM_BUILTIN_ATOMIC],
+[
+ AC_MSG_CHECKING([if gcc supports __sync_bool_compare_and_swap])
+ AC_TRY_LINK(,
+ [
+ int variable = 1;
+ return (__sync_bool_compare_and_swap(&variable, 1, 2)
+ && __sync_add_and_fetch(&variable, 1)) ? 1 : 0;
+ ],
+ [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(HAVE_BUILTIN_ATOMIC, 1, [Define to 1 if gcc supports __sync_bool_compare_and_swap() a.o.])
+ ],
+ [
+ AC_MSG_RESULT([no])
+ ])
+])
+
+AC_DEFUN([AC_FPM_LQ],
+[
+ have_lq=no
+
+ AC_MSG_CHECKING([for TCP_INFO])
+
+ AC_TRY_COMPILE([ #include <netinet/tcp.h> ], [struct tcp_info ti; int x = TCP_INFO;], [
+ have_lq=tcp_info
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+
+ if test "$have_lq" = "tcp_info"; then
+ AC_DEFINE([HAVE_LQ_TCP_INFO], 1, [do we have TCP_INFO?])
+ fi
+
+ if test "$have_lq" = "no" ; then
+ AC_MSG_CHECKING([for SO_LISTENQLEN])
+
+ AC_TRY_COMPILE([ #include <sys/socket.h> ], [int x = SO_LISTENQLIMIT; int y = SO_LISTENQLEN;], [
+ have_lq=so_listenq
+ AC_MSG_RESULT([yes])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+
+ if test "$have_lq" = "tcp_info"; then
+ AC_DEFINE([HAVE_LQ_SO_LISTENQ], 1, [do we have SO_LISTENQxxx?])
+ fi
+ fi
+])
dnl }}}
AC_MSG_CHECKING(for FPM build)
if test "$PHP_FPM" != "no"; then
AC_MSG_RESULT($PHP_FPM)
- AC_LIB_EVENT([$minimum_libevent_version])
-
- PHP_ADD_LIBRARY_WITH_PATH(event, $LIBEVENT_PATH)
-
- PHP_TEST_BUILD(event_init, [ ], [
- AC_MSG_RESULT(no)
- AC_MSG_ERROR([build test failed. Please check the config.log for details.])
- ], $LIBEVENT_LIBS)
-
AC_FPM_STDLIBS
AC_FPM_PRCTL
AC_FPM_CLOCK
AC_FPM_TRACE
+ AC_FPM_BUILTIN_ATOMIC
+ AC_FPM_LQ
PHP_ARG_WITH(fpm-user,,
[ --with-fpm-user[=USER] Set the user for php-fpm to run as. (default: nobody)], nobody, no)
@@ -538,19 +370,19 @@ if test "$PHP_FPM" != "no"; then
php_fpm_group="$PHP_FPM_GROUP"
fi
- PHP_SUBST_OLD(fpm_version)
PHP_SUBST_OLD(php_fpm_user)
PHP_SUBST_OLD(php_fpm_group)
php_fpm_sysconfdir=`eval echo $sysconfdir`
PHP_SUBST_OLD(php_fpm_sysconfdir)
php_fpm_localstatedir=`eval echo $localstatedir`
PHP_SUBST_OLD(php_fpm_localstatedir)
+ php_fpm_prefix=`eval echo $prefix`
+ PHP_SUBST_OLD(php_fpm_prefix)
- AC_DEFINE_UNQUOTED(PHP_FPM_VERSION, "$fpm_version", [fpm version])
AC_DEFINE_UNQUOTED(PHP_FPM_USER, "$php_fpm_user", [fpm user name])
AC_DEFINE_UNQUOTED(PHP_FPM_GROUP, "$php_fpm_group", [fpm group name])
- PHP_OUTPUT(sapi/fpm/php-fpm.conf sapi/fpm/init.d.php-fpm sapi/fpm/php-fpm.1)
+ PHP_OUTPUT(sapi/fpm/php-fpm.conf sapi/fpm/init.d.php-fpm sapi/fpm/php-fpm.8)
PHP_ADD_MAKEFILE_FRAGMENT([$abs_srcdir/sapi/fpm/Makefile.frag], [$abs_srcdir/sapi/fpm], [sapi/fpm])
SAPI_FPM_PATH=sapi/fpm/php-fpm
@@ -560,10 +392,7 @@ if test "$PHP_FPM" != "no"; then
PHP_FPM_TRACE_FILES="fpm/fpm_trace.c fpm/fpm_trace_$fpm_trace_type.c"
fi
- PHP_FPM_CFLAGS="$LIBEVENT_CFLAGS -I$abs_srcdir/sapi/fpm"
-
- SAPI_EXTRA_LIBS="$LIBEVENT_LIBS"
- PHP_SUBST(SAPI_EXTRA_LIBS)
+ PHP_FPM_CFLAGS="-I$abs_srcdir/sapi/fpm"
INSTALL_IT=":"
PHP_FPM_FILES="fpm/fastcgi.c \
diff --git a/sapi/fpm/fpm/fpm.c b/sapi/fpm/fpm/fpm.c
index 34292b5d4..17a215c88 100644
--- a/sapi/fpm/fpm/fpm.c
+++ b/sapi/fpm/fpm/fpm.c
@@ -23,23 +23,26 @@
struct fpm_globals_s fpm_globals;
-int fpm_init(int argc, char **argv, char *config, struct event_base **base) /* {{{ */
+int fpm_init(int argc, char **argv, char *config, char *prefix, int test_conf) /* {{{ */
{
fpm_globals.argc = argc;
fpm_globals.argv = argv;
- fpm_globals.config = config;
+ if (config && *config) {
+ fpm_globals.config = strdup(config);
+ }
+ fpm_globals.prefix = prefix;
- if (0 > fpm_php_init_main() ||
+ if (0 > fpm_php_init_main() ||
0 > fpm_stdio_init_main() ||
- 0 > fpm_conf_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_pctl_init_main() ||
0 > fpm_children_init_main() ||
0 > fpm_sockets_init_main() ||
0 > fpm_worker_pool_init_main() ||
- 0 > fpm_event_init_main(base)) {
+ 0 > fpm_event_init_main()) {
return -1;
}
@@ -47,7 +50,8 @@ int fpm_init(int argc, char **argv, char *config, struct event_base **base) /* {
return -1;
}
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "fpm is running, pid %d", (int) fpm_globals.parent_pid);
+ fpm_stdio_init_final();
+ zlog(ZLOG_NOTICE, "fpm is running, pid %d", (int) fpm_globals.parent_pid);
return 0;
}
@@ -55,7 +59,7 @@ int fpm_init(int argc, char **argv, char *config, struct event_base **base) /* {
/* children: return listening socket
parent: never return */
-int fpm_run(int *max_requests, struct event_base *base) /* {{{ */
+int fpm_run(int *max_requests) /* {{{ */
{
struct fpm_worker_pool_s *wp;
@@ -63,7 +67,7 @@ int fpm_run(int *max_requests, struct event_base *base) /* {{{ */
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
int is_parent;
- is_parent = fpm_children_create_initial(wp, base);
+ is_parent = fpm_children_create_initial(wp);
if (!is_parent) {
goto run_child;
@@ -71,7 +75,7 @@ int fpm_run(int *max_requests, struct event_base *base) /* {{{ */
}
/* run event loop forever */
- fpm_event_loop(base);
+ fpm_event_loop();
run_child: /* only workers reach this point */
diff --git a/sapi/fpm/fpm/fpm.h b/sapi/fpm/fpm/fpm.h
index ba4390448..63e3bacca 100644
--- a/sapi/fpm/fpm/fpm.h
+++ b/sapi/fpm/fpm/fpm.h
@@ -6,17 +6,16 @@
#define FPM_H 1
#include <unistd.h>
-#include <sys/types.h> /* for event.h below */
-#include <event.h>
-int fpm_run(int *max_requests, struct event_base *base);
-int fpm_init(int argc, char **argv, char *config, struct event_base **base);
+int fpm_run(int *max_requests);
+int fpm_init(int argc, char **argv, char *config, char *prefix, int test_conf);
struct fpm_globals_s {
pid_t parent_pid;
int argc;
char **argv;
char *config;
+ char *prefix;
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 8c287ddfb..638bafddc 100644
--- a/sapi/fpm/fpm/fpm_atomic.h
+++ b/sapi/fpm/fpm/fpm_atomic.h
@@ -12,7 +12,19 @@
#endif
#include <sched.h>
-#if ( __i386__ || __i386 )
+#ifdef HAVE_BUILTIN_ATOMIC
+
+/**
+ * all the cases below (as provided by upstream) define:
+ * word as atomic_int_t, and
+ * unsigned word as atomic_uint_t
+ * and only use volatile atomic_uint_t as atomic_t
+ */
+
+typedef volatile unsigned long atomic_t;
+#define atomic_cmp_set(a,b,c) __sync_bool_compare_and_swap(a,b,c)
+
+#elif ( __i386__ || __i386 )
typedef int32_t atomic_int_t;
typedef uint32_t atomic_uint_t;
@@ -83,6 +95,8 @@ typedef uint32_t atomic_uint_t;
#elif ( __sparc__ || __sparc ) /* Marcin Ochab */
+#if (__sparcv9 || __sparcv9__)
+
#if (__arch64__ || __arch64)
typedef uint64_t atomic_uint_t;
typedef volatile atomic_uint_t atomic_t;
@@ -119,9 +133,13 @@ static inline atomic_uint_t atomic_cmp_set(atomic_t *lock, atomic_uint_t old, at
/* }}} */
#endif
+#else /* #if (__sparcv9 || __sparcv9__) */
+#error Sparc v8 and predecessors are not and will not be supported (see bug report 53310)
+#endif /* #if (__sparcv9 || __sparcv9__) */
+
#else
-#error unsupported processor. please write a patch and send it to me
+#error Unsupported processor. Please open a bug report (bugs.php.net).
#endif
diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c
index d303cfb03..499ad08e8 100644
--- a/sapi/fpm/fpm/fpm_children.c
+++ b/sapi/fpm/fpm/fpm_children.c
@@ -152,7 +152,7 @@ static void fpm_child_init(struct fpm_worker_pool_s *wp) /* {{{ */
0 > fpm_env_init_child(wp) ||
0 > fpm_php_init_child(wp)) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] child failed to initialize", wp->config->name);
+ zlog(ZLOG_ERROR, "[pool %s] child failed to initialize", wp->config->name);
exit(255);
}
}
@@ -171,7 +171,7 @@ int fpm_children_free(struct fpm_child_s *child) /* {{{ */
}
/* }}} */
-void fpm_children_bury(struct event_base *base) /* {{{ */
+void fpm_children_bury() /* {{{ */
{
int status;
pid_t pid;
@@ -201,18 +201,18 @@ void fpm_children_bury(struct event_base *base) /* {{{ */
} else if (WIFSIGNALED(status)) {
const char *signame = fpm_signal_names[WTERMSIG(status)];
- const char *have_core = WCOREDUMP(status) ? " (core dumped)" : "";
+ const char *have_core = WCOREDUMP(status) ? " - core dumped" : "";
if (signame == NULL) {
signame = "";
}
- snprintf(buf, sizeof(buf), "on signal %d %s%s", WTERMSIG(status), signame, have_core);
+ snprintf(buf, sizeof(buf), "on signal %d (%s%s)", WTERMSIG(status), signame, have_core);
/* if it's been killed because of dynamic process management
* don't restart it automaticaly
*/
- if (child && child->idle_kill && WTERMSIG(status) == SIGTERM) {
+ if (child && child->idle_kill && WTERMSIG(status) == SIGQUIT) {
restart_child = 0;
}
@@ -221,7 +221,7 @@ void fpm_children_bury(struct event_base *base) /* {{{ */
}
} else if (WIFSTOPPED(status)) {
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "child %d stopped for tracing", (int) pid);
+ zlog(ZLOG_NOTICE, "child %d stopped for tracing", (int) pid);
if (child && child->tracer) {
child->tracer(child);
@@ -246,9 +246,9 @@ void fpm_children_bury(struct event_base *base) /* {{{ */
if (!fpm_pctl_can_spawn_children()) {
severity = ZLOG_DEBUG;
}
- zlog(ZLOG_STUFF, severity, "[pool %s] child %d exited %s after %ld.%06d seconds from start", child->wp->config->name, (int) pid, buf, tv2.tv_sec, (int) tv2.tv_usec);
+ zlog(severity, "[pool %s] child %d exited %s after %ld.%06d seconds from start", child->wp->config->name, (int) pid, buf, tv2.tv_sec, (int) tv2.tv_usec);
} else {
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "[pool %s] child %d has been killed by the process managment after %ld.%06d seconds from start", child->wp->config->name, (int) pid, tv2.tv_sec, (int) tv2.tv_usec);
+ zlog(ZLOG_DEBUG, "[pool %s] child %d has been killed by the process managment after %ld.%06d seconds from start", child->wp->config->name, (int) pid, tv2.tv_sec, (int) tv2.tv_usec);
}
fpm_child_close(child, 1 /* in event_loop */);
@@ -275,21 +275,21 @@ void fpm_children_bury(struct event_base *base) /* {{{ */
if (restart_condition) {
- zlog(ZLOG_STUFF, ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload", fpm_global_config.emergency_restart_threshold, fpm_global_config.emergency_restart_interval);
+ zlog(ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload", fpm_global_config.emergency_restart_threshold, fpm_global_config.emergency_restart_interval);
- fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET, base);
+ fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET);
}
}
if (restart_child) {
- fpm_children_make(wp, 1 /* in event loop */, 1, 0, base);
+ fpm_children_make(wp, 1 /* in event loop */, 1, 0);
if (fpm_globals.is_child) {
break;
}
}
} else {
- zlog(ZLOG_STUFF, ZLOG_ALERT, "oops, unknown child exited %s", buf);
+ zlog(ZLOG_ALERT, "oops, unknown child (%d) exited %s", pid, buf);
}
}
}
@@ -302,7 +302,7 @@ static struct fpm_child_s *fpm_resources_prepare(struct fpm_worker_pool_s *wp) /
c = fpm_child_alloc();
if (!c) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] malloc failed", wp->config->name);
+ zlog(ZLOG_ERROR, "[pool %s] malloc failed", wp->config->name);
return 0;
}
@@ -340,15 +340,15 @@ static void fpm_child_resources_use(struct fpm_child_s *child) /* {{{ */
}
/* }}} */
-static void fpm_parent_resources_use(struct fpm_child_s *child, struct event_base *base) /* {{{ */
+static void fpm_parent_resources_use(struct fpm_child_s *child) /* {{{ */
{
fpm_shm_slots_parent_use_slot(child);
- fpm_stdio_parent_use_pipes(child, base);
+ fpm_stdio_parent_use_pipes(child);
fpm_child_link(child);
}
/* }}} */
-int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to_spawn, int is_debug, struct event_base *base) /* {{{ */
+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;
@@ -378,17 +378,13 @@ int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to
switch (pid) {
case 0 :
- event_reinit(base); /* reinitialize event base after fork() */
fpm_child_resources_use(child);
fpm_globals.is_child = 1;
- if (in_event_loop) {
- fpm_event_exit_loop(base);
- }
fpm_child_init(wp);
return 0;
case -1 :
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fork() failed");
+ zlog(ZLOG_SYSERROR, "fork() failed");
enough = 1;
fpm_resources_discard(child);
@@ -398,9 +394,9 @@ int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to
default :
child->pid = pid;
fpm_clock_get(&child->started);
- fpm_parent_resources_use(child, base);
+ fpm_parent_resources_use(child);
- zlog(ZLOG_STUFF, is_debug ? ZLOG_DEBUG : ZLOG_NOTICE, "[pool %s] child %d started", wp->config->name, (int) pid);
+ zlog(is_debug ? ZLOG_DEBUG : ZLOG_NOTICE, "[pool %s] child %d started", wp->config->name, (int) pid);
}
}
@@ -409,9 +405,9 @@ int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to
}
/* }}} */
-int fpm_children_create_initial(struct fpm_worker_pool_s *wp, struct event_base *base) /* {{{ */
+int fpm_children_create_initial(struct fpm_worker_pool_s *wp) /* {{{ */
{
- return fpm_children_make(wp, 0 /* not in event loop yet */, 0, 1, base);
+ return fpm_children_make(wp, 0 /* not in event loop yet */, 0, 1);
}
/* }}} */
diff --git a/sapi/fpm/fpm/fpm_children.h b/sapi/fpm/fpm/fpm_children.h
index d88184269..4010a4f3b 100644
--- a/sapi/fpm/fpm/fpm_children.h
+++ b/sapi/fpm/fpm/fpm_children.h
@@ -7,15 +7,15 @@
#include <sys/time.h>
#include <sys/types.h>
-#include <event.h>
#include "fpm_worker_pool.h"
+#include "fpm_events.h"
-int fpm_children_create_initial(struct fpm_worker_pool_s *wp, struct event_base *base);
+int fpm_children_create_initial(struct fpm_worker_pool_s *wp);
int fpm_children_free(struct fpm_child_s *child);
-void fpm_children_bury(struct event_base *base);
+void fpm_children_bury();
int fpm_children_init_main();
-int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to_spawn, int is_debug, struct event_base *base);
+int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to_spawn, int is_debug);
struct fpm_child_s;
@@ -23,7 +23,7 @@ struct fpm_child_s {
struct fpm_child_s *prev, *next;
struct timeval started;
struct fpm_worker_pool_s *wp;
- struct event ev_stdout, ev_stderr;
+ struct fpm_event_s ev_stdout, ev_stderr;
int shm_slot_i;
int fd_stdout, fd_stderr;
void (*tracer)(struct fpm_child_s *);
diff --git a/sapi/fpm/fpm/fpm_clock.c b/sapi/fpm/fpm/fpm_clock.c
index 3eb515943..66751b81b 100644
--- a/sapi/fpm/fpm/fpm_clock.c
+++ b/sapi/fpm/fpm/fpm_clock.c
@@ -37,7 +37,7 @@ int fpm_clock_get(struct timeval *tv) /* {{{ */
struct timespec ts;
if (0 > clock_gettime(CLOCK_MONOTONIC, &ts)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "clock_gettime() failed");
+ zlog(ZLOG_SYSERROR, "clock_gettime() failed");
return -1;
}
@@ -69,7 +69,7 @@ int fpm_clock_init() /* {{{ */
ret = host_get_clock_service(mach_host_self(), REALTIME_CLOCK, &mach_clock);
if (ret != KERN_SUCCESS) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "host_get_clock_service() failed: %s", mach_error_string(ret));
+ zlog(ZLOG_ERROR, "host_get_clock_service() failed: %s", mach_error_string(ret));
return -1;
}
@@ -77,7 +77,7 @@ int fpm_clock_init() /* {{{ */
ret = clock_get_time(mach_clock, &aTime);
if (ret != KERN_SUCCESS) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret));
+ zlog(ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret));
return -1;
}
@@ -93,7 +93,7 @@ int fpm_clock_get(struct timeval *tv) /* {{{ */
ret = clock_get_time(mach_clock, &aTime);
if (ret != KERN_SUCCESS) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret));
+ zlog(ZLOG_ERROR, "clock_get_time() failed: %s", mach_error_string(ret));
return -1;
}
diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c
index 4590155c7..f38227c2f 100644
--- a/sapi/fpm/fpm/fpm_conf.c
+++ b/sapi/fpm/fpm/fpm_conf.c
@@ -52,50 +52,54 @@ static char *fpm_conf_set_log_level(zval *value, void **config, intptr_t offset)
static char *fpm_conf_set_rlimit_core(zval *value, void **config, intptr_t offset);
static char *fpm_conf_set_pm(zval *value, void **config, intptr_t offset);
-struct fpm_global_config_s fpm_global_config = { 0, 0, 0, 1, NULL, NULL};
+struct fpm_global_config_s fpm_global_config = { .daemonize = 1 };
static struct fpm_worker_pool_s *current_wp = NULL;
static int ini_recursion = 0;
static char *ini_filename = NULL;
static int ini_lineno = 0;
static char *ini_include = NULL;
+#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, offsetof(struct fpm_global_config_s, emergency_restart_threshold) },
- { "emergency_restart_interval", &fpm_conf_set_time, offsetof(struct fpm_global_config_s, emergency_restart_interval) },
- { "process_control_timeout", &fpm_conf_set_time, offsetof(struct fpm_global_config_s, process_control_timeout) },
- { "daemonize", &fpm_conf_set_boolean, offsetof(struct fpm_global_config_s, daemonize) },
- { "pid", &fpm_conf_set_string, offsetof(struct fpm_global_config_s, pid_file) },
- { "error_log", &fpm_conf_set_string, offsetof(struct fpm_global_config_s, error_log) },
+ { "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 },
{ 0, 0, 0 }
};
static struct ini_value_parser_s ini_fpm_pool_options[] = {
- { "user", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, user) },
- { "group", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, group) },
- { "chroot", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, chroot) },
- { "chdir", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, chdir) },
- { "request_terminate_timeout", &fpm_conf_set_time, offsetof(struct fpm_worker_pool_config_s, request_terminate_timeout) },
- { "request_slowlog_timeout", &fpm_conf_set_time, offsetof(struct fpm_worker_pool_config_s, request_slowlog_timeout) },
- { "slowlog", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, slowlog) },
- { "rlimit_files", &fpm_conf_set_integer, offsetof(struct fpm_worker_pool_config_s, rlimit_files) },
- { "rlimit_core", &fpm_conf_set_rlimit_core, offsetof(struct fpm_worker_pool_config_s, rlimit_core) },
- { "catch_workers_output", &fpm_conf_set_boolean, offsetof(struct fpm_worker_pool_config_s, catch_workers_output) },
- { "listen", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, listen_address) },
- { "listen.owner", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, listen_owner) },
- { "listen.group", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, listen_group) },
- { "listen.mode", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, listen_mode) },
- { "listen.backlog", &fpm_conf_set_integer, offsetof(struct fpm_worker_pool_config_s, listen_backlog) },
- { "listen.allowed_clients", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, listen_allowed_clients) },
- { "pm", &fpm_conf_set_pm, offsetof(struct fpm_worker_pool_config_s, pm) },
- { "pm.max_requests", &fpm_conf_set_integer, offsetof(struct fpm_worker_pool_config_s, pm_max_requests) },
- { "pm.max_children", &fpm_conf_set_integer, offsetof(struct fpm_worker_pool_config_s, pm_max_children) },
- { "pm.start_servers", &fpm_conf_set_integer, offsetof(struct fpm_worker_pool_config_s, pm_start_servers) },
- { "pm.min_spare_servers", &fpm_conf_set_integer, offsetof(struct fpm_worker_pool_config_s, pm_min_spare_servers) },
- { "pm.max_spare_servers", &fpm_conf_set_integer, offsetof(struct fpm_worker_pool_config_s, pm_max_spare_servers) },
- { "pm.status_path", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, pm_status_path) },
- { "ping.path", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, ping_path) },
- { "ping.response", &fpm_conf_set_string, offsetof(struct fpm_worker_pool_config_s, 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) },
{ 0, 0, 0 }
};
@@ -111,11 +115,34 @@ static int fpm_conf_is_dir(char *path) /* {{{ */
}
/* }}} */
+static int fpm_conf_expand_pool_name(char **value) {
+ char *token;
+
+ if (!value || !*value) {
+ return 0;
+ }
+
+ while ((token = strstr(*value, "$pool"))) {
+ char *buf;
+ char *p1 = *value;
+ char *p2 = token + strlen("$pool");
+ if (!current_wp || !current_wp->config || !current_wp->config->name) {
+ return -1;
+ }
+ token[0] = '\0';
+ spprintf(&buf, 0, "%s%s%s", p1, current_wp->config->name, p2);
+ *value = strdup(buf);
+ efree(buf);
+ }
+
+ return 0;
+}
+
static char *fpm_conf_set_boolean(zval *value, void **config, intptr_t offset) /* {{{ */
{
char *val = Z_STRVAL_P(value);
- long value_y = !strcasecmp(val, "yes") || !strcmp(val, "1") || !strcasecmp(val, "on") || !strcasecmp(val, "true");
- long value_n = !strcasecmp(val, "no") || !strcmp(val, "0") || !strcasecmp(val, "off") || !strcasecmp(val, "false");
+ long value_y = !strcasecmp(val, "1");
+ long value_n = !strcasecmp(val, "");
if (!value_y && !value_n) {
return "invalid boolean value";
@@ -138,6 +165,9 @@ static char *fpm_conf_set_string(zval *value, void **config, intptr_t offset) /*
if (!new) {
return "fpm_conf_set_string(): strdup() failed";
}
+ if (fpm_conf_expand_pool_name(&new) == -1) {
+ return "Can't use '$pool' when the pool is not defined";
+ }
*old = new;
return NULL;
@@ -146,17 +176,17 @@ static char *fpm_conf_set_string(zval *value, void **config, intptr_t offset) /*
static char *fpm_conf_set_integer(zval *value, void **config, intptr_t offset) /* {{{ */
{
- int i;
char *val = Z_STRVAL_P(value);
+ char *p;
- for (i=0; i<strlen(val); i++) {
- if ( i == 0 && val[i] == '-' ) continue;
- if (val[i] < '0' || val[i] > '9') {
- return("is not a valid number (greater or equal than zero");
+ 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)";
}
}
* (int *) ((char *) *config + offset) = atoi(val);
- return(NULL);
+ return NULL;
}
/* }}} */
@@ -204,7 +234,7 @@ static char *fpm_conf_set_log_level(zval *value, void **config, intptr_t offset)
{
char *val = Z_STRVAL_P(value);
- if (!strcmp(val, "debug")) {
+ if (!strcasecmp(val, "debug")) {
fpm_globals.log_level = ZLOG_DEBUG;
} else if (!strcasecmp(val, "notice")) {
fpm_globals.log_level = ZLOG_NOTICE;
@@ -227,7 +257,7 @@ static char *fpm_conf_set_rlimit_core(zval *value, void **config, intptr_t offse
char *val = Z_STRVAL_P(value);
struct fpm_worker_pool_config_s *c = *config;
- if (!strcmp(val, "unlimited")) {
+ if (!strcasecmp(val, "unlimited")) {
c->rlimit_core = -1;
} else {
int int_value;
@@ -255,9 +285,9 @@ static char *fpm_conf_set_pm(zval *value, void **config, intptr_t offset) /* {{{
{
char *val = Z_STRVAL_P(value);
struct fpm_worker_pool_config_s *c = *config;
- if (!strcmp(val, "static")) {
+ if (!strcasecmp(val, "static")) {
c->pm = PM_STYLE_STATIC;
- } else if (!strcmp(val, "dynamic")) {
+ } else if (!strcasecmp(val, "dynamic")) {
c->pm = PM_STYLE_DYNAMIC;
} else {
return "invalid process manager (static or dynamic)";
@@ -288,10 +318,13 @@ static char *fpm_conf_set_array(zval *key, zval *value, void **config, int conve
if (convert_to_bool) {
char *err = fpm_conf_set_boolean(value, &subconf, 0);
- if (err) return(err);
+ if (err) return err;
kv->value = strdup(b ? "On" : "Off");
} else {
kv->value = strdup(Z_STRVAL_P(value));
+ if (fpm_conf_expand_pool_name(&kv->value) == -1) {
+ return "Can't use '$pool' when the pool is not defined";
+ }
}
if (!kv->value) {
@@ -322,7 +355,7 @@ static void *fpm_worker_pool_config_alloc() /* {{{ */
}
memset(wp->config, 0, sizeof(struct fpm_worker_pool_config_s));
- wp->config->listen_backlog = -1;
+ wp->config->listen_backlog = FPM_BACKLOG_DEFAULT;
if (!fpm_worker_all_pools) {
fpm_worker_all_pools = wp;
@@ -378,27 +411,68 @@ int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc) /* {{{ */
free(wpc->chroot);
free(wpc->chdir);
free(wpc->slowlog);
+ free(wpc->prefix);
return 0;
}
/* }}} */
-static int fpm_evaluate_full_path(char **path) /* {{{ */
+static int fpm_evaluate_full_path(char **path, struct fpm_worker_pool_s *wp, char *default_prefix, int expand) /* {{{ */
{
- if (**path != '/') {
- char *full_path;
+ char *prefix = NULL;
+ char *full_path;
- full_path = malloc(sizeof(PHP_PREFIX) + strlen(*path) + 1);
+ if (!path || !*path || **path == '/') {
+ return 0;
+ }
- if (!full_path) {
- return -1;
+ if (wp && wp->config) {
+ prefix = wp->config->prefix;
+ }
+
+ /* if the wp prefix is not set */
+ if (prefix == NULL) {
+ prefix = fpm_globals.prefix;
+ }
+
+ /* if the global prefix is not set */
+ if (prefix == NULL) {
+ prefix = default_prefix ? default_prefix : PHP_PREFIX;
+ }
+
+ if (expand) {
+ char *tmp;
+ tmp = strstr(*path, "$prefix");
+ if (tmp != NULL) {
+
+ if (tmp != *path) {
+ zlog(ZLOG_ERROR, "'$prefix' must be use at the begining of the value");
+ return -1;
+ }
+
+ if (strlen(*path) > strlen("$prefix")) {
+ free(*path);
+ tmp = strdup((*path) + strlen("$prefix"));
+ *path = tmp;
+ } else {
+ free(*path);
+ *path = NULL;
+ }
}
+ }
- sprintf(full_path, "%s/%s", PHP_PREFIX, *path);
+ if (*path) {
+ spprintf(&full_path, 0, "%s/%s", prefix, *path);
free(*path);
- *path = full_path;
+ *path = strdup(full_path);
+ efree(full_path);
+ } else {
+ *path = strdup(prefix);
}
+ if (**path != '/' && wp != NULL && wp->config) {
+ return fpm_evaluate_full_path(path, NULL, default_prefix, expand);
+ }
return 0;
}
/* }}} */
@@ -408,35 +482,44 @@ static int fpm_conf_process_all_pools() /* {{{ */
struct fpm_worker_pool_s *wp;
if (!fpm_worker_all_pools) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "at least one pool section must be specified in config file");
+ zlog(ZLOG_ERROR, "at least one pool section must be specified in config file");
return -1;
}
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
+ if (wp->config->prefix && *wp->config->prefix) {
+ fpm_evaluate_full_path(&wp->config->prefix, NULL, NULL, 0);
+
+ if (!fpm_conf_is_dir(wp->config->prefix)) {
+ zlog(ZLOG_ERROR, "[pool %s] the prefix '%s' does not exist or is not a directory", wp->config->name, wp->config->prefix);
+ return -1;
+ }
+ }
+
if (wp->config->listen_address && *wp->config->listen_address) {
wp->listen_address_domain = fpm_sockets_domain_from_address(wp->config->listen_address);
if (wp->listen_address_domain == FPM_AF_UNIX && *wp->config->listen_address != '/') {
- fpm_evaluate_full_path(&wp->config->listen_address);
+ fpm_evaluate_full_path(&wp->config->listen_address, wp, NULL, 0);
}
} else {
- zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] no listen address have been defined!", wp->config->name);
+ zlog(ZLOG_ALERT, "[pool %s] no listen address have been defined!", wp->config->name);
return -1;
}
if (!wp->config->user) {
- zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] user has not been defined", wp->config->name);
+ zlog(ZLOG_ALERT, "[pool %s] user has not been defined", wp->config->name);
return -1;
}
if (wp->config->pm != PM_STYLE_STATIC && wp->config->pm != PM_STYLE_DYNAMIC) {
- zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] the process manager is missing (static or dynamic)", wp->config->name);
+ zlog(ZLOG_ALERT, "[pool %s] the process manager is missing (static or dynamic)", wp->config->name);
return -1;
}
if (wp->config->pm_max_children < 1) {
- zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] pm.max_children must be a positive value", wp->config->name);
+ zlog(ZLOG_ALERT, "[pool %s] pm.max_children must be a positive value", wp->config->name);
return -1;
}
@@ -444,66 +527,65 @@ static int fpm_conf_process_all_pools() /* {{{ */
struct fpm_worker_pool_config_s *config = wp->config;
if (config->pm_min_spare_servers <= 0) {
- zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] pm.min_spare_servers(%d) must be a positive value", wp->config->name, config->pm_min_spare_servers);
+ zlog(ZLOG_ALERT, "[pool %s] pm.min_spare_servers(%d) must be a positive value", wp->config->name, config->pm_min_spare_servers);
return -1;
}
if (config->pm_max_spare_servers <= 0) {
- zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] pm.max_spare_servers(%d) must be a positive value", wp->config->name, config->pm_max_spare_servers);
+ zlog(ZLOG_ALERT, "[pool %s] pm.max_spare_servers(%d) must be a positive value", wp->config->name, config->pm_max_spare_servers);
return -1;
}
if (config->pm_min_spare_servers > config->pm_max_children ||
config->pm_max_spare_servers > config->pm_max_children) {
- zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] pm.min_spare_servers(%d) and pm.max_spare_servers(%d) cannot be greater than pm.max_children(%d)",
+ zlog(ZLOG_ALERT, "[pool %s] pm.min_spare_servers(%d) and pm.max_spare_servers(%d) cannot be greater than pm.max_children(%d)",
wp->config->name, config->pm_min_spare_servers, config->pm_max_spare_servers, config->pm_max_children);
return -1;
}
if (config->pm_max_spare_servers < config->pm_min_spare_servers) {
- zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] pm.max_spare_servers(%d) must not be less than pm.min_spare_servers(%d)", wp->config->name, config->pm_max_spare_servers, config->pm_min_spare_servers);
+ zlog(ZLOG_ALERT, "[pool %s] pm.max_spare_servers(%d) must not be less than pm.min_spare_servers(%d)", wp->config->name, config->pm_max_spare_servers, config->pm_min_spare_servers);
return -1;
}
if (config->pm_start_servers <= 0) {
config->pm_start_servers = config->pm_min_spare_servers + ((config->pm_max_spare_servers - config->pm_min_spare_servers) / 2);
- zlog(ZLOG_STUFF, ZLOG_WARNING, "[pool %s] pm.start_servers is not set. It's been set to %d.", wp->config->name, config->pm_start_servers);
+ zlog(ZLOG_WARNING, "[pool %s] pm.start_servers is not set. It's been set to %d.", wp->config->name, config->pm_start_servers);
} else if (config->pm_start_servers < config->pm_min_spare_servers || config->pm_start_servers > config->pm_max_spare_servers) {
- zlog(ZLOG_STUFF, ZLOG_ALERT, "[pool %s] pm.start_servers(%d) must not be less than pm.min_spare_servers(%d) and not greater than pm.max_spare_servers(%d)", wp->config->name, config->pm_start_servers, config->pm_min_spare_servers, config->pm_max_spare_servers);
+ zlog(ZLOG_ALERT, "[pool %s] pm.start_servers(%d) must not be less than pm.min_spare_servers(%d) and not greater than pm.max_spare_servers(%d)", wp->config->name, config->pm_start_servers, config->pm_min_spare_servers, config->pm_max_spare_servers);
return -1;
}
}
+ if (wp->config->slowlog && *wp->config->slowlog) {
+ fpm_evaluate_full_path(&wp->config->slowlog, wp, NULL, 0);
+ }
if (wp->config->request_slowlog_timeout) {
#if HAVE_FPM_TRACE
if (! (wp->config->slowlog && *wp->config->slowlog)) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] 'slowlog' must be specified for use with 'request_slowlog_timeout'", wp->config->name);
+ zlog(ZLOG_ERROR, "[pool %s] 'slowlog' must be specified for use with 'request_slowlog_timeout'", wp->config->name);
return -1;
}
#else
static int warned = 0;
if (!warned) {
- zlog(ZLOG_STUFF, ZLOG_WARNING, "[pool %s] 'request_slowlog_timeout' is not supported on your system", wp->config->name);
+ zlog(ZLOG_WARNING, "[pool %s] 'request_slowlog_timeout' is not supported on your system", wp->config->name);
warned = 1;
}
wp->config->request_slowlog_timeout = 0;
#endif
- }
- if (wp->config->request_slowlog_timeout && wp->config->slowlog && *wp->config->slowlog) {
- int fd;
+ if (wp->config->slowlog && *wp->config->slowlog) {
+ int fd;
- fpm_evaluate_full_path(&wp->config->slowlog);
-
- if (wp->config->request_slowlog_timeout) {
fd = open(wp->config->slowlog, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
if (0 > fd) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(%s) failed", wp->config->slowlog);
+ zlog(ZLOG_SYSERROR, "open(%s) failed", wp->config->slowlog);
return -1;
}
close(fd);
@@ -515,18 +597,18 @@ static int fpm_conf_process_all_pools() /* {{{ */
int i;
if (*ping != '/') {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the ping path '%s' must start with a '/'", wp->config->name, ping);
+ zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' must start with a '/'", wp->config->name, ping);
return -1;
}
if (strlen(ping) < 2) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the ping path '%s' is not long enough", wp->config->name, ping);
+ zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' is not long enough", wp->config->name, ping);
return -1;
}
for (i=0; i<strlen(ping); i++) {
if (!isalnum(ping[i]) && ping[i] != '/' && ping[i] != '-' && ping[i] != '_' && ping[i] != '.') {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the ping path '%s' must containt only the following characters '[alphanum]/_-.'", wp->config->name, ping);
+ zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' must containt only the following characters '[alphanum]/_-.'", wp->config->name, ping);
return -1;
}
}
@@ -535,7 +617,7 @@ static int fpm_conf_process_all_pools() /* {{{ */
wp->config->ping_response = strdup("pong");
} else {
if (strlen(wp->config->ping_response) < 1) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the ping response page '%s' is not long enough", wp->config->name, wp->config->ping_response);
+ zlog(ZLOG_ERROR, "[pool %s] the ping response page '%s' is not long enough", wp->config->name, wp->config->ping_response);
return -1;
}
}
@@ -552,73 +634,95 @@ static int fpm_conf_process_all_pools() /* {{{ */
/* struct fpm_status_s fpm_status; */
if (*status != '/') {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the status path '%s' must start with a '/'", wp->config->name, status);
+ zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must start with a '/'", wp->config->name, status);
return -1;
}
if (strlen(status) < 2) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the status path '%s' is not long enough", wp->config->name, status);
+ zlog(ZLOG_ERROR, "[pool %s] the status path '%s' is not long enough", wp->config->name, status);
return -1;
}
for (i=0; i<strlen(status); i++) {
if (!isalnum(status[i]) && status[i] != '/' && status[i] != '-' && status[i] != '_' && status[i] != '.') {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the status path '%s' must contain only the following characters '[alphanum]/_-.'", wp->config->name, status);
+ 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_STUFF, ZLOG_ERROR, "[pool %s] unable to allocate shared memory for status page '%s'", wp->config->name, status);
+ zlog(ZLOG_ERROR, "[pool %s] unable to allocate shared memory for status page '%s'", wp->config->name, status);
return -1;
}
fpm_status_update_accepted_conn(wp->shm_status, 0);
- fpm_status_update_activity(wp->shm_status, -1, -1, -1, 1);
+ 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) {
+
+ fpm_evaluate_full_path(&wp->config->chroot, wp, NULL, 1);
+
if (*wp->config->chroot != '/') {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the chroot path '%s' must start with a '/'", wp->config->name, wp->config->chroot);
+ zlog(ZLOG_ERROR, "[pool %s] the chroot path '%s' must start with a '/'", wp->config->name, wp->config->chroot);
return -1;
}
if (!fpm_conf_is_dir(wp->config->chroot)) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the chroot path '%s' does not exist or is not a directory", wp->config->name, wp->config->chroot);
+ zlog(ZLOG_ERROR, "[pool %s] the chroot path '%s' does not exist or is not a directory", wp->config->name, wp->config->chroot);
return -1;
}
}
if (wp->config->chdir && *wp->config->chdir) {
+
+ fpm_evaluate_full_path(&wp->config->chdir, wp, NULL, 0);
+
if (*wp->config->chdir != '/') {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the chdir path '%s' must start with a '/'", wp->config->name, wp->config->chdir);
+ zlog(ZLOG_ERROR, "[pool %s] the chdir path '%s' must start with a '/'", wp->config->name, wp->config->chdir);
return -1;
}
if (wp->config->chroot) {
char *buf;
- size_t len;
- len = strlen(wp->config->chroot) + strlen(wp->config->chdir) + 1;
- buf = malloc(sizeof(char) * len);
- if (!buf) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] malloc() failed", wp->config->name);
- return -1;
- }
- snprintf(buf, len, "%s%s", wp->config->chroot, wp->config->chdir);
+ spprintf(&buf, 0, "%s/%s", wp->config->chroot, wp->config->chdir);
+
if (!fpm_conf_is_dir(buf)) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the chdir path '%s' within the chroot path '%s' ('%s') does not exist or is not a directory", wp->config->name, wp->config->chdir, wp->config->chroot, buf);
- free(buf);
+ zlog(ZLOG_ERROR, "[pool %s] the chdir path '%s' within the chroot path '%s' ('%s') does not exist or is not a directory", wp->config->name, wp->config->chdir, wp->config->chroot, buf);
+ efree(buf);
return -1;
}
- free(buf);
+
+ efree(buf);
} else {
if (!fpm_conf_is_dir(wp->config->chdir)) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] the chdir path '%s' does not exist or is not a directory", wp->config->name, wp->config->chdir);
+ zlog(ZLOG_ERROR, "[pool %s] the chdir path '%s' does not exist or is not a directory", wp->config->name, wp->config->chdir);
return -1;
}
}
}
+ if (!wp->config->chroot) {
+ struct key_value_s *kv;
+ char *options[] = FPM_PHP_INI_TO_EXPAND;
+ char **p;
+
+ for (kv = wp->config->php_values; kv; kv = kv->next) {
+ 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++) {
+ if (!strcasecmp(kv->key, *p)) {
+ fpm_evaluate_full_path(&kv->value, wp, NULL, 0);
+ }
+ }
+ }
+ }
}
return 0;
}
@@ -628,7 +732,7 @@ int fpm_conf_unlink_pid() /* {{{ */
{
if (fpm_global_config.pid_file) {
if (0 > unlink(fpm_global_config.pid_file)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "unlink(\"%s\") failed", fpm_global_config.pid_file);
+ zlog(ZLOG_SYSERROR, "unlink(\"%s\") failed", fpm_global_config.pid_file);
return -1;
}
}
@@ -648,14 +752,14 @@ int fpm_conf_write_pid() /* {{{ */
fd = creat(fpm_global_config.pid_file, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd < 0) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "creat(\"%s\") failed", fpm_global_config.pid_file);
+ zlog(ZLOG_SYSERROR, "creat(\"%s\") failed", fpm_global_config.pid_file);
return -1;
}
len = sprintf(buf, "%d", (int) fpm_globals.parent_pid);
if (len != write(fd, buf, len)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "write() failed");
+ zlog(ZLOG_SYSERROR, "write() failed");
return -1;
}
close(fd);
@@ -667,18 +771,14 @@ int fpm_conf_write_pid() /* {{{ */
static int fpm_conf_post_process() /* {{{ */
{
if (fpm_global_config.pid_file) {
- fpm_evaluate_full_path(&fpm_global_config.pid_file);
+ fpm_evaluate_full_path(&fpm_global_config.pid_file, NULL, PHP_LOCALSTATEDIR, 0);
}
if (!fpm_global_config.error_log) {
- char *tmp_log_path;
-
- spprintf(&tmp_log_path, 0, "%s/log/php-fpm.log", PHP_LOCALSTATEDIR);
- fpm_global_config.error_log = strdup(tmp_log_path);
- efree(tmp_log_path);
+ fpm_global_config.error_log = strdup("log/php-fpm.log");
}
- fpm_evaluate_full_path(&fpm_global_config.error_log);
+ fpm_evaluate_full_path(&fpm_global_config.error_log, NULL, PHP_LOCALSTATEDIR, 0);
if (0 > fpm_stdio_open_error_log(0)) {
return -1;
@@ -694,6 +794,7 @@ static void fpm_conf_cleanup(int which, void *arg) /* {{{ */
free(fpm_global_config.error_log);
fpm_global_config.pid_file = 0;
fpm_global_config.error_log = 0;
+ free(fpm_globals.config);
}
/* }}} */
@@ -714,12 +815,14 @@ static void fpm_conf_ini_parser_include(char *inc, void *arg TSRMLS_DC) /* {{{ *
if ((i = glob(inc, GLOB_ERR | GLOB_MARK | GLOB_NOSORT, NULL, &g)) != 0) {
#ifdef GLOB_NOMATCH
if (i == GLOB_NOMATCH) {
- zlog(ZLOG_STUFF, ZLOG_WARNING, "Nothing matches the include pattern '%s' from %s at line %d.", inc, filename, ini_lineno);
+ zlog(ZLOG_WARNING, "Nothing matches the include pattern '%s' from %s at line %d.", inc, filename, ini_lineno);
+ efree(filename);
return;
}
#endif /* GLOB_NOMATCH */
- zlog(ZLOG_STUFF, ZLOG_ERROR, "Unable to globalize '%s' (ret=%d) from %s at line %d.", inc, i, filename, ini_lineno);
+ zlog(ZLOG_ERROR, "Unable to globalize '%s' (ret=%d) from %s at line %d.", inc, i, filename, ini_lineno);
*error = 1;
+ efree(filename);
return;
}
@@ -728,8 +831,9 @@ static void fpm_conf_ini_parser_include(char *inc, void *arg TSRMLS_DC) /* {{{ *
if (len < 1) continue;
if (g.gl_pathv[i][len - 1] == '/') continue; /* don't parse directories */
if (0 > fpm_conf_load_ini_file(g.gl_pathv[i] TSRMLS_CC)) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "Unable to include %s from %s at line %d", g.gl_pathv[i], filename, ini_lineno);
+ zlog(ZLOG_ERROR, "Unable to include %s from %s at line %d", g.gl_pathv[i], filename, ini_lineno);
*error = 1;
+ efree(filename);
return;
}
}
@@ -737,11 +841,14 @@ static void fpm_conf_ini_parser_include(char *inc, void *arg TSRMLS_DC) /* {{{ *
}
#else /* HAVE_GLOB */
if (0 > fpm_conf_load_ini_file(inc TSRMLS_CC)) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "Unable to include %s from %s at line %d", inc, filename, ini_lineno);
+ zlog(ZLOG_ERROR, "Unable to include %s from %s at line %d", inc, filename, ini_lineno);
*error = 1;
+ efree(filename);
return;
}
#endif /* HAVE_GLOB */
+
+ efree(filename);
}
/* }}} */
@@ -770,13 +877,13 @@ static void fpm_conf_ini_parser_section(zval *section, void *arg TSRMLS_DC) /* {
/* it's a new pool */
config = (struct fpm_worker_pool_config_s *)fpm_worker_pool_config_alloc();
if (!current_wp || !config) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] Unable to alloc a new WorkerPool for worker '%s'", ini_filename, ini_lineno, Z_STRVAL_P(section));
+ zlog(ZLOG_ERROR, "[%s:%d] Unable to alloc a new WorkerPool for worker '%s'", ini_filename, ini_lineno, Z_STRVAL_P(section));
*error = 1;
return;
}
config->name = strdup(Z_STRVAL_P(section));
if (!config->name) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] Unable to alloc memory for configuration name for worker '%s'", ini_filename, ini_lineno, Z_STRVAL_P(section));
+ zlog(ZLOG_ERROR, "[%s:%d] Unable to alloc memory for configuration name for worker '%s'", ini_filename, ini_lineno, Z_STRVAL_P(section));
*error = 1;
return;
}
@@ -790,14 +897,14 @@ static void fpm_conf_ini_parser_entry(zval *name, zval *value, void *arg TSRMLS_
int *error = (int *)arg;
if (!value) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] value is NULL for a ZEND_INI_PARSER_ENTRY", ini_filename, ini_lineno);
+ zlog(ZLOG_ERROR, "[%s:%d] value is NULL for a ZEND_INI_PARSER_ENTRY", ini_filename, ini_lineno);
*error = 1;
return;
}
if (!strcmp(Z_STRVAL_P(name), "include")) {
if (ini_include) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] two includes at the same time !", ini_filename, ini_lineno);
+ zlog(ZLOG_ERROR, "[%s:%d] two includes at the same time !", ini_filename, ini_lineno);
*error = 1;
return;
}
@@ -817,14 +924,14 @@ static void fpm_conf_ini_parser_entry(zval *name, zval *value, void *arg TSRMLS_
if (!strcasecmp(parser->name, Z_STRVAL_P(name))) {
char *ret;
if (!parser->parser) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] the parser for entry '%s' is not defined", ini_filename, ini_lineno, parser->name);
+ zlog(ZLOG_ERROR, "[%s:%d] the parser for entry '%s' is not defined", ini_filename, ini_lineno, parser->name);
*error = 1;
return;
}
ret = parser->parser(value, &config, parser->offset);
if (ret) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] unable to parse value for entry '%s': %s", ini_filename, ini_lineno, parser->name, ret);
+ zlog(ZLOG_ERROR, "[%s:%d] unable to parse value for entry '%s': %s", ini_filename, ini_lineno, parser->name, ret);
*error = 1;
return;
}
@@ -835,7 +942,7 @@ static void fpm_conf_ini_parser_entry(zval *name, zval *value, void *arg TSRMLS_
}
/* nothing has been found if we got here */
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] unknown entry '%s'", ini_filename, ini_lineno, Z_STRVAL_P(name));
+ zlog(ZLOG_ERROR, "[%s:%d] unknown entry '%s'", ini_filename, ini_lineno, Z_STRVAL_P(name));
*error = 1;
}
/* }}} */
@@ -846,45 +953,60 @@ static void fpm_conf_ini_parser_array(zval *name, zval *key, zval *value, void *
char *err = NULL;
void *config;
- if (!Z_STRVAL_P(key) || !Z_STRVAL_P(value) || !*Z_STRVAL_P(key) || !*Z_STRVAL_P(value)) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] Mispell array ?", ini_filename, ini_lineno);
+ if (!Z_STRVAL_P(key) || !Z_STRVAL_P(value) || !*Z_STRVAL_P(key)) {
+ zlog(ZLOG_ERROR, "[%s:%d] Misspelled array ?", ini_filename, ini_lineno);
*error = 1;
return;
}
if (!current_wp || !current_wp->config) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] Array are not allowed in the global section", ini_filename, ini_lineno);
+ zlog(ZLOG_ERROR, "[%s:%d] Array are not allowed in the global section", ini_filename, ini_lineno);
*error = 1;
return;
}
if (!strcmp("env", Z_STRVAL_P(name))) {
- config = (char *)current_wp->config + offsetof(struct fpm_worker_pool_config_s, env);
+ if (!*Z_STRVAL_P(value)) {
+ zlog(ZLOG_ERROR, "[%s:%d] empty value", ini_filename, ini_lineno);
+ *error = 1;
+ return;
+ }
+ config = (char *)current_wp->config + WPO(env);
err = fpm_conf_set_array(key, value, &config, 0);
} else if (!strcmp("php_value", Z_STRVAL_P(name))) {
- config = (char *)current_wp->config + offsetof(struct fpm_worker_pool_config_s, php_values);
+ if (!*Z_STRVAL_P(value)) {
+ zlog(ZLOG_ERROR, "[%s:%d] empty value", ini_filename, ini_lineno);
+ *error = 1;
+ return;
+ }
+ config = (char *)current_wp->config + WPO(php_values);
err = fpm_conf_set_array(key, value, &config, 0);
} else if (!strcmp("php_admin_value", Z_STRVAL_P(name))) {
- config = (char *)current_wp->config + offsetof(struct fpm_worker_pool_config_s, php_admin_values);
+ if (!*Z_STRVAL_P(value)) {
+ zlog(ZLOG_ERROR, "[%s:%d] empty value", ini_filename, ini_lineno);
+ *error = 1;
+ return;
+ }
+ config = (char *)current_wp->config + WPO(php_admin_values);
err = fpm_conf_set_array(key, value, &config, 0);
} else if (!strcmp("php_flag", Z_STRVAL_P(name))) {
- config = (char *)current_wp->config + offsetof(struct fpm_worker_pool_config_s, php_values);
+ config = (char *)current_wp->config + WPO(php_values);
err = fpm_conf_set_array(key, value, &config, 1);
} else if (!strcmp("php_admin_flag", Z_STRVAL_P(name))) {
- config = (char *)current_wp->config + offsetof(struct fpm_worker_pool_config_s, php_admin_values);
+ config = (char *)current_wp->config + WPO(php_admin_values);
err = fpm_conf_set_array(key, value, &config, 1);
} else {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] unknown directive '%s'", ini_filename, ini_lineno, Z_STRVAL_P(name));
+ zlog(ZLOG_ERROR, "[%s:%d] unknown directive '%s'", ini_filename, ini_lineno, Z_STRVAL_P(name));
*error = 1;
return;
}
if (err) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] error while parsing '%s[%s]' : %s", ini_filename, ini_lineno, Z_STRVAL_P(name), Z_STRVAL_P(key), err);
+ zlog(ZLOG_ERROR, "[%s:%d] error while parsing '%s[%s]' : %s", ini_filename, ini_lineno, Z_STRVAL_P(name), Z_STRVAL_P(key), err);
*error = 1;
return;
}
@@ -910,7 +1032,7 @@ static void fpm_conf_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback
fpm_conf_ini_parser_array(arg1, arg3, arg2, error TSRMLS_CC);
break;;
default:
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s:%d] Unknown INI syntax", ini_filename, ini_lineno);
+ zlog(ZLOG_ERROR, "[%s:%d] Unknown INI syntax", ini_filename, ini_lineno);
*error = 1;
break;;
}
@@ -928,18 +1050,18 @@ int fpm_conf_load_ini_file(char *filename TSRMLS_DC) /* {{{ */
int ret = 1;
if (!filename || !filename[0]) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "Configuration file is empty");
+ zlog(ZLOG_ERROR, "Configuration file is empty");
return -1;
}
fd = open(filename, O_RDONLY, 0);
if (fd < 0) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "Unable to open file '%s', errno=%d", filename, errno);
+ zlog(ZLOG_ERROR, "Unable to open file '%s', errno=%d", filename, errno);
return -1;
}
if (ini_recursion++ > 4) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "You can include more than 5 files recusively");
+ zlog(ZLOG_ERROR, "You can include more than 5 files recusively");
return -1;
}
@@ -953,7 +1075,7 @@ int fpm_conf_load_ini_file(char *filename TSRMLS_DC) /* {{{ */
buf[n++] = '\n';
ini_lineno++;
ini_filename = filename;
- tmp = zend_parse_ini_string(buf, 1, ZEND_INI_SCANNER_RAW, (zend_ini_parser_cb_t)fpm_conf_ini_parser, &error TSRMLS_CC);
+ tmp = zend_parse_ini_string(buf, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fpm_conf_ini_parser, &error TSRMLS_CC);
ini_filename = filename;
if (error || tmp == FAILURE) {
if (ini_include) free(ini_include);
@@ -964,7 +1086,7 @@ int fpm_conf_load_ini_file(char *filename TSRMLS_DC) /* {{{ */
if (ini_include) {
char *tmp = ini_include;
ini_include = NULL;
- fpm_evaluate_full_path(&tmp);
+ fpm_evaluate_full_path(&tmp, NULL, NULL, 0);
fpm_conf_ini_parser_include(tmp, &error TSRMLS_CC);
if (error) {
free(tmp);
@@ -983,30 +1105,119 @@ int fpm_conf_load_ini_file(char *filename TSRMLS_DC) /* {{{ */
}
/* }}} */
-int fpm_conf_init_main() /* {{{ */
+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, "\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, " ");
+
+ 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, "\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);
+
+ for (kv = wp->config->env; kv; kv = kv->next) {
+ zlog(ZLOG_NOTICE, "\tenv[%s] = %s", kv->key, kv->value);
+ }
+
+ for (kv = wp->config->php_values; kv; kv = kv->next) {
+ zlog(ZLOG_NOTICE, "\tphp_value[%s] = %s", kv->key, kv->value);
+ }
+
+ for (kv = wp->config->php_admin_values; kv; kv = kv->next) {
+ zlog(ZLOG_NOTICE, "\tphp_admin_value[%s] = %s", kv->key, kv->value);
+ }
+ zlog(ZLOG_NOTICE, " ");
+ }
+}
+/* }}} */
+
+int fpm_conf_init_main(int test_conf) /* {{{ */
{
- char *filename = fpm_globals.config;
- int free = 0;
int ret;
TSRMLS_FETCH();
- if (filename == NULL) {
- spprintf(&filename, 0, "%s/php-fpm.conf", PHP_SYSCONFDIR);
- free = 1;
+ if (fpm_globals.prefix && *fpm_globals.prefix) {
+ if (!fpm_conf_is_dir(fpm_globals.prefix)) {
+ zlog(ZLOG_ERROR, "the global prefix '%s' does not exist or is not a directory", fpm_globals.prefix);
+ return -1;
+ }
}
- ret = fpm_conf_load_ini_file(filename TSRMLS_CC);
+ if (fpm_globals.config == NULL) {
+ char *tmp;
+
+ if (fpm_globals.prefix == NULL) {
+ spprintf(&tmp, 0, "%s/php-fpm.conf", PHP_SYSCONFDIR);
+ } else {
+ spprintf(&tmp, 0, "%s/etc/php-fpm.conf", fpm_globals.prefix);
+ }
+
+ if (!tmp) {
+ zlog(ZLOG_SYSERROR, "spprintf() failed (tmp for fpm_globals.config)");
+ return -1;
+ }
+
+ fpm_globals.config = strdup(tmp);
+ efree(tmp);
+
+ if (!fpm_globals.config) {
+ zlog(ZLOG_SYSERROR, "spprintf() failed (fpm_globals.config)");
+ return -1;
+ }
+ }
+
+ ret = fpm_conf_load_ini_file(fpm_globals.config TSRMLS_CC);
if (0 > ret) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "failed to load configuration file '%s'", filename);
- if (free) efree(filename);
+ zlog(ZLOG_ERROR, "failed to load configuration file '%s'", fpm_globals.config);
return -1;
}
- if (free) efree(filename);
-
if (0 > fpm_conf_post_process()) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "failed to post process the configuration");
+ zlog(ZLOG_ERROR, "failed to post process the configuration");
+ return -1;
+ }
+
+ if (test_conf) {
+ if (test_conf > 1) {
+ fpm_conf_dump();
+ }
+ zlog(ZLOG_NOTICE, "configuration file %s test is successful\n", fpm_globals.config);
return -1;
}
diff --git a/sapi/fpm/fpm/fpm_conf.h b/sapi/fpm/fpm/fpm_conf.h
index aace7811e..ac38ee2e9 100644
--- a/sapi/fpm/fpm/fpm_conf.h
+++ b/sapi/fpm/fpm/fpm_conf.h
@@ -10,6 +10,10 @@
#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 {
@@ -31,6 +35,7 @@ extern struct fpm_global_config_s fpm_global_config;
struct fpm_worker_pool_config_s {
char *name;
+ char *prefix;
char *user;
char *group;
char *chroot;
@@ -69,7 +74,7 @@ struct ini_value_parser_s {
enum { PM_STYLE_STATIC = 1, PM_STYLE_DYNAMIC = 2 };
-int fpm_conf_init_main();
+int fpm_conf_init_main(int test_conf);
int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc);
int fpm_conf_write_pid();
int fpm_conf_unlink_pid();
diff --git a/sapi/fpm/fpm/fpm_config.h b/sapi/fpm/fpm/fpm_config.h
index 165bd7d62..3637f376c 100644
--- a/sapi/fpm/fpm/fpm_config.h
+++ b/sapi/fpm/fpm/fpm_config.h
@@ -1,44 +1,83 @@
-
- /* $Id: fpm_config.h,v 1.16 2008/05/25 00:30:43 anight Exp $ */
- /* (c) 2007,2008 Andrei Nigmatulin */
+/* $Id: fpm_config.h,v 1.16 2008/05/25 00:30:43 anight Exp $ */
+/* (c) 2007,2008 Andrei Nigmatulin */
#include <php_config.h>
+
#ifdef FPM_AUTOCONFIG_H
-#include <fpm_autoconfig.h>
+# include <fpm_autoconfig.h>
#endif
/* Solaris does not have it */
#ifndef INADDR_NONE
-#define INADDR_NONE (-1)
+# define INADDR_NONE (-1)
#endif
/* If we're not using GNU C, elide __attribute__ */
#ifndef __GNUC__
-# define __attribute__(x) /*NOTHING*/
+# define __attribute__(x) /*NOTHING*/
#endif
+/* Missing timer* macros (for solaris) */
+#ifndef timerisset
+# define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
+#endif
+
+#ifndef timerclear
+# define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
+#endif
-/* Solaris does not have it */
#ifndef timersub
-#define timersub(tvp, uvp, vvp) \
- do { \
- (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
- (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
- if ((vvp)->tv_usec < 0) { \
- (vvp)->tv_sec--; \
- (vvp)->tv_usec += 1000000; \
- } \
+# define timersub(tvp, uvp, vvp) \
+ do { \
+ (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
+ (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
+ if ((vvp)->tv_usec < 0) { \
+ (vvp)->tv_sec--; \
+ (vvp)->tv_usec += 1000000; \
+ } \
+ } while (0)
+#endif
+
+#ifndef timeradd
+# define timeradd(a, b, result) \
+ do { \
+ (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
+ (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
+ if ((result)->tv_usec >= 1000000) \
+ { \
+ ++(result)->tv_sec; \
+ (result)->tv_usec -= 1000000; \
+ } \
} while (0)
#endif
+#ifndef timercmp
+/* does not work for >= and <= */
+# define timercmp(a, b, CMP) \
+ (((a)->tv_sec == (b)->tv_sec) ? \
+ ((a)->tv_usec CMP (b)->tv_usec) : \
+ ((a)->tv_sec CMP (b)->tv_sec))
+#endif
+/* endof timer* macros */
+
#ifndef MIN
-#define MIN(a,b) (((a)<(b))?(a):(b))
+# define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
+#ifndef MAX
+# define MAX(a,b) (((a)>(b))?(a):(b))
#endif
#if defined(HAVE_PTRACE) || defined(PROC_MEM_FILE) || defined(HAVE_MACH_VM_READ)
-#define HAVE_FPM_TRACE 1
+# define HAVE_FPM_TRACE 1
+#else
+# define HAVE_FPM_TRACE 0
+#endif
+
+#if defined(HAVE_LQ_TCP_INFO) || defined(HAVE_LQ_SO_LISTENQ)
+# define HAVE_FPM_LQ 1
#else
-#define HAVE_FPM_TRACE 0
+# define HAVE_FPM_LQ 0
#endif
diff --git a/sapi/fpm/fpm/fpm_env.c b/sapi/fpm/fpm/fpm_env.c
index ddc4705ec..aa647d15b 100644
--- a/sapi/fpm/fpm/fpm_env.c
+++ b/sapi/fpm/fpm/fpm_env.c
@@ -12,8 +12,16 @@
#include <string.h>
#include "fpm_env.h"
+#include "fpm.h"
#include "zlog.h"
+#ifndef HAVE_SETPROCTITLE
+#ifdef __linux__
+static char **fpm_env_argv = NULL;
+static size_t fpm_env_argv_len = 0;
+#endif
+#endif
+
#ifndef HAVE_SETENV
# ifdef (__sparc__ || __sparc)
int setenv(char *name, char *value, int clobber) /* {{{ */
@@ -111,9 +119,30 @@ static char * nvmatch(char *s1, char *s2) /* {{{ */
/* }}} */
#endif
+void fpm_env_setproctitle(char *title) /* {{{ */
+{
+#ifdef HAVE_SETPROCTITLE
+ setproctitle("%s", title);
+#else
+#ifdef __linux__
+ if (fpm_env_argv != NULL && fpm_env_argv_len > strlen(SETPROCTITLE_PREFIX) + 3) {
+ memset(fpm_env_argv[0], 0, fpm_env_argv_len);
+ strncpy(fpm_env_argv[0], SETPROCTITLE_PREFIX, fpm_env_argv_len - 2);
+ strncpy(fpm_env_argv[0] + strlen(SETPROCTITLE_PREFIX), title, fpm_env_argv_len - strlen(SETPROCTITLE_PREFIX) - 2);
+ fpm_env_argv[1] = NULL;
+ }
+#endif
+#endif
+}
+/* }}} */
+
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);
+ efree(title);
clearenv();
@@ -169,12 +198,79 @@ static int fpm_env_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */
int fpm_env_init_main() /* {{{ */
{
struct fpm_worker_pool_s *wp;
+ int i;
+ char *first = NULL;
+ char *last = NULL;
+ char *title;
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
if (0 > fpm_env_conf_wp(wp)) {
return -1;
}
}
+#ifndef HAVE_SETPROCTITLE
+#ifdef __linux__
+ /*
+ * This piece of code has been inspirated from nginx and pureftpd code, whic
+ * are under BSD licence.
+ *
+ * To change the process title in Linux we have to set argv[1] to NULL
+ * and to copy the title to the same place where the argv[0] points to.
+ * However, argv[0] may be too small to hold a new title. Fortunately, Linux
+ * store argv[] and environ[] one after another. So we should ensure that is
+ * the continuous memory and then we allocate the new memory for environ[]
+ * and copy it. After this we could use the memory starting from argv[0] for
+ * our process title.
+ */
+
+ for (i = 0; i < fpm_globals.argc; i++) {
+ if (first == NULL) {
+ first = fpm_globals.argv[i];
+ }
+ if (last == NULL || fpm_globals.argv[i] == last + 1) {
+ last = fpm_globals.argv[i] + strlen(fpm_globals.argv[i]);
+ }
+ }
+ if (environ) {
+ for (i = 0; environ[i]; i++) {
+ if (first == NULL) {
+ first = environ[i];
+ }
+ if (last == NULL || environ[i] == last + 1) {
+ last = environ[i] + strlen(environ[i]);
+ }
+ }
+ }
+ if (first == NULL || last == NULL) {
+ return 0;
+ }
+
+ fpm_env_argv_len = last - first;
+ fpm_env_argv = fpm_globals.argv;
+ if (environ != NULL) {
+ char **new_environ;
+ unsigned int env_nb = 0U;
+
+ while (environ[env_nb]) {
+ env_nb++;
+ }
+
+ if ((new_environ = malloc((1U + env_nb) * sizeof (char *))) == NULL) {
+ return -1;
+ }
+ new_environ[env_nb] = NULL;
+ while (env_nb > 0U) {
+ env_nb--;
+ new_environ[env_nb] = strdup(environ[env_nb]);
+ }
+ environ = new_environ;
+ }
+#endif
+#endif
+
+ spprintf(&title, 0, "master process (%s)", fpm_globals.config);
+ fpm_env_setproctitle(title);
+ efree(title);
return 0;
}
/* }}} */
diff --git a/sapi/fpm/fpm/fpm_env.h b/sapi/fpm/fpm/fpm_env.h
index 0f79ed786..bf472368d 100644
--- a/sapi/fpm/fpm/fpm_env.h
+++ b/sapi/fpm/fpm/fpm_env.h
@@ -7,8 +7,11 @@
#include "fpm_worker_pool.h"
+#define SETPROCTITLE_PREFIX "php-fpm: "
+
int fpm_env_init_child(struct fpm_worker_pool_s *wp);
int fpm_env_init_main();
+void fpm_env_setproctitle(char *title);
extern char **environ;
diff --git a/sapi/fpm/fpm/fpm_events.c b/sapi/fpm/fpm/fpm_events.c
index aa4086d9d..66ff393e2 100644
--- a/sapi/fpm/fpm/fpm_events.c
+++ b/sapi/fpm/fpm/fpm_events.c
@@ -9,6 +9,9 @@
#include <stdlib.h> /* for putenv */
#include <string.h>
+#include <php.h>
+#include <php_network.h>
+
#include "fpm.h"
#include "fpm_process_ctl.h"
#include "fpm_events.h"
@@ -17,19 +20,43 @@
#include "fpm_signals.h"
#include "fpm_children.h"
#include "zlog.h"
+#include "fpm_clock.h"
+
+#define fpm_event_set_timeout(ev, now) timeradd(&(now), &(ev)->frequency, &(ev)->timeout);
+
+typedef struct fpm_event_queue_s {
+ struct fpm_event_queue_s *prev;
+ struct fpm_event_queue_s *next;
+ struct fpm_event_s *ev;
+} fpm_event_queue;
+
+static void fpm_event_cleanup(int which, void *arg);
+static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg);
+static struct fpm_event_s *fpm_event_queue_isset(struct fpm_event_queue_s *queue, struct fpm_event_s *ev);
+static int fpm_event_queue_add(struct fpm_event_queue_s **queue, struct fpm_event_s *ev);
+static int fpm_event_queue_del(struct fpm_event_queue_s **queue, struct fpm_event_s *ev);
+static void fpm_event_queue_destroy(struct fpm_event_queue_s **queue);
+
+static int fpm_event_nfds_max;
+static struct fpm_event_queue_s *fpm_event_queue_timer = NULL;
+static struct fpm_event_queue_s *fpm_event_queue_fd = NULL;
+static php_pollfd *fpm_event_ufds = NULL;
static void fpm_event_cleanup(int which, void *arg) /* {{{ */
{
- struct event_base *base = (struct event_base *)arg;
- event_base_free(base);
+ if (fpm_event_ufds) {
+ free(fpm_event_ufds);
+ }
+ fpm_event_queue_destroy(&fpm_event_queue_timer);
+ fpm_event_queue_destroy(&fpm_event_queue_fd);
}
/* }}} */
-static void fpm_got_signal(int fd, short ev, void *arg) /* {{{ */
+static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
{
char c;
int res;
- struct event_base *base = (struct event_base *)arg;
+ int fd = ev->fd;;
do {
do {
@@ -38,43 +65,43 @@ static void fpm_got_signal(int fd, short ev, void *arg) /* {{{ */
if (res <= 0) {
if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed");
+ zlog(ZLOG_SYSERROR, "read() failed");
}
return;
}
switch (c) {
case 'C' : /* SIGCHLD */
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGCHLD");
- fpm_children_bury(base);
+ zlog(ZLOG_DEBUG, "received SIGCHLD");
+ fpm_children_bury();
break;
case 'I' : /* SIGINT */
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGINT");
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "Terminating ...");
- fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET, base);
+ zlog(ZLOG_DEBUG, "received SIGINT");
+ zlog(ZLOG_NOTICE, "Terminating ...");
+ fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET);
break;
case 'T' : /* SIGTERM */
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGTERM");
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "Terminating ...");
- fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET, base);
+ zlog(ZLOG_DEBUG, "received SIGTERM");
+ zlog(ZLOG_NOTICE, "Terminating ...");
+ fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET);
break;
case 'Q' : /* SIGQUIT */
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGQUIT");
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "Finishing ...");
- fpm_pctl(FPM_PCTL_STATE_FINISHING, FPM_PCTL_ACTION_SET, base);
+ zlog(ZLOG_DEBUG, "received SIGQUIT");
+ zlog(ZLOG_NOTICE, "Finishing ...");
+ fpm_pctl(FPM_PCTL_STATE_FINISHING, FPM_PCTL_ACTION_SET);
break;
case '1' : /* SIGUSR1 */
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGUSR1");
+ zlog(ZLOG_DEBUG, "received SIGUSR1");
if (0 == fpm_stdio_open_error_log(1)) {
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "log file re-opened");
+ zlog(ZLOG_NOTICE, "log file re-opened");
} else {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "unable to re-opened log file");
+ zlog(ZLOG_ERROR, "unable to re-opened log file");
}
break;
case '2' : /* SIGUSR2 */
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGUSR2");
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "Reloading in progress ...");
- fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET, base);
+ zlog(ZLOG_DEBUG, "received SIGUSR2");
+ zlog(ZLOG_NOTICE, "Reloading in progress ...");
+ fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET);
break;
}
@@ -86,57 +113,335 @@ static void fpm_got_signal(int fd, short ev, void *arg) /* {{{ */
}
/* }}} */
-int fpm_event_init_main(struct event_base **base) /* {{{ */
+static struct fpm_event_s *fpm_event_queue_isset(struct fpm_event_queue_s *queue, struct fpm_event_s *ev) /* {{{ */
+{
+ if (!ev) {
+ return NULL;
+ }
+
+ while (queue) {
+ if (queue->ev == ev) {
+ return ev;
+ }
+ queue = queue->next;
+ }
+
+ return NULL;
+}
+/* }}} */
+
+static int fpm_event_queue_add(struct fpm_event_queue_s **queue, struct fpm_event_s *ev) /* {{{ */
{
- *base = event_base_new();
+ struct fpm_event_queue_s *elt;
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "libevent: using %s", event_base_get_method(*base));
+ if (!queue || !ev) {
+ return -1;
+ }
- if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_event_cleanup, *base)) {
+ if (fpm_event_queue_isset(*queue, ev)) {
+ return 0;
+ }
+
+ if (!(elt = malloc(sizeof(struct fpm_event_queue_s)))) {
+ zlog(ZLOG_SYSERROR, "malloc() failed");
return -1;
}
- return 0;
+ elt->prev = NULL;
+ elt->next = NULL;
+ elt->ev = ev;
+
+ if (*queue) {
+ (*queue)->prev = elt;
+ elt->next = *queue;
+ }
+ *queue = elt;
+
+ return 0;
+}
+/* }}} */
+
+static int fpm_event_queue_del(struct fpm_event_queue_s **queue, struct fpm_event_s *ev) /* {{{ */
+{
+ struct fpm_event_queue_s *q;
+ if (!queue || !ev) {
+ return -1;
+ }
+ q = *queue;
+ while (q) {
+ if (q->ev == ev) {
+ if (q->prev) {
+ q->prev->next = q->next;
+ }
+ if (q->next) {
+ q->next->prev = q->prev;
+ }
+ if (q == *queue) {
+ *queue = q->next;
+ (*queue)->prev = NULL;
+ }
+ free(q);
+ return 0;
+ }
+ q = q->next;
+ }
+ return -1;
+}
+/* }}} */
+
+static void fpm_event_queue_destroy(struct fpm_event_queue_s **queue) /* {{{ */
+{
+ struct fpm_event_queue_s *q, *tmp;
+
+ if (!queue) {
+ return;
+ }
+ q = *queue;
+ while (q) {
+ tmp = q;
+ q = q->next;
+ /* q->prev = NULL */
+ free(tmp);
+ }
+ *queue = NULL;
}
/* }}} */
-int fpm_event_loop(struct event_base *base) /* {{{ */
+int fpm_event_init_main() /* {{{ */
{
- static struct event signal_fd_event;
-
- event_set(&signal_fd_event, fpm_signals_get_fd(), EV_PERSIST | EV_READ, &fpm_got_signal, base);
- event_base_set(base, &signal_fd_event);
- event_add(&signal_fd_event, 0);
- fpm_pctl_heartbeat(-1, 0, base);
- fpm_pctl_perform_idle_server_maintenance_heartbeat(-1, 0, base);
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "ready to handle connections");
- event_base_dispatch(base);
+ struct fpm_worker_pool_s *wp;
+
+ /* count the max number of necessary fds for polling */
+ fpm_event_nfds_max = 1; /* only one FD is necessary at startup for the master process signal pipe */
+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
+ if (!wp->config) continue;
+ if (wp->config->catch_workers_output && wp->config->pm_max_children > 0) {
+ fpm_event_nfds_max += (wp->config->pm_max_children * 2);
+ }
+ }
+
+ /* malloc the max number of necessary fds for polling */
+ fpm_event_ufds = malloc(sizeof(php_pollfd) * fpm_event_nfds_max);
+ if (!fpm_event_ufds) {
+ zlog(ZLOG_SYSERROR, "malloc() failed");
+ return -1;
+ }
+
+ zlog(ZLOG_DEBUG, "%d fds have been reserved", fpm_event_nfds_max);
+
+ if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_event_cleanup, NULL)) {
+ return -1;
+ }
return 0;
}
/* }}} */
-int fpm_event_add(int fd, struct event_base *base, struct event *ev, void (*callback)(int, short, void *), void *arg) /* {{{ */
+void fpm_event_loop() /* {{{ */
+{
+ static struct fpm_event_s signal_fd_event;
+
+ /* sanity check */
+ if (fpm_globals.parent_pid != getpid()) {
+ return;
+ }
+
+ fpm_event_set(&signal_fd_event, fpm_signals_get_fd(), FPM_EV_READ, &fpm_got_signal, NULL);
+ fpm_event_add(&signal_fd_event, 0);
+
+ /* 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");
+
+ while (1) {
+ struct fpm_event_queue_s *q, *q2;
+ struct timeval ms;
+ struct timeval tmp;
+ struct timeval now;
+ unsigned long int timeout;
+ int i, ret;
+
+ /* sanity check */
+ if (fpm_globals.parent_pid != getpid()) {
+ return;
+ }
+
+ fpm_clock_get(&now);
+ timerclear(&ms);
+
+ /* search in the timeout queue for the next timer to trigger */
+ q = fpm_event_queue_timer;
+ while (q) {
+ if (!timerisset(&ms)) {
+ ms = q->ev->timeout;
+ } else {
+ if (timercmp(&q->ev->timeout, &ms, <)) {
+ ms = q->ev->timeout;
+ }
+ }
+ q = q->next;
+ }
+
+ /* 1s timeout if none has been set */
+ if (!timerisset(&ms) || timercmp(&ms, &now, <) || timercmp(&ms, &now, ==)) {
+ timeout = 1000;
+ } else {
+ timersub(&ms, &now, &tmp);
+ timeout = (tmp.tv_sec * 1000) + (tmp.tv_usec / 1000) + 1;
+ }
+
+ /* init fpm_event_ufds for php_poll2 */
+ memset(fpm_event_ufds, 0, sizeof(php_pollfd) * fpm_event_nfds_max);
+ i = 0;
+ q = fpm_event_queue_fd;
+ while (q && i < fpm_event_nfds_max) {
+ fpm_event_ufds[i].fd = q->ev->fd;
+ fpm_event_ufds[i].events = POLLIN;
+ q->ev->index = i++;
+ q = q->next;
+ }
+
+ /* wait for inconming event or timeout */
+ if ((ret = php_poll2(fpm_event_ufds, i, timeout)) == -1) {
+ if (errno != EINTR) {
+ zlog(ZLOG_WARNING, "php_poll2() returns %d", errno);
+ }
+ } else if (ret > 0) {
+
+ /* trigger POLLIN events */
+ q = fpm_event_queue_fd;
+ while (q) {
+ if (q->ev && q->ev->index >= 0 && q->ev->index < fpm_event_nfds_max) {
+ if (q->ev->fd == fpm_event_ufds[q->ev->index].fd) {
+ if (fpm_event_ufds[q->ev->index].revents & POLLIN) {
+ fpm_event_fire(q->ev);
+ /* sanity check */
+ if (fpm_globals.parent_pid != getpid()) {
+ return;
+ }
+ }
+ }
+ q->ev->index = -1;
+ }
+ q = q->next;
+ }
+ }
+
+ /* trigger timers */
+ q = fpm_event_queue_timer;
+ while (q) {
+ fpm_clock_get(&now);
+ if (q->ev) {
+ if (timercmp(&now, &q->ev->timeout, >) || timercmp(&now, &q->ev->timeout, ==)) {
+ fpm_event_fire(q->ev);
+ /* sanity check */
+ if (fpm_globals.parent_pid != getpid()) {
+ return;
+ }
+ if (q->ev->flags & FPM_EV_PERSIST) {
+ fpm_event_set_timeout(q->ev, now);
+ } else { /* delete the event */
+ q2 = q;
+ if (q->prev) {
+ q->prev->next = q->next;
+ }
+ if (q->next) {
+ q->next->prev = q->prev;
+ }
+ if (q == fpm_event_queue_timer) {
+ fpm_event_queue_timer = q->next;
+ fpm_event_queue_timer->prev = NULL;
+ }
+ q = q->next;
+ free(q2);
+ continue;
+ }
+ }
+ }
+ q = q->next;
+ }
+ }
+}
+/* }}} */
+
+void fpm_event_fire(struct fpm_event_s *ev) /* {{{ */
{
- event_set(ev, fd, EV_PERSIST | EV_READ, callback, arg);
- event_base_set(base, ev);
- return event_add(ev, 0);
+ if (!ev || !ev->callback) {
+ return;
+ }
+
+ (*ev->callback)( (struct fpm_event_s *) ev, ev->which, ev->arg);
}
/* }}} */
-int fpm_event_del(struct event *ev) /* {{{ */
+int fpm_event_set(struct fpm_event_s *ev, int fd, int flags, void (*callback)(struct fpm_event_s *, short, void *), void *arg) /* {{{ */
{
- return event_del(ev);
+ if (!ev || !callback || fd < -1) {
+ return -1;
+ }
+ memset(ev, 0, sizeof(struct fpm_event_s));
+ ev->fd = fd;
+ ev->callback = callback;
+ ev->arg = arg;
+ ev->flags = flags;
+ return 0;
}
/* }}} */
-void fpm_event_exit_loop(struct event_base *base) /* {{{ */
+int fpm_event_add(struct fpm_event_s *ev, unsigned long int frequency) /* {{{ */
{
- event_base_loopbreak(base);
+ struct timeval now;
+ struct timeval tmp;
+
+ if (!ev) {
+ return -1;
+ }
+
+ ev->index = -1;
+
+ /* it's a triggered event on incoming data */
+ if (ev->flags & FPM_EV_READ) {
+ ev->which = FPM_EV_READ;
+ if (fpm_event_queue_add(&fpm_event_queue_fd, ev) != 0) {
+ return -1;
+ }
+ return 0;
+ }
+
+ /* it's a timer event */
+ ev->which = FPM_EV_TIMEOUT;
+
+ fpm_clock_get(&now);
+ if (frequency >= 1000) {
+ tmp.tv_sec = frequency / 1000;
+ tmp.tv_usec = (frequency % 1000) * 1000;
+ } else {
+ tmp.tv_sec = 0;
+ tmp.tv_usec = frequency * 1000;
+ }
+ ev->frequency = tmp;
+ fpm_event_set_timeout(ev, now);
+
+ if (fpm_event_queue_add(&fpm_event_queue_timer, ev) != 0) {
+ return -1;
+ }
+
+ return 0;
}
/* }}} */
-void fpm_event_fire(struct event *ev) /* {{{ */
+int fpm_event_del(struct fpm_event_s *ev) /* {{{ */
{
- (*ev->ev_callback)( (int) ev->ev_fd, (short) ev->ev_res, ev->ev_arg);
+ if (fpm_event_queue_del(&fpm_event_queue_fd, ev) != 0) {
+ return -1;
+ }
+
+ if (fpm_event_queue_del(&fpm_event_queue_timer, ev) != 0) {
+ return -1;
+ }
+
+ return 0;
}
/* }}} */
+/* }}} */
diff --git a/sapi/fpm/fpm/fpm_events.h b/sapi/fpm/fpm/fpm_events.h
index 7a5a9a53b..bec13ba5e 100644
--- a/sapi/fpm/fpm/fpm_events.h
+++ b/sapi/fpm/fpm/fpm_events.h
@@ -5,12 +5,28 @@
#ifndef FPM_EVENTS_H
#define FPM_EVENTS_H 1
-void fpm_event_exit_loop(struct event_base *base);
-int fpm_event_loop(struct event_base *base);
-int fpm_event_add(int fd, struct event_base *base, struct event *ev, void (*callback)(int, short, void *), void *arg);
-int fpm_event_del(struct event *ev);
-void fpm_event_fire(struct event *ev);
-int fpm_event_init_main(struct event_base **base);
+#define FPM_EV_TIMEOUT (1 << 0)
+#define FPM_EV_READ (1 << 1)
+#define FPM_EV_PERSIST (1 << 2)
+#define fpm_event_set_timer(ev, flags, cb, arg) fpm_event_set((ev), -1, (flags), (cb), (arg))
+
+struct fpm_event_s {
+ int fd; /* not set with FPM_EV_TIMEOUT */
+ struct timeval timeout; /* next time to trigger */
+ struct timeval frequency;
+ void (*callback)(struct fpm_event_s *, short, void *);
+ void *arg;
+ int flags;
+ int index; /* index of the fd in the ufds array */
+ short which; /* type of event */
+};
+
+void fpm_event_loop();
+void fpm_event_fire(struct fpm_event_s *ev);
+int fpm_event_init_main();
+int fpm_event_set(struct fpm_event_s *ev, int fd, int flags, void (*callback)(struct fpm_event_s *, short, void *), void *arg);
+int fpm_event_add(struct fpm_event_s *ev, unsigned long int timeout);
+int fpm_event_del(struct fpm_event_s *ev);
#endif
diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c
index 2ee4539b2..8f0d76007 100644
--- a/sapi/fpm/fpm/fpm_main.c
+++ b/sapi/fpm/fpm/fpm_main.c
@@ -152,6 +152,8 @@ static const opt_struct OPTIONS[] = {
{'?', 0, "usage"},/* help alias (both '?' and 'usage') */
{'v', 0, "version"},
{'y', 1, "fpm-config"},
+ {'t', 0, "test"},
+ {'p', 1, "prefix"},
{'-', 0, NULL} /* end of args */
};
@@ -166,7 +168,6 @@ typedef struct _php_cgi_globals_struct {
HashTable user_config_cache;
char *error_header;
char *fpm_config;
- struct event_base *event_base;
} php_cgi_globals_struct;
/* {{{ user_config_cache
@@ -959,7 +960,7 @@ static void php_cgi_usage(char *argv0)
prog = "php";
}
- php_printf( "Usage: %s [-n] [-e] [-h] [-i] [-m] [-v] [-c <file>] [-d foo[=bar]] [-y <file>]\n"
+ php_printf( "Usage: %s [-n] [-e] [-h] [-i] [-m] [-v] [-t] [-p <prefix> ] [-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"
@@ -968,9 +969,12 @@ static void php_cgi_usage(char *argv0)
" -i PHP information\n"
" -m Show compiled in modules\n"
" -v Version number\n"
+ " -p, --prefix <dir>\n"
+ " Specify alternative prefix path to FastCGI process manager (default: %s).\n"
" -y, --fpm-config <file>\n"
- " Specify alternative path to FastCGI process manager config file.\n",
- prog);
+ " Specify alternative path to FastCGI process manager config file.\n"
+ " -t, --test Test FPM configuration and exit\n",
+ prog, PHP_PREFIX);
}
/* }}} */
@@ -1372,7 +1376,7 @@ static void init_request_info(TSRMLS_D)
int mode = ZEND_INI_USER;
char *tmp;
spprintf(&tmp, 0, "%s\n", ini);
- zend_parse_ini_string(tmp, 1, ZEND_INI_SCANNER_RAW, (zend_ini_parser_cb_t)fastcgi_ini_parser, &mode TSRMLS_CC);
+ zend_parse_ini_string(tmp, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fastcgi_ini_parser, &mode TSRMLS_CC);
efree(tmp);
}
@@ -1381,7 +1385,7 @@ static void init_request_info(TSRMLS_D)
int mode = ZEND_INI_SYSTEM;
char *tmp;
spprintf(&tmp, 0, "%s\n", ini);
- zend_parse_ini_string(tmp, 1, ZEND_INI_SCANNER_RAW, (zend_ini_parser_cb_t)fastcgi_ini_parser, &mode TSRMLS_CC);
+ zend_parse_ini_string(tmp, 1, ZEND_INI_SCANNER_NORMAL, (zend_ini_parser_cb_t)fastcgi_ini_parser, &mode TSRMLS_CC);
efree(tmp);
}
}
@@ -1406,7 +1410,7 @@ static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_
return;
}
- if (!value || strlen(value) < 1) {
+ if (!value) {
fprintf(stderr, "Passing INI directive through FastCGI: empty value for key '%s'\n", key);
return;
}
@@ -1480,7 +1484,6 @@ static PHP_MINFO_FUNCTION(cgi)
{
php_info_print_table_start();
php_info_print_table_row(2, "php-fpm", "active");
- php_info_print_table_row(2, "php-fpm version", PHP_FPM_VERSION);
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
@@ -1548,6 +1551,8 @@ int main(int argc, char *argv[])
int fcgi_fd = 0;
fcgi_request request;
char *fpm_config = NULL;
+ char *fpm_prefix = NULL;
+ int test_conf = 0;
fcgi_init();
@@ -1585,9 +1590,11 @@ int main(int argc, char *argv[])
}
cgi_sapi_module.php_ini_path_override = strdup(php_optarg);
break;
+
case 'n':
cgi_sapi_module.php_ini_ignore = 1;
break;
+
case 'd': {
/* define ini entries on command line */
int len = strlen(php_optarg);
@@ -1619,14 +1626,23 @@ int main(int argc, char *argv[])
}
break;
}
+
case 'y':
fpm_config = php_optarg;
break;
+ case 'p':
+ fpm_prefix = php_optarg;
+ break;
+
case 'e': /* enable extended info output */
CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;
break;
+ case 't':
+ test_conf++;
+ break;
+
case 'm': /* list compiled in modules */
cgi_sapi_module.startup(&cgi_sapi_module);
php_output_startup();
@@ -1763,11 +1779,11 @@ 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), &CGIG(event_base))) {
+ if (0 > fpm_init(argc, argv, fpm_config ? fpm_config : CGIG(fpm_config), fpm_prefix, test_conf)) {
return FAILURE;
}
- fcgi_fd = fpm_run(&max_requests, CGIG(event_base));
+ fcgi_fd = fpm_run(&max_requests);
parent = 0;
fcgi_set_is_fastcgi(1);
@@ -1920,8 +1936,10 @@ fastcgi_request_done:
out:
SG(server_context) = NULL;
- php_module_shutdown(TSRMLS_C);
- sapi_shutdown();
+ if (parent) {
+ php_module_shutdown(TSRMLS_C);
+ sapi_shutdown();
+ }
#ifdef ZTS
tsrm_shutdown();
diff --git a/sapi/fpm/fpm/fpm_php.c b/sapi/fpm/fpm/fpm_php.c
index ce5dac4bc..eeba71301 100644
--- a/sapi/fpm/fpm/fpm_php.c
+++ b/sapi/fpm/fpm/fpm_php.c
@@ -139,6 +139,7 @@ static int fpm_php_set_allowed_clients(struct fpm_worker_pool_s *wp) /* {{{ */
}
/* }}} */
+#if 0 /* Comment out this non used function. It could be used later. */
static int fpm_php_set_fcgi_mgmt_vars(struct fpm_worker_pool_s *wp) /* {{{ */
{
char max_workers[10 + 1]; /* 4294967295 */
@@ -151,6 +152,7 @@ static int fpm_php_set_fcgi_mgmt_vars(struct fpm_worker_pool_s *wp) /* {{{ */
return 0;
}
/* }}} */
+#endif
char *fpm_php_script_filename(TSRMLS_D) /* {{{ */
{
diff --git a/sapi/fpm/fpm/fpm_php.h b/sapi/fpm/fpm/fpm_php.h
index 8c4b58ceb..81e533267 100644
--- a/sapi/fpm/fpm/fpm_php.h
+++ b/sapi/fpm/fpm/fpm_php.h
@@ -11,6 +11,26 @@
#include "build-defs.h" /* for PHP_ defines */
#include "fpm/fpm_conf.h"
+#define FPM_PHP_INI_TO_EXPAND \
+ { \
+ "error_log", \
+ "extension_dir", \
+ "mime_magic.magicfile", \
+ "sendmail_path", \
+ "session.cookie_path", \
+ "session_pgsql.sem_file_name", \
+ "soap.wsdl_cache_dir", \
+ "uploadprogress.file.filename_template", \
+ "xdebug.output_dir", \
+ "xdebug.profiler_output_dir", \
+ "xdebug.trace_output_dir", \
+ "xmms.path", \
+ "axis2.client_home", \
+ "blenc.key_file", \
+ "coin_acceptor.device", \
+ NULL \
+ }
+
struct fpm_worker_pool_s;
int fpm_php_init_child(struct fpm_worker_pool_s *wp);
diff --git a/sapi/fpm/fpm/fpm_php_trace.c b/sapi/fpm/fpm/fpm_php_trace.c
index 306a592c8..03874584f 100644
--- a/sapi/fpm/fpm/fpm_php_trace.c
+++ b/sapi/fpm/fpm/fpm_php_trace.c
@@ -139,12 +139,12 @@ void fpm_php_trace(struct fpm_child_s *child) /* {{{ */
TSRMLS_FETCH();
FILE *slowlog;
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "about to trace %d", (int) child->pid);
+ zlog(ZLOG_NOTICE, "about to trace %d", (int) child->pid);
slowlog = fopen(child->wp->config->slowlog, "a+");
if (!slowlog) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fopen(%s) failed", child->wp->config->slowlog);
+ zlog(ZLOG_SYSERROR, "fopen(%s) failed", child->wp->config->slowlog);
goto done0;
}
@@ -167,7 +167,7 @@ done0:
fpm_pctl_kill(child->pid, FPM_PCTL_CONT);
child->tracer = 0;
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "finished trace of %d", (int) child->pid);
+ zlog(ZLOG_NOTICE, "finished trace of %d", (int) child->pid);
}
/* }}} */
diff --git a/sapi/fpm/fpm/fpm_process_ctl.c b/sapi/fpm/fpm/fpm_process_ctl.c
index b24f950f5..badda1408 100644
--- a/sapi/fpm/fpm/fpm_process_ctl.c
+++ b/sapi/fpm/fpm/fpm_process_ctl.c
@@ -19,6 +19,7 @@
#include "fpm_request.h"
#include "fpm_worker_pool.h"
#include "fpm_status.h"
+#include "fpm_sockets.h"
#include "zlog.h"
@@ -48,36 +49,25 @@ static void fpm_pctl_cleanup(int which, void *arg) /* {{{ */
}
/* }}} */
-static struct event pctl_event;
+static struct fpm_event_s pctl_event;
-static void fpm_pctl_action(int fd, short which, void *arg) /* {{{ */
+static void fpm_pctl_action(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
{
- struct event_base *base = (struct event_base *)arg;
-
- evtimer_del(&pctl_event);
- memset(&pctl_event, 0, sizeof(pctl_event));
- fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_TIMEOUT, base);
+ fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_TIMEOUT);
}
/* }}} */
-static int fpm_pctl_timeout_set(int sec, struct event_base *base) /* {{{ */
+static int fpm_pctl_timeout_set(int sec) /* {{{ */
{
- struct timeval tv = { .tv_sec = sec, .tv_usec = 0 };
-
- if (evtimer_initialized(&pctl_event)) {
- evtimer_del(&pctl_event);
- }
-
- evtimer_set(&pctl_event, &fpm_pctl_action, base);
- event_base_set(base, &pctl_event);
- evtimer_add(&pctl_event, &tv);
+ fpm_event_set_timer(&pctl_event, 0, &fpm_pctl_action, NULL);
+ fpm_event_add(&pctl_event, sec * 1000);
return 0;
}
/* }}} */
static void fpm_pctl_exit() /* {{{ */
{
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "exiting, bye-bye!");
+ zlog(ZLOG_NOTICE, "exiting, bye-bye!");
fpm_conf_unlink_pid();
fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT_MAIN);
@@ -90,7 +80,7 @@ static void fpm_pctl_exit() /* {{{ */
static void fpm_pctl_exec() /* {{{ */
{
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "reloading: execvp(\"%s\", {\"%s\""
+ zlog(ZLOG_NOTICE, "reloading: execvp(\"%s\", {\"%s\""
"%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s"
"%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s"
"})",
@@ -109,7 +99,7 @@ static void fpm_pctl_exec() /* {{{ */
fpm_cleanups_run(FPM_CLEANUP_PARENT_EXEC);
execvp(saved_argv[0], saved_argv);
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "execvp() failed");
+ zlog(ZLOG_SYSERROR, "execvp() failed");
exit(1);
}
/* }}} */
@@ -143,6 +133,9 @@ int fpm_pctl_kill(pid_t pid, int how) /* {{{ */
case FPM_PCTL_CONT :
s = SIGCONT;
break;
+ case FPM_PCTL_QUIT :
+ s = SIGQUIT;
+ break;
default :
break;
}
@@ -161,7 +154,7 @@ static void fpm_pctl_kill_all(int signo) /* {{{ */
for (child = wp->children; child; child = child->next) {
int res = kill(child->pid, signo);
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "[pool %s] sending signal %d %s to child %d",
+ zlog(ZLOG_DEBUG, "[pool %s] sending signal %d %s to child %d",
child->wp->config->name, signo,
fpm_signal_names[signo] ? fpm_signal_names[signo] : "", (int) child->pid);
@@ -172,12 +165,12 @@ static void fpm_pctl_kill_all(int signo) /* {{{ */
}
if (alive_children) {
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "%d child(ren) still alive", alive_children);
+ zlog(ZLOG_DEBUG, "%d child(ren) still alive", alive_children);
}
}
/* }}} */
-static void fpm_pctl_action_next(struct event_base *base) /* {{{ */
+static void fpm_pctl_action_next() /* {{{ */
{
int sig, timeout;
@@ -203,11 +196,11 @@ static void fpm_pctl_action_next(struct event_base *base) /* {{{ */
fpm_pctl_kill_all(sig);
fpm_signal_sent = sig;
- fpm_pctl_timeout_set(timeout, base);
+ fpm_pctl_timeout_set(timeout);
}
/* }}} */
-void fpm_pctl(int new_state, int action, struct event_base *base) /* {{{ */
+void fpm_pctl(int new_state, int action) /* {{{ */
{
switch (action) {
case FPM_PCTL_ACTION_SET :
@@ -227,7 +220,7 @@ void fpm_pctl(int new_state, int action, struct event_base *base) /* {{{ */
if (new_state == FPM_PCTL_STATE_TERMINATING) break;
case FPM_PCTL_STATE_TERMINATING :
/* nothing can override 'terminating' state */
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "not switching to '%s' state, because already in '%s' state",
+ zlog(ZLOG_DEBUG, "not switching to '%s' state, because already in '%s' state",
fpm_state_names[new_state], fpm_state_names[fpm_state]);
return;
}
@@ -235,11 +228,11 @@ void fpm_pctl(int new_state, int action, struct event_base *base) /* {{{ */
fpm_signal_sent = 0;
fpm_state = new_state;
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "switching to '%s' state", fpm_state_names[fpm_state]);
+ zlog(ZLOG_DEBUG, "switching to '%s' state", fpm_state_names[fpm_state]);
/* fall down */
case FPM_PCTL_ACTION_TIMEOUT :
- fpm_pctl_action_next(base);
+ fpm_pctl_action_next();
break;
case FPM_PCTL_ACTION_LAST_CHILD_EXITED :
fpm_pctl_action_last();
@@ -255,14 +248,14 @@ int fpm_pctl_can_spawn_children() /* {{{ */
}
/* }}} */
-int fpm_pctl_child_exited(struct event_base *base) /* {{{ */
+int fpm_pctl_child_exited() /* {{{ */
{
if (fpm_state == FPM_PCTL_STATE_NORMAL) {
return 0;
}
if (!fpm_globals.running_children) {
- fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_LAST_CHILD_EXITED, base);
+ fpm_pctl(FPM_PCTL_STATE_UNSPECIFIED, FPM_PCTL_ACTION_LAST_CHILD_EXITED);
}
return 0;
}
@@ -314,51 +307,49 @@ static void fpm_pctl_check_request_timeout(struct timeval *now) /* {{{ */
}
/* }}} */
-static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now, struct event_base *base) /* {{{ */
+static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ */
{
struct fpm_worker_pool_s *wp;
- struct fpm_child_s *last_idle_child = NULL;
- int i;
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
struct fpm_child_s *child;
+ struct fpm_child_s *last_idle_child = NULL;
int idle = 0;
int active = 0;
+ int children_to_fork;
+ unsigned cur_lq;
if (wp->config == NULL) continue;
for (child = wp->children; child; child = child->next) {
- int ret = fpm_request_is_idle(child);
- if (ret == 1) {
+ if (fpm_request_is_idle(child)) {
if (last_idle_child == NULL) {
last_idle_child = child;
} else {
- if (child->started.tv_sec < last_idle_child->started.tv_sec) {
+ if (timercmp(&child->started, &last_idle_child->started, <)) {
last_idle_child = child;
}
}
idle++;
- } else if (ret == 0) {
+ } else {
active++;
}
}
- if ((active + idle) != wp->running_children) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] unable to retrieve process activity of one or more child(ren). Will try again later.", wp->config->name);
- continue;
- }
-
/* update status structure for all PMs */
- fpm_status_update_activity(wp->shm_status, idle, active, idle + active, 0);
+ if (0 > fpm_socket_get_listening_queue(wp, &cur_lq, NULL)) {
+ cur_lq = 0;
+ }
+ 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;
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "[pool %s] currently %d active children, %d spare children, %d running children. Spawning rate %d", wp->config->name, active, idle, wp->running_children, wp->idle_spawn_rate);
+ zlog(ZLOG_DEBUG, "[pool %s] currently %d active children, %d spare children, %d running children. Spawning rate %d", wp->config->name, active, idle, wp->running_children, wp->idle_spawn_rate);
if (idle > wp->config->pm_max_spare_servers && last_idle_child) {
last_idle_child->idle_kill = 1;
- fpm_pctl_kill(last_idle_child->pid, FPM_PCTL_TERM);
+ fpm_pctl_kill(last_idle_child->pid, FPM_PCTL_QUIT);
wp->idle_spawn_rate = 1;
continue;
}
@@ -366,7 +357,8 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now, struct
if (idle < wp->config->pm_min_spare_servers) {
if (wp->running_children >= wp->config->pm_max_children) {
if (!wp->warn_max_children) {
- zlog(ZLOG_STUFF, ZLOG_WARNING, "[pool %s] server reached max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_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);
wp->warn_max_children = 1;
}
wp->idle_spawn_rate = 1;
@@ -374,17 +366,18 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now, struct
}
if (wp->idle_spawn_rate >= 8) {
- zlog(ZLOG_STUFF, 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 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);
}
/* compute the number of idle process to spawn */
- i = MIN(wp->idle_spawn_rate, wp->config->pm_min_spare_servers - idle);
+ children_to_fork = MIN(wp->idle_spawn_rate, wp->config->pm_min_spare_servers - idle);
/* get sure it won't exceed max_children */
- i = MIN(i, wp->config->pm_max_children - wp->running_children);
- if (i <= 0) {
+ 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) {
- zlog(ZLOG_STUFF, ZLOG_WARNING, "[pool %s] server reached max_children setting (%d), consider raising it", wp->config->name, wp->config->pm_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);
wp->warn_max_children = 1;
}
wp->idle_spawn_rate = 1;
@@ -392,7 +385,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now, struct
}
wp->warn_max_children = 0;
- fpm_children_make(wp, 1, i, 1, base);
+ fpm_children_make(wp, 1, children_to_fork, 1);
/* if it's a child, stop here without creating the next event
* this event is reserved to the master process
@@ -401,7 +394,7 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now, struct
return;
}
- zlog(ZLOG_STUFF, ZLOG_DEBUG, "[pool %s] %d child(ren) have been created dynamically", wp->config->name, i);
+ zlog(ZLOG_DEBUG, "[pool %s] %d child(ren) have been created dynamically", wp->config->name, children_to_fork);
/* Double the spawn rate for the next iteration */
if (wp->idle_spawn_rate < FPM_MAX_SPAWN_RATE) {
@@ -414,37 +407,40 @@ static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now, struct
}
/* }}} */
-void fpm_pctl_heartbeat(int fd, short which, void *arg) /* {{{ */
+void fpm_pctl_heartbeat(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
{
- static struct event heartbeat;
- struct timeval tv = { .tv_sec = 0, .tv_usec = 130000 };
+ static struct fpm_event_s heartbeat;
struct timeval now;
- struct event_base *base = (struct event_base *)arg;
- if (which == EV_TIMEOUT) {
- evtimer_del(&heartbeat);
+ if (fpm_globals.parent_pid != getpid()) {
+ return; /* sanity check */
+ }
+
+ if (which == FPM_EV_TIMEOUT) {
fpm_clock_get(&now);
fpm_pctl_check_request_timeout(&now);
+ return;
}
- evtimer_set(&heartbeat, &fpm_pctl_heartbeat, base);
- event_base_set(base, &heartbeat);
- evtimer_add(&heartbeat, &tv);
+ /* first call without setting to initialize the timer */
+ fpm_event_set_timer(&heartbeat, FPM_EV_PERSIST, &fpm_pctl_heartbeat, NULL);
+ fpm_event_add(&heartbeat, FPM_PCTL_HEARTBEAT);
}
/* }}} */
-void fpm_pctl_perform_idle_server_maintenance_heartbeat(int fd, short which, void *arg) /* {{{ */
+void fpm_pctl_perform_idle_server_maintenance_heartbeat(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
{
- static struct event heartbeat;
- struct timeval tv = { .tv_sec = 0, .tv_usec = FPM_IDLE_SERVER_MAINTENANCE_HEARTBEAT };
+ static struct fpm_event_s heartbeat;
struct timeval now;
- struct event_base *base = (struct event_base *)arg;
- if (which == EV_TIMEOUT) {
- evtimer_del(&heartbeat);
+ if (fpm_globals.parent_pid != getpid()) {
+ return; /* sanity check */
+ }
+
+ if (which == FPM_EV_TIMEOUT) {
fpm_clock_get(&now);
if (fpm_pctl_can_spawn_children()) {
- fpm_pctl_perform_idle_server_maintenance(&now, base);
+ fpm_pctl_perform_idle_server_maintenance(&now);
/* if it's a child, stop here without creating the next event
* this event is reserved to the master process
@@ -453,11 +449,12 @@ void fpm_pctl_perform_idle_server_maintenance_heartbeat(int fd, short which, voi
return;
}
}
+ return;
}
- evtimer_set(&heartbeat, &fpm_pctl_perform_idle_server_maintenance_heartbeat, base);
- event_base_set(base, &heartbeat);
- evtimer_add(&heartbeat, &tv);
+ /* first call without setting which to initialize the timer */
+ fpm_event_set_timer(&heartbeat, FPM_EV_PERSIST, &fpm_pctl_perform_idle_server_maintenance_heartbeat, NULL);
+ fpm_event_add(&heartbeat, FPM_IDLE_SERVER_MAINTENANCE_HEARTBEAT);
}
/* }}} */
diff --git a/sapi/fpm/fpm/fpm_process_ctl.h b/sapi/fpm/fpm/fpm_process_ctl.h
index 8834d5f3b..36577097c 100644
--- a/sapi/fpm/fpm/fpm_process_ctl.h
+++ b/sapi/fpm/fpm/fpm_process_ctl.h
@@ -5,18 +5,22 @@
#ifndef FPM_PROCESS_CTL_H
#define FPM_PROCESS_CTL_H 1
+#include "fpm_events.h"
+
/* spawn max 32 children at once */
#define FPM_MAX_SPAWN_RATE (32)
-/* 1s (in µs here) heatbeat for idle server maintenance */
-#define FPM_IDLE_SERVER_MAINTENANCE_HEARTBEAT (1000000)
+/* 1s (in ms) heartbeat for idle server maintenance */
+#define FPM_IDLE_SERVER_MAINTENANCE_HEARTBEAT (1000)
+/* 130ms heartbeat for pctl */
+#define FPM_PCTL_HEARTBEAT (130)
struct fpm_child_s;
-void fpm_pctl(int new_state, int action, struct event_base *base);
+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_heartbeat(int fd, short which, void *arg);
-void fpm_pctl_perform_idle_server_maintenance_heartbeat(int fd, short which, void *arg);
+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();
int fpm_pctl_init_main();
@@ -38,7 +42,8 @@ enum {
enum {
FPM_PCTL_TERM,
FPM_PCTL_STOP,
- FPM_PCTL_CONT
+ FPM_PCTL_CONT,
+ FPM_PCTL_QUIT
};
#endif
diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c
index 8fff8bea3..590548e57 100644
--- a/sapi/fpm/fpm/fpm_request.c
+++ b/sapi/fpm/fpm/fpm_request.c
@@ -136,7 +136,7 @@ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now,
fpm_trace_signal(child->pid);
- zlog(ZLOG_STUFF, ZLOG_WARNING, "[pool %s] child %d, script '%s' executing too slow (%d.%06d sec), logging",
+ zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' executing too slow (%d.%06d sec), logging",
child->wp->config->name, (int) child->pid, purified_script_filename, (int) tv.tv_sec, (int) tv.tv_usec);
}
else
@@ -145,7 +145,7 @@ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now,
str_purify_filename(purified_script_filename, slot_c.script_filename, sizeof(slot_c.script_filename));
fpm_pctl_kill(child->pid, FPM_PCTL_TERM);
- zlog(ZLOG_STUFF, ZLOG_WARNING, "[pool %s] child %d, script '%s' execution timed out (%d.%06d sec), terminating",
+ zlog(ZLOG_WARNING, "[pool %s] child %d, script '%s' execution timed out (%d.%06d sec), terminating",
child->wp->config->name, (int) child->pid, purified_script_filename, (int) tv.tv_sec, (int) tv.tv_usec);
}
}
@@ -154,16 +154,11 @@ 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_shm_slot_s slot_c;
+ struct fpm_shm_slot_s slot;
- slot = fpm_shm_slot(child);
- if (!fpm_shm_slots_acquire(slot, 1)) {
- return -1;
- }
+ /* no need in atomicity here */
+ slot = *fpm_shm_slot(child);
- slot_c = *slot;
- fpm_shm_slots_release(slot);
- return(!slot_c.accepted.tv_sec && !slot_c.accepted.tv_usec ? 1 : 0);
+ return slot.request_stage == FPM_REQUEST_ACCEPTING;
}
/* }}} */
diff --git a/sapi/fpm/fpm/fpm_shm.c b/sapi/fpm/fpm/fpm_shm.c
index cfacde204..5f4040990 100644
--- a/sapi/fpm/fpm/fpm_shm.c
+++ b/sapi/fpm/fpm/fpm_shm.c
@@ -30,7 +30,7 @@ struct fpm_shm_s *fpm_shm_alloc(size_t sz) /* {{{ */
shm->mem = mmap(0, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
if (!shm->mem) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "mmap(MAP_ANONYMOUS | MAP_SHARED) failed");
+ zlog(ZLOG_SYSERROR, "mmap(MAP_ANONYMOUS | MAP_SHARED) failed");
free(shm);
return 0;
}
diff --git a/sapi/fpm/fpm/fpm_signals.c b/sapi/fpm/fpm/fpm_signals.c
index eb2528b0e..aea69750b 100644
--- a/sapi/fpm/fpm/fpm_signals.c
+++ b/sapi/fpm/fpm/fpm_signals.c
@@ -182,17 +182,17 @@ int fpm_signals_init_main() /* {{{ */
struct sigaction act;
if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "socketpair() failed");
+ zlog(ZLOG_SYSERROR, "socketpair() failed");
return -1;
}
if (0 > fd_set_blocked(sp[0], 0) || 0 > fd_set_blocked(sp[1], 0)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fd_set_blocked() failed");
+ zlog(ZLOG_SYSERROR, "fd_set_blocked() failed");
return -1;
}
if (0 > fcntl(sp[0], F_SETFD, FD_CLOEXEC) || 0 > fcntl(sp[1], F_SETFD, FD_CLOEXEC)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fcntl(F_SETFD, FD_CLOEXEC) failed");
+ zlog(ZLOG_SYSERROR, "fcntl(F_SETFD, FD_CLOEXEC) failed");
return -1;
}
@@ -207,7 +207,7 @@ int fpm_signals_init_main() /* {{{ */
0 > sigaction(SIGCHLD, &act, 0) ||
0 > sigaction(SIGQUIT, &act, 0)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed");
+ zlog(ZLOG_SYSERROR, "sigaction() failed");
return -1;
}
return 0;
@@ -236,7 +236,7 @@ int fpm_signals_init_child() /* {{{ */
0 > sigaction(SIGCHLD, &act_dfl, 0) ||
0 > sigaction(SIGQUIT, &act, 0)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed");
+ zlog(ZLOG_SYSERROR, "sigaction() failed");
return -1;
}
return 0;
diff --git a/sapi/fpm/fpm/fpm_sockets.c b/sapi/fpm/fpm/fpm_sockets.c
index 21baf053c..baa9f9803 100644
--- a/sapi/fpm/fpm/fpm_sockets.c
+++ b/sapi/fpm/fpm/fpm_sockets.c
@@ -49,7 +49,7 @@ static int fpm_sockets_resolve_af_inet(char *node, char *service, struct sockadd
ret = getaddrinfo(node, service, &hints, &res);
if (ret != 0) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "can't resolve hostname '%s%s%s': getaddrinfo said: %s%s%s\n",
+ zlog(ZLOG_ERROR, "can't resolve hostname '%s%s%s': getaddrinfo said: %s%s%s\n",
node, service ? ":" : "", service ? service : "",
gai_strerror(ret), ret == EAI_SYSTEM ? ", system error: " : "", ret == EAI_SYSTEM ? strerror(errno) : "");
return -1;
@@ -65,7 +65,7 @@ enum { FPM_GET_USE_SOCKET = 1, FPM_STORE_SOCKET = 2, FPM_STORE_USE_SOCKET = 3 };
static void fpm_sockets_cleanup(int which, void *arg) /* {{{ */
{
- int i;
+ unsigned i;
char *env_value = 0;
int p = 0;
struct listening_socket_s *ls = sockets_list.data;
@@ -124,7 +124,7 @@ static int fpm_sockets_hash_op(int sock, struct sockaddr *sa, char *key, int typ
case FPM_GET_USE_SOCKET :
{
- int i;
+ unsigned i;
struct listening_socket_s *ls = sockets_list.data;
for (i = 0; i < sockets_list.used; i++, ls++) {
@@ -171,7 +171,7 @@ static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct
sock = socket(sa->sa_family, SOCK_STREAM, 0);
if (0 > sock) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "socket() failed");
+ zlog(ZLOG_SYSERROR, "socket() failed");
return -1;
}
@@ -179,28 +179,32 @@ static int fpm_sockets_new_listening_socket(struct fpm_worker_pool_s *wp, struct
if (wp->listen_address_domain == FPM_AF_UNIX) {
unlink( ((struct sockaddr_un *) sa)->sun_path);
+ saved_umask = umask(0777 ^ wp->socket_mode);
}
- saved_umask = umask(0777 ^ wp->socket_mode);
-
if (0 > bind(sock, sa, socklen)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "bind() for address '%s' failed", wp->config->listen_address);
+ zlog(ZLOG_SYSERROR, "bind() for address '%s' failed", wp->config->listen_address);
+ if (wp->listen_address_domain == FPM_AF_UNIX) {
+ umask(saved_umask);
+ }
return -1;
}
if (wp->listen_address_domain == FPM_AF_UNIX) {
char *path = ((struct sockaddr_un *) sa)->sun_path;
+
+ umask(saved_umask);
+
if (wp->socket_uid != -1 || wp->socket_gid != -1) {
if (0 > chown(path, wp->socket_uid, wp->socket_gid)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "chown() for address '%s' failed", wp->config->listen_address);
+ zlog(ZLOG_SYSERROR, "chown() for address '%s' failed", wp->config->listen_address);
return -1;
}
}
}
- umask(saved_umask);
if (0 > listen(sock, wp->config->listen_backlog)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "listen() for address '%s' failed", wp->config->listen_address);
+ zlog(ZLOG_SYSERROR, "listen() for address '%s' failed", wp->config->listen_address);
return -1;
}
return sock;
@@ -253,7 +257,7 @@ static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /*
}
if (port == 0) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "invalid port value '%s'", port_str);
+ zlog(ZLOG_ERROR, "invalid port value '%s'", port_str);
return -1;
}
@@ -265,7 +269,7 @@ static int fpm_socket_af_inet_listening_socket(struct fpm_worker_pool_s *wp) /*
if (0 > fpm_sockets_resolve_af_inet(addr, NULL, &sa_in)) {
return -1;
}
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "address '%s' resolved as %u.%u.%u.%u", addr, IPQUAD(&sa_in.sin_addr));
+ zlog(ZLOG_NOTICE, "address '%s' resolved as %u.%u.%u.%u", addr, IPQUAD(&sa_in.sin_addr));
}
} else {
sa_in.sin_addr.s_addr = htonl(INADDR_ANY);
@@ -290,7 +294,7 @@ static int fpm_socket_af_unix_listening_socket(struct fpm_worker_pool_s *wp) /*
int fpm_sockets_init_main() /* {{{ */
{
- int i;
+ unsigned i;
struct fpm_worker_pool_s *wp;
char *inherited = getenv("FPM_SOCKETS");
struct listening_socket_s *ls;
@@ -314,7 +318,7 @@ int fpm_sockets_init_main() /* {{{ */
*eq = '\0';
fd_no = atoi(eq + 1);
type = fpm_sockets_domain_from_address(inherited);
- zlog(ZLOG_STUFF, ZLOG_NOTICE, "using inherited socket fd=%d, \"%s\"", fd_no, inherited);
+ zlog(ZLOG_NOTICE, "using inherited socket fd=%d, \"%s\"", fd_no, inherited);
fpm_sockets_hash_op(fd_no, 0, inherited, type, FPM_STORE_SOCKET);
}
@@ -340,6 +344,10 @@ 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;
}
@@ -369,3 +377,76 @@ int fpm_sockets_init_main() /* {{{ */
}
/* }}} */
+#if HAVE_FPM_LQ
+
+#ifdef HAVE_LQ_TCP_INFO
+
+#include <netinet/tcp.h>
+
+int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, 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)) {
+ return -1;
+ }
+
+ /* kernel >= 2.6.24 return non-zero here, that means operation is supported */
+ if (info.tcpi_sacked == 0) {
+ return -1;
+ }
+
+ if (cur_lq) {
+ *cur_lq = info.tcpi_unacked;
+ }
+
+ if (max_lq) {
+ *max_lq = info.tcpi_sacked;
+ }
+
+ return 0;
+}
+
+#endif
+
+#ifdef HAVE_LQ_SO_LISTENQ
+
+int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, 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)) {
+ return -1;
+ }
+
+ *cur_lq = val;
+ }
+
+ if (max_lq) {
+ if (0 > getsockopt(wp->listening_socket, SOL_SOCKET, SO_LISTENQLIMIT, &val, &len)) {
+ return -1;
+ }
+
+ *max_lq = val;
+ }
+
+ return 0;
+}
+
+#endif
+
+#else
+
+int fpm_socket_get_listening_queue(struct fpm_worker_pool_s *wp, unsigned *cur_lq, unsigned *max_lq)
+{
+ return -1;
+}
+
+#endif
diff --git a/sapi/fpm/fpm/fpm_sockets.h b/sapi/fpm/fpm/fpm_sockets.h
index d9e283d5a..b74fc234c 100644
--- a/sapi/fpm/fpm/fpm_sockets.h
+++ b/sapi/fpm/fpm/fpm_sockets.h
@@ -10,8 +10,18 @@
#include "fpm_worker_pool.h"
+/*
+ On FreeBSD and OpenBSD, backlog negative values are truncated to SOMAXCONN
+*/
+#if (__FreeBSD__) || (__OpenBSD__)
+#define FPM_BACKLOG_DEFAULT -1
+#else
+#define FPM_BACKLOG_DEFAULT 128
+#endif
+
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);
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 ebc73cdc6..76daf7d10 100644
--- a/sapi/fpm/fpm/fpm_status.c
+++ b/sapi/fpm/fpm/fpm_status.c
@@ -1,5 +1,5 @@
- /* $Id: fpm_status.c 298380 2010-04-23 15:09:28Z fat $ */
+ /* $Id: fpm_status.c 305281 2010-11-11 21:38:18Z fat $ */
/* (c) 2009 Jerome Loyet */
#include "php.h"
@@ -20,13 +20,13 @@ static char *fpm_status_pong= NULL;
int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
{
if (!wp || !wp->config) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "unable to init fpm_status because conf structure is NULL");
+ 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_STUFF, ZLOG_ERROR, "[pool %s] unable to init fpm_status because the dedicated SHM has not been set", wp->config->name);
+ 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;
@@ -37,7 +37,7 @@ int fpm_status_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
}
if (wp->config->ping_path) {
if (!wp->config->ping_response) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] ping is set (%s) but pong is not set.", wp->config->name, wp->config->ping_path);
+ zlog(ZLOG_ERROR, "[pool %s] ping is set (%s) but pong is not set.", wp->config->name, wp->config->ping_path);
return -1;
}
fpm_status_ping = strdup(wp->config->ping_path);
@@ -99,7 +99,41 @@ void fpm_status_update_accepted_conn(struct fpm_shm_s *shm, unsigned long int ac
}
/* }}} */
-void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int total, int clear_last_update) /* {{{ */
+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;
+
+ status.max_children_reached++;
+
+ /* one shot operation */
+ *(struct fpm_status_s *)shm->mem = status;
+}
+/* }}} */
+
+void fpm_status_update_max_children_reached(struct fpm_shm_s *shm, unsigned int max_children_reached) /* {{{ */
+{
+ 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.max_children_reached = max_children_reached;
+
+ /* 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;
@@ -112,6 +146,8 @@ void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int
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 {
@@ -130,15 +166,30 @@ static void fpm_status_handle_status_txt(struct fpm_status_s *status, char **out
}
spprintf(output, 0,
- "accepted conn: %lu\n"
- "pool: %s\n"
- "process manager: %s\n"
- "idle processes: %d\n"
- "active processes: %d\n"
- "total processes: %d\n",
- status->accepted_conn, fpm_status_pool, status->pm == PM_STYLE_STATIC ? "static" : "dynamic", status->idle, status->active, status->total);
-
- spprintf(content_type, 0, "text/plain");
+ "pool: %s\n"
+ "process manager: %s\n"
+ "accepted conn: %lu\n"
+#if HAVE_FPM_LQ
+ "listen queue len: %u\n"
+ "max listen queue len: %d\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,
+#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: text/plain");
}
/* }}} */
@@ -150,16 +201,31 @@ static void fpm_status_handle_status_html(struct fpm_status_s *status, char **ou
spprintf(output, 0,
"<table>\n"
- "<tr><th>accepted conn</th><td>%lu</td></tr>\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"
+#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"
+#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>",
- status->accepted_conn, fpm_status_pool, status->pm == PM_STYLE_STATIC ? "static" : "dynamic", status->idle, status->active, status->total);
-
- spprintf(content_type, 0, "text/html");
+ 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: text/html");
}
/* }}} */
@@ -171,16 +237,31 @@ static void fpm_status_handle_status_json(struct fpm_status_s *status, char **ou
spprintf(output, 0,
"{"
- "\"accepted conn\":%lu,"
"\"pool\":\"%s\","
"\"process manager\":\"%s\","
+ "\"accepted conn\":%lu,"
+#if HAVE_FPM_LQ
+ "\"listen queue len\":%u,"
+ "\"max listen queue len\":%d,"
+#endif
"\"idle processes\":%d,"
"\"active processes\":%d,"
- "\"total processes\":%d"
+ "\"total processes\":%d,"
+ "\"max children reached\":%u"
"}",
- status->accepted_conn, fpm_status_pool, status->pm == PM_STYLE_STATIC ? "static" : "dynamic", status->idle, status->active, status->total);
-
- spprintf(content_type, 0, "application/jsonrequest");
+ 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");
}
/* }}} */
@@ -226,7 +307,7 @@ int fpm_status_handle_status(char *uri, char *query_string, char **output, char
}
if (!*output || !content_type) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] unable to allocate status ouput buffer", fpm_status_pool);
+ zlog(ZLOG_ERROR, "[pool %s] unable to allocate status ouput buffer", fpm_status_pool);
return 1;
}
diff --git a/sapi/fpm/fpm/fpm_status.h b/sapi/fpm/fpm/fpm_status.h
index a079bd0df..4e9c50705 100644
--- a/sapi/fpm/fpm/fpm_status.h
+++ b/sapi/fpm/fpm/fpm_status.h
@@ -1,5 +1,5 @@
- /* $Id: fpm_status.h 298380 2010-04-23 15:09:28Z fat $ */
+ /* $Id: fpm_status.h 305267 2010-11-11 02:34:47Z fat $ */
/* (c) 2009 Jerome Loyet */
#ifndef FPM_STATUS_H
@@ -14,15 +14,20 @@ struct fpm_status_s {
int idle;
int active;
int total;
+ unsigned cur_lq;
+ int max_lq;
unsigned long int accepted_conn;
+ unsigned int max_children_reached;
struct timeval last_update;
};
int fpm_status_init_child(struct fpm_worker_pool_s *wp);
-void fpm_status_update_activity(struct fpm_shm_s *shm, int idle, int active, int total, int clear_last_update);
+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);
void fpm_status_update_accepted_conn(struct fpm_shm_s *shm, unsigned long int accepted_conn);
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);
diff --git a/sapi/fpm/fpm/fpm_stdio.c b/sapi/fpm/fpm/fpm_stdio.c
index d18e1d532..571f3074b 100644
--- a/sapi/fpm/fpm/fpm_stdio.c
+++ b/sapi/fpm/fpm/fpm_stdio.c
@@ -26,12 +26,12 @@ int fpm_stdio_init_main() /* {{{ */
int fd = open("/dev/null", O_RDWR);
if (0 > fd) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(\"/dev/null\") failed");
+ zlog(ZLOG_SYSERROR, "open(\"/dev/null\") failed");
return -1;
}
if (0 > dup2(fd, STDIN_FILENO) || 0 > dup2(fd, STDOUT_FILENO)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "dup2() failed");
+ zlog(ZLOG_SYSERROR, "dup2() failed");
return -1;
}
close(fd);
@@ -41,17 +41,16 @@ int fpm_stdio_init_main() /* {{{ */
int fpm_stdio_init_final() /* {{{ */
{
- zlog_set_level(fpm_globals.log_level);
if (fpm_global_config.daemonize) {
if (fpm_globals.error_log_fd != STDERR_FILENO) {
/* there might be messages to stderr from libevent, we need to log them all */
if (0 > dup2(fpm_globals.error_log_fd, STDERR_FILENO)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "dup2() failed");
+ zlog(ZLOG_SYSERROR, "dup2() failed");
return -1;
}
}
- zlog_set_fd(fpm_globals.error_log_fd);
}
+ zlog_set_launched();
return 0;
}
/* }}} */
@@ -64,7 +63,7 @@ int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
if (wp->listening_socket != STDIN_FILENO) {
if (0 > dup2(wp->listening_socket, STDIN_FILENO)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "dup2() failed");
+ zlog(ZLOG_SYSERROR, "dup2() failed");
return -1;
}
}
@@ -72,18 +71,30 @@ int fpm_stdio_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
}
/* }}} */
-static void fpm_stdio_child_said(int fd, short which, void *arg) /* {{{ */
+static void fpm_stdio_child_said(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
{
static const int max_buf_size = 1024;
+ int fd = ev->fd;
char buf[max_buf_size];
- struct fpm_child_s *child = arg;
- int is_stdout = fd == child->fd_stdout;
- struct event *ev = is_stdout ? &child->ev_stdout : &child->ev_stderr;
+ struct fpm_child_s *child;
+ int is_stdout;
+ struct fpm_event_s *event;
int fifo_in = 1, fifo_out = 1;
int is_last_message = 0;
int in_buf = 0;
int res;
+ if (!arg) {
+ return;
+ }
+ child = (struct fpm_child_s *)arg;
+ is_stdout = (fd == child->fd_stdout);
+ if (is_stdout) {
+ event = &child->ev_stdout;
+ } else {
+ event = &child->ev_stderr;
+ }
+
while (fifo_in || fifo_out) {
if (fifo_in) {
res = read(fd, buf + in_buf, max_buf_size - 1 - in_buf);
@@ -94,10 +105,10 @@ static void fpm_stdio_child_said(int fd, short which, void *arg) /* {{{ */
} else { /* error or pipe is closed */
if (res < 0) { /* error */
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed");
+ zlog(ZLOG_SYSERROR, "read() failed");
}
- fpm_event_del(ev);
+ fpm_event_del(event);
is_last_message = 1;
if (is_stdout) {
@@ -140,7 +151,7 @@ static void fpm_stdio_child_said(int fd, short which, void *arg) /* {{{ */
*nl = '\0';
}
- zlog(ZLOG_STUFF, ZLOG_WARNING, "[pool %s] child %d said into %s: \"%s\"%s", child->wp->config->name,
+ zlog(ZLOG_WARNING, "[pool %s] child %d said into %s: \"%s\"%s", child->wp->config->name,
(int) child->pid, is_stdout ? "stdout" : "stderr", buf, is_last_message ? ", pipe is closed" : "");
if (nl) {
@@ -164,18 +175,18 @@ int fpm_stdio_prepare_pipes(struct fpm_child_s *child) /* {{{ */
}
if (0 > pipe(fd_stdout)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pipe() failed");
+ zlog(ZLOG_SYSERROR, "pipe() failed");
return -1;
}
if (0 > pipe(fd_stderr)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pipe() failed");
+ zlog(ZLOG_SYSERROR, "pipe() failed");
close(fd_stdout[0]); close(fd_stdout[1]);
return -1;
}
if (0 > fd_set_blocked(fd_stdout[0], 0) || 0 > fd_set_blocked(fd_stderr[0], 0)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fd_set_blocked() failed");
+ zlog(ZLOG_SYSERROR, "fd_set_blocked() failed");
close(fd_stdout[0]); close(fd_stdout[1]);
close(fd_stderr[0]); close(fd_stderr[1]);
return -1;
@@ -184,7 +195,7 @@ int fpm_stdio_prepare_pipes(struct fpm_child_s *child) /* {{{ */
}
/* }}} */
-int fpm_stdio_parent_use_pipes(struct fpm_child_s *child, struct event_base *base) /* {{{ */
+int fpm_stdio_parent_use_pipes(struct fpm_child_s *child) /* {{{ */
{
if (0 == child->wp->config->catch_workers_output) { /* not required */
return 0;
@@ -196,8 +207,11 @@ int fpm_stdio_parent_use_pipes(struct fpm_child_s *child, struct event_base *bas
child->fd_stdout = fd_stdout[0];
child->fd_stderr = fd_stderr[0];
- fpm_event_add(child->fd_stdout, base, &child->ev_stdout, fpm_stdio_child_said, child);
- fpm_event_add(child->fd_stderr, base, &child->ev_stderr, fpm_stdio_child_said, child);
+ fpm_event_set(&child->ev_stdout, child->fd_stdout, FPM_EV_READ, fpm_stdio_child_said, child);
+ fpm_event_add(&child->ev_stdout, 0);
+
+ fpm_event_set(&child->ev_stderr, child->fd_stderr, FPM_EV_READ, fpm_stdio_child_said, child);
+ fpm_event_add(&child->ev_stderr, 0);
return 0;
}
/* }}} */
@@ -237,7 +251,7 @@ int fpm_stdio_open_error_log(int reopen) /* {{{ */
fd = open(fpm_global_config.error_log, O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
if (0 > fd) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(\"%s\") failed", fpm_global_config.error_log);
+ zlog(ZLOG_SYSERROR, "open(\"%s\") failed", fpm_global_config.error_log);
return -1;
}
@@ -251,6 +265,9 @@ int fpm_stdio_open_error_log(int reopen) /* {{{ */
fd = fpm_globals.error_log_fd; /* for FD_CLOSEXEC to work */
} else {
fpm_globals.error_log_fd = fd;
+ if (fpm_global_config.daemonize) {
+ zlog_set_fd(fpm_globals.error_log_fd);
+ }
}
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
return 0;
diff --git a/sapi/fpm/fpm/fpm_stdio.h b/sapi/fpm/fpm/fpm_stdio.h
index 5d53a26e8..d3d61e46b 100644
--- a/sapi/fpm/fpm/fpm_stdio.h
+++ b/sapi/fpm/fpm/fpm_stdio.h
@@ -12,7 +12,7 @@ int fpm_stdio_init_final();
int fpm_stdio_init_child(struct fpm_worker_pool_s *wp);
int fpm_stdio_prepare_pipes(struct fpm_child_s *child);
void fpm_stdio_child_use_pipes(struct fpm_child_s *child);
-int fpm_stdio_parent_use_pipes(struct fpm_child_s *child, struct event_base *base);
+int fpm_stdio_parent_use_pipes(struct fpm_child_s *child);
int fpm_stdio_discard_pipes(struct fpm_child_s *child);
int fpm_stdio_open_error_log(int reopen);
diff --git a/sapi/fpm/fpm/fpm_trace_mach.c b/sapi/fpm/fpm/fpm_trace_mach.c
index 47b44ff82..fe26fd9e2 100644
--- a/sapi/fpm/fpm/fpm_trace_mach.c
+++ b/sapi/fpm/fpm/fpm_trace_mach.c
@@ -37,7 +37,7 @@ static int fpm_mach_vm_read_page(vm_offset_t page) /* {{{ */
kr = mach_vm_read(target, page, fpm_pagesize, &local_page, &local_size);
if (kr != KERN_SUCCESS) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "mach_vm_read() failed: %s (%d)", mach_error_string(kr), kr);
+ zlog(ZLOG_ERROR, "mach_vm_read() failed: %s (%d)", mach_error_string(kr), kr);
return -1;
}
return 0;
@@ -47,7 +47,7 @@ static int fpm_mach_vm_read_page(vm_offset_t page) /* {{{ */
int fpm_trace_signal(pid_t pid) /* {{{ */
{
if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "kill(SIGSTOP) failed");
+ zlog(ZLOG_SYSERROR, "kill(SIGSTOP) failed");
return -1;
}
return 0;
@@ -65,7 +65,7 @@ int fpm_trace_ready(pid_t pid) /* {{{ */
if (kr == KERN_FAILURE) {
msg = " It seems that master process does not have enough privileges to trace processes.";
}
- zlog(ZLOG_STUFF, ZLOG_ERROR, "task_for_pid() failed: %s (%d)%s", mach_error_string(kr), kr, msg);
+ zlog(ZLOG_ERROR, "task_for_pid() failed: %s (%d)%s", mach_error_string(kr), kr, msg);
return -1;
}
return 0;
diff --git a/sapi/fpm/fpm/fpm_trace_pread.c b/sapi/fpm/fpm/fpm_trace_pread.c
index d2f7e5a05..eda84928e 100644
--- a/sapi/fpm/fpm/fpm_trace_pread.c
+++ b/sapi/fpm/fpm/fpm_trace_pread.c
@@ -26,7 +26,7 @@ static int mem_file = -1;
int fpm_trace_signal(pid_t pid) /* {{{ */
{
if (0 > fpm_pctl_kill(pid, FPM_PCTL_STOP)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "kill(SIGSTOP) failed");
+ zlog(ZLOG_SYSERROR, "kill(SIGSTOP) failed");
return -1;
}
return 0;
@@ -40,7 +40,7 @@ int fpm_trace_ready(pid_t pid) /* {{{ */
sprintf(buf, "/proc/%d/" PROC_MEM_FILE, (int) pid);
mem_file = open(buf, O_RDONLY);
if (0 > mem_file) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "open(%s) failed", buf);
+ zlog(ZLOG_SYSERROR, "open(%s) failed", buf);
return -1;
}
return 0;
@@ -58,7 +58,7 @@ int fpm_trace_close(pid_t pid) /* {{{ */
int fpm_trace_get_long(long addr, long *data) /* {{{ */
{
if (sizeof(*data) != pread(mem_file, (void *) data, sizeof(*data), (uintptr_t) addr)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "pread() failed");
+ zlog(ZLOG_SYSERROR, "pread() failed");
return -1;
}
return 0;
diff --git a/sapi/fpm/fpm/fpm_trace_ptrace.c b/sapi/fpm/fpm/fpm_trace_ptrace.c
index 86cf52830..395c1ac08 100644
--- a/sapi/fpm/fpm/fpm_trace_ptrace.c
+++ b/sapi/fpm/fpm/fpm_trace_ptrace.c
@@ -29,7 +29,7 @@ static pid_t traced_pid;
int fpm_trace_signal(pid_t pid) /* {{{ */
{
if (0 > ptrace(PTRACE_ATTACH, pid, 0, 0)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(ATTACH) failed");
+ zlog(ZLOG_SYSERROR, "ptrace(ATTACH) failed");
return -1;
}
return 0;
@@ -46,7 +46,7 @@ int fpm_trace_ready(pid_t pid) /* {{{ */
int fpm_trace_close(pid_t pid) /* {{{ */
{
if (0 > ptrace(PTRACE_DETACH, pid, (void *) 1, 0)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(DETACH) failed");
+ zlog(ZLOG_SYSERROR, "ptrace(DETACH) failed");
return -1;
}
traced_pid = 0;
@@ -65,14 +65,14 @@ int fpm_trace_get_long(long addr, long *data) /* {{{ */
};
if (0 > ptrace(PT_IO, traced_pid, (void *) &ptio, 0)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(PT_IO) failed");
+ zlog(ZLOG_SYSERROR, "ptrace(PT_IO) failed");
return -1;
}
#else
errno = 0;
*data = ptrace(PTRACE_PEEKDATA, traced_pid, (void *) addr, 0);
if (errno) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "ptrace(PEEKDATA) failed");
+ zlog(ZLOG_SYSERROR, "ptrace(PEEKDATA) failed");
return -1;
}
#endif
diff --git a/sapi/fpm/fpm/fpm_unix.c b/sapi/fpm/fpm/fpm_unix.c
index 395d703d1..d63ea4d5b 100644
--- a/sapi/fpm/fpm/fpm_unix.c
+++ b/sapi/fpm/fpm/fpm_unix.c
@@ -45,7 +45,7 @@ int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp) /* {{{ */
pwd = getpwnam(c->listen_owner);
if (!pwd) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, c->listen_owner);
+ zlog(ZLOG_SYSERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, c->listen_owner);
return -1;
}
@@ -58,7 +58,7 @@ int fpm_unix_resolve_socket_premissions(struct fpm_worker_pool_s *wp) /* {{{ */
grp = getgrnam(c->listen_group);
if (!grp) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, c->listen_group);
+ zlog(ZLOG_SYSERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, c->listen_group);
return -1;
}
wp->socket_gid = grp->gr_gid;
@@ -84,7 +84,7 @@ static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */
pwd = getpwnam(wp->config->user);
if (!pwd) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, wp->config->user);
+ zlog(ZLOG_ERROR, "[pool %s] cannot get uid for user '%s'", wp->config->name, wp->config->user);
return -1;
}
@@ -104,7 +104,7 @@ static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */
grp = getgrnam(wp->config->group);
if (!grp) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, wp->config->group);
+ zlog(ZLOG_ERROR, "[pool %s] cannot get gid for group '%s'", wp->config->name, wp->config->group);
return -1;
}
wp->set_gid = grp->gr_gid;
@@ -113,19 +113,19 @@ static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */
#ifndef I_REALLY_WANT_ROOT_PHP
if (wp->set_uid == 0 || wp->set_gid == 0) {
- zlog(ZLOG_STUFF, ZLOG_ERROR, "[pool %s] please specify user and group other than root", wp->config->name);
+ zlog(ZLOG_ERROR, "[pool %s] please specify user and group other than root", wp->config->name);
return -1;
}
#endif
} else { /* not root */
if (wp->config->user && *wp->config->user) {
- zlog(ZLOG_STUFF, ZLOG_WARNING, "[pool %s] 'user' directive is ignored", wp->config->name);
+ zlog(ZLOG_WARNING, "[pool %s] 'user' directive is ignored", wp->config->name);
}
if (wp->config->group && *wp->config->group) {
- zlog(ZLOG_STUFF, ZLOG_WARNING, "[pool %s] 'group' directive is ignored", wp->config->name);
+ zlog(ZLOG_WARNING, "[pool %s] 'group' directive is ignored", wp->config->name);
}
if (wp->config->chroot && *wp->config->chroot) {
- zlog(ZLOG_STUFF, ZLOG_WARNING, "[pool %s] 'chroot' directive is ignored", wp->config->name);
+ zlog(ZLOG_WARNING, "[pool %s] 'chroot' directive is ignored", wp->config->name);
}
{ /* set up HOME and USER anyway */
@@ -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_STUFF, ZLOG_SYSERROR, "[pool %s] setrlimit(RLIMIT_NOFILE, %d) failed (%d)", wp->config->name, wp->config->rlimit_files, errno);
+ zlog(ZLOG_SYSERROR, "[pool %s] setrlimit(RLIMIT_NOFILE, %d) failed (%d)", wp->config->name, wp->config->rlimit_files, errno);
}
}
@@ -163,13 +163,13 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
r.rlim_max = r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core;
if (0 > setrlimit(RLIMIT_CORE, &r)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] setrlimit(RLIMIT_CORE, %d) failed (%d)", wp->config->name, wp->config->rlimit_core, errno);
+ zlog(ZLOG_SYSERROR, "[pool %s] setrlimit(RLIMIT_CORE, %d) failed (%d)", wp->config->name, wp->config->rlimit_core, errno);
}
}
if (is_root && wp->config->chroot && *wp->config->chroot) {
if (0 > chroot(wp->config->chroot)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] chroot(%s) failed", wp->config->name, wp->config->chroot);
+ zlog(ZLOG_SYSERROR, "[pool %s] chroot(%s) failed", wp->config->name, wp->config->chroot);
return -1;
}
made_chroot = 1;
@@ -177,7 +177,7 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
if (wp->config->chdir && *wp->config->chdir) {
if (0 > chdir(wp->config->chdir)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] chdir(%s) failed", wp->config->name, wp->config->chdir);
+ zlog(ZLOG_SYSERROR, "[pool %s] chdir(%s) failed", wp->config->name, wp->config->chdir);
return -1;
}
} else if (made_chroot) {
@@ -187,17 +187,17 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
if (is_root) {
if (wp->set_gid) {
if (0 > setgid(wp->set_gid)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] setgid(%d) failed", wp->config->name, wp->set_gid);
+ zlog(ZLOG_SYSERROR, "[pool %s] setgid(%d) failed", wp->config->name, wp->set_gid);
return -1;
}
}
if (wp->set_uid) {
if (0 > initgroups(wp->config->user, wp->set_gid)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] initgroups(%s, %d) failed", wp->config->name, wp->config->user, wp->set_gid);
+ zlog(ZLOG_SYSERROR, "[pool %s] initgroups(%s, %d) failed", wp->config->name, wp->config->user, wp->set_gid);
return -1;
}
if (0 > setuid(wp->set_uid)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] setuid(%d) failed", wp->config->name, wp->set_uid);
+ zlog(ZLOG_SYSERROR, "[pool %s] setuid(%d) failed", wp->config->name, wp->set_uid);
return -1;
}
}
@@ -205,7 +205,7 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
#ifdef HAVE_PRCTL
if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) {
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] prctl(PR_SET_DUMPABLE) failed", wp->config->name);
+ zlog(ZLOG_SYSERROR, "[pool %s] prctl(PR_SET_DUMPABLE) failed", wp->config->name);
}
#endif
@@ -224,7 +224,7 @@ int fpm_unix_init_main() /* {{{ */
if (fpm_global_config.daemonize) {
switch (fork()) {
case -1 :
- zlog(ZLOG_STUFF, ZLOG_SYSERROR, "daemonized fork() failed");
+ zlog(ZLOG_SYSERROR, "daemonized fork() failed");
return -1;
case 0 :
break;
@@ -246,7 +246,7 @@ int fpm_unix_init_main() /* {{{ */
}
}
- fpm_stdio_init_final();
+ zlog_set_level(fpm_globals.log_level);
return 0;
}
/* }}} */
diff --git a/sapi/fpm/fpm/fpm_worker_pool.h b/sapi/fpm/fpm/fpm_worker_pool.h
index 63aff9a55..7f240a20c 100644
--- a/sapi/fpm/fpm/fpm_worker_pool.h
+++ b/sapi/fpm/fpm/fpm_worker_pool.h
@@ -25,6 +25,7 @@ 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;
diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c
index fc3c0168e..b99ad850d 100644
--- a/sapi/fpm/fpm/zlog.c
+++ b/sapi/fpm/fpm/zlog.c
@@ -18,6 +18,7 @@
static int zlog_fd = -1;
static int zlog_level = ZLOG_NOTICE;
+static int launched = 0;
static const char *level_names[] = {
[ZLOG_DEBUG] = "DEBUG",
@@ -27,6 +28,16 @@ static const char *level_names[] = {
[ZLOG_ALERT] = "ALERT",
};
+const char *zlog_get_level_name() /* {{{ */
+{
+ return level_names[zlog_level];
+}
+/* }}} */
+
+void zlog_set_launched(void) {
+ launched = 1;
+}
+
size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len) /* {{{ */
{
struct tm t;
@@ -58,7 +69,7 @@ int zlog_set_level(int new_value) /* {{{ */
}
/* }}} */
-void zlog(const char *function, int line, int flags, const char *fmt, ...) /* {{{ */
+void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* {{{ */
{
struct timeval tv;
char buf[MAX_LINE_LENGTH];
@@ -110,6 +121,9 @@ void zlog(const char *function, int line, int flags, const char *fmt, ...) /* {{
buf[len++] = '\n';
write(zlog_fd > -1 ? zlog_fd : STDERR_FILENO, buf, len);
+ if (zlog_fd != STDERR_FILENO && zlog_fd > -1 && !launched && (flags & ZLOG_LEVEL_MASK) >= ZLOG_NOTICE) {
+ write(STDERR_FILENO, buf, len);
+ }
}
/* }}} */
diff --git a/sapi/fpm/fpm/zlog.h b/sapi/fpm/fpm/zlog.h
index b5ac3d9bc..598c075e3 100644
--- a/sapi/fpm/fpm/zlog.h
+++ b/sapi/fpm/fpm/zlog.h
@@ -5,16 +5,18 @@
#ifndef ZLOG_H
#define ZLOG_H 1
-#define ZLOG_STUFF __func__, __LINE__
+#define zlog(flags,...) zlog_ex(__func__, __LINE__, flags, __VA_ARGS__)
struct timeval;
int zlog_set_fd(int new_fd);
int zlog_set_level(int new_value);
+const char *zlog_get_level_name();
+void zlog_set_launched(void);
size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len);
-void zlog(const char *function, int line, int flags, const char *fmt, ...)
+void zlog_ex(const char *function, int line, int flags, const char *fmt, ...)
__attribute__ ((format(printf,4,5)));
enum {
diff --git a/sapi/fpm/init.d.php-fpm.in b/sapi/fpm/init.d.php-fpm.in
index dfeb69aeb..766d10207 100644
--- a/sapi/fpm/init.d.php-fpm.in
+++ b/sapi/fpm/init.d.php-fpm.in
@@ -2,8 +2,8 @@
### BEGIN INIT INFO
# Provides: php-fpm
-# Required-Start: $all
-# Required-Stop: $all
+# Required-Start: $remote_fs $network
+# Required-Stop: $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts php-fpm
diff --git a/sapi/fpm/php-fpm.1.in b/sapi/fpm/php-fpm.8.in
index 3e940da1d..6c9c6d627 100644
--- a/sapi/fpm/php-fpm.1.in
+++ b/sapi/fpm/php-fpm.8.in
@@ -1,4 +1,4 @@
-.TH PHP-FPM 1 "2009" "The PHP Group" "Scripting Language"
+.TH PHP-FPM 8 "2009" "The PHP Group" "Scripting Language"
.SH NAME
.TP 15
php-fpm \- PHP FastCGI Process Manager 'PHP-FPM'
@@ -77,15 +77,28 @@ Show compiled in modules
.PD 1
.B \-v
Version number
+.B \-\-prefix \fIpath\fP
+.TP
+.PD 1
+.B \-p
+Specify alternative prefix path (the default is @php_fpm_prefix@)
.TP
.PD 0
.B \-\-fpm\-config \fIfile\fP
.TP
.PD 1
-.B \-\-y
+.B \-y
Specify alternative path to FastCGI process manager configuration file (the default is @php_fpm_sysconfdir@/php-fpm.conf)
.TP
.PD 0
+.B \-\-test
+.TP
+.PD 1
+.B \-t
+Test FPM configuration file and exit
+If called twice (-tt), the configuration is dumped before exiting.
+.TP
+.PD 0
.B \-\-zend\-extension \fIfile\fP
.TP
.PD 1
@@ -164,7 +177,7 @@ A List of active developers can be found here:
And last but not least PHP was developed with the help of a huge amount of
contributors all around the world.
.SH VERSION INFORMATION
-This manpage describes \fBphp\fP, version @PHP_VERSION@, \fBfpm\fP, version @fpm_version@.
+This manpage describes \fBphp-fpm\fP, version @PHP_VERSION@.
.SH COPYRIGHT
Copyright \(co 1997\-2009 The PHP Group
.PD 0
diff --git a/sapi/fpm/php-fpm.conf.in b/sapi/fpm/php-fpm.conf.in
index 15024982b..314b7e5c5 100644
--- a/sapi/fpm/php-fpm.conf.in
+++ b/sapi/fpm/php-fpm.conf.in
@@ -3,12 +3,16 @@
;;;;;;;;;;;;;;;;;;;;;
; All relative paths in this configuration file are relative to PHP's install
-; prefix.
+; prefix (@prefix@). This prefix can be dynamicaly changed by using the
+; '-p' argument from the command line.
; Include one or more files. If glob(3) exists, it is used to include a bunch of
; files from a glob(3) pattern. This directive can be used everywhere in the
; file.
-;include=@EXPANDED_SYSCONFDIR@/fpm.d/*.conf
+; Relative path can also be used. They will be prefixed by:
+; - the global prefix if it's been set (-p arguement)
+; - @prefix@ otherwise
+;include=etc/fpm.d/*.conf
;;;;;;;;;;;;;;;;;;
; Global Options ;
@@ -16,12 +20,14 @@
[global]
; Pid file
+; Note: the default prefix is @EXPANDED_LOCALSTATEDIR@
; Default Value: none
-;pid = @EXPANDED_LOCALSTATEDIR@/run/php-fpm.pid
+;pid = run/php-fpm.pid
; Error log file
-; Default Value: @EXPANDED_LOCALSTATEDIR@/log/php-fpm.log
-;error_log = @EXPANDED_LOCALSTATEDIR@/log/php-fpm.log
+; Note: the default prefix is @EXPANDED_LOCALSTATEDIR@
+; Default Value: log/php-fpm.log
+;error_log = log/php-fpm.log
; Log level
; Possible Values: alert, error, warning, notice, debug
@@ -62,8 +68,23 @@
; FPM can handle. Your system will tell you anyway :)
; Start a new pool named 'www'.
+; the variable $pool can we used in any directive and will be replaced by the
+; pool name ('www' here)
[www]
+; Per pool prefix
+; It only applies on the following directives:
+; - 'slowlog'
+; - 'listen' (unixsocket)
+; - 'chroot'
+; - 'chdir'
+; - 'php_values'
+; - 'php_admin_values'
+; When not set, the global prefix (or @php_fpm_prefix@) applies instead.
+; Note: This directive can also be relative to the global prefix.
+; Default Value: none
+;prefix = /path/to/pools/$pool
+
; The address on which to accept FastCGI requests.
; Valid syntaxes are:
; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific address on
@@ -75,7 +96,7 @@
listen = 127.0.0.1:9000
; Set listen(2) backlog. A value of '-1' means unlimited.
-; Default Value: -1
+; Default Value: 128 (-1 on FreeBSD and OpenBSD)
;listen.backlog = -1
; List of ipv4 addresses of FastCGI clients which are allowed to connect.
@@ -154,21 +175,25 @@ pm.max_children = 50
; The URI to view the FPM status page. If this value is not set, no URI will be
; recognized as a status page. By default, the status page shows the following
; information:
-; accepted conn - the number of request accepted by the pool;
-; pool - the name of the pool;
-; process manager - static or dynamic;
-; idle processes - the number of idle processes;
-; active processes - the number of active processes;
-; total processes - the number of idle + active processes.
+; accepted conn - the number of request accepted by the pool;
+; pool - the name of the pool;
+; process manager - static or dynamic;
+; idle processes - the number of idle processes;
+; active processes - the number of active processes;
+; total processes - the number of idle + active processes.
+; max children reached - number of times, the process limit has been reached,
+; when pm tries to start more children (works only for
+; pm 'dynamic')
; The values of 'idle processes', 'active processes' and 'total processes' are
; updated each second. The value of 'accepted conn' is updated in real time.
; Example output:
-; accepted conn: 12073
-; pool: www
-; process manager: static
-; idle processes: 35
-; active processes: 65
-; total processes: 100
+; accepted conn: 12073
+; pool: www
+; process manager: static
+; idle processes: 35
+; active processes: 65
+; 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
; syntax. Example:
@@ -212,8 +237,9 @@ pm.max_children = 50
;request_slowlog_timeout = 0
; The log file for slow requests
-; Default Value: @EXPANDED_LOCALSTATEDIR@/log/php-fpm.log.slow
-;slowlog = @EXPANDED_LOCALSTATEDIR@/log/php-fpm.log.slow
+; Default Value: not set
+; Note: slowlog is mandatory if request_slowlog_timeout is set
+;slowlog = log/$pool.log.slow
; Set open file descriptor rlimit.
; Default Value: system defined value
@@ -226,18 +252,24 @@ pm.max_children = 50
; Chroot to this directory at the start. This value must be defined as an
; absolute path. When this value is not set, chroot is not used.
+; Note: you can prefix with '$prefix' to chroot to the pool prefix or one
+; of its subdirectories. If the pool prefix is not set, the global prefix
+; will be used instead.
; Note: chrooting is a great security feature and should be used whenever
; possible. However, all PHP paths will be relative to the chroot
; (error_log, sessions.save_path, ...).
; Default Value: not set
;chroot =
-; Chdir to this directory at the start. This value must be an absolute path.
+; Chdir to this directory at the start.
+; Note: relative path can be used.
; Default Value: current directory or / when chroot
;chdir = /var/www
; Redirect worker stdout and stderr into main error log. If not set, stdout and
; stderr will be redirected to /dev/null according to FastCGI specs.
+; Note: on highloaded environement, this can cause some delay in the page
+; process time (several ms).
; Default Value: no
;catch_workers_output = yes
@@ -264,6 +296,9 @@ pm.max_children = 50
; overwrite previously defined php.ini values, but will append the new value
; instead.
+; Note: path INI options can be relative and will be expanded with the prefix
+; (pool, global or @prefix@)
+
; Default Value: nothing is defined by default except the values in php.ini and
; specified at startup with the -d argument
;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com