Commit: 0e99329e0aa8bbfe1b6d0ad06660630538118e2f
Author: Remi Collet <r...@php.net> Tue, 21 May 2013 09:49:00 +0200
Parents: 77fffff15762137e2d8173df9b733b4cb70fc996
Branches: PHP-5.4
Link:
http://git.php.net/?p=php-src.git;a=commitdiff;h=0e99329e0aa8bbfe1b6d0ad06660630538118e2f
Log:
Add --with-fpm-systemd option to report health to systemd, and
systemd_interval option to configure this. The service can now use
Type=notify in the systemd unit file.
Systemd status line will looks like:
Status: "Processes active: 0, idle: 5, Requests: 90, slow: 0, Traffic:
10req/sec"
Watchdog mode is also supported. In this case watchdog interval,
configured in the unit file, override the systemd_interval option.
When not used (default), no change from previous version.
Changed paths:
M NEWS
M sapi/fpm/config.m4
M sapi/fpm/fpm/fpm_conf.c
M sapi/fpm/fpm/fpm_conf.h
M sapi/fpm/fpm/fpm_events.c
A sapi/fpm/fpm/fpm_systemd.c
A sapi/fpm/fpm/fpm_systemd.h
M sapi/fpm/php-fpm.conf.in
M sapi/fpm/php-fpm.service.in
diff --git a/NEWS b/NEWS
index 5bf6872..227fcac 100644
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,9 @@ PHP
NEWS
. Fixed some possible memory or resource leaks and possible null dereference
detected by code coverity scan. (Remi)
. Log a warning when a syscall fails. (Remi)
+ . Add --with-fpm-systemd option to report health to systemd, and
+ systemd_interval option to configure this. The service can now use
+ Type=notify in the systemd unit file. (Remi)
- SNMP:
. Fixed bug #64765 (Some IPv6 addresses get interpreted wrong).
diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4
index 6191c32..579f7c2 100644
--- a/sapi/fpm/config.m4
+++ b/sapi/fpm/config.m4
@@ -563,6 +563,26 @@ if test "$PHP_FPM" != "no"; then
[ --with-fpm-group[=GRP] Set the group for php-fpm to run as. For a system
user, this
should usually be set to match the fpm username (default:
nobody)], nobody, no)
+ PHP_ARG_WITH(fpm-systemd,,
+ [ --with-fpm-systemd Activate systemd integration], no, no)
+
+ if test "$PHP_FPM_SYSTEMD" != "no" ; then
+ AC_CHECK_LIB(systemd-daemon, sd_notify, SYSTEMD_LIBS="-lsystemd-daemon")
+ AC_CHECK_HEADERS(systemd/sd-daemon.h, [HAVE_SD_DAEMON_H="yes"],
[HAVE_SD_DAEMON_H="no"])
+ if test $HAVE_SD_DAEMON_H = "no" || test -z "${SYSTEMD_LIBS}"; then
+ AC_MSG_ERROR([Your system does not support systemd.])
+ else
+ AC_DEFINE(HAVE_SYSTEMD, 1, [FPM use systemd integration])
+ PHP_FPM_SD_FILES="fpm/fpm_systemd.c"
+ PHP_ADD_LIBRARY(systemd-daemon)
+ php_fpm_systemd=notify
+ fi
+ else
+ php_fpm_systemd=simple
+ fi
+ PHP_SUBST_OLD(php_fpm_systemd)
+ AC_DEFINE_UNQUOTED(PHP_FPM_SYSTEMD, "$php_fpm_systemd", [fpm systemd service
type])
+
if test -z "$PHP_FPM_USER" -o "$PHP_FPM_USER" = "yes" -o "$PHP_FPM_USER" =
"no"; then
php_fpm_user="nobody"
else
@@ -635,7 +655,7 @@ if test "$PHP_FPM" != "no"; then
fpm/events/port.c \
"
- PHP_SELECT_SAPI(fpm, program, $PHP_FPM_FILES $PHP_FPM_TRACE_FILES,
$PHP_FPM_CFLAGS, '$(SAPI_FPM_PATH)')
+ PHP_SELECT_SAPI(fpm, program, $PHP_FPM_FILES $PHP_FPM_TRACE_FILES
$PHP_FPM_SD_FILES, $PHP_FPM_CFLAGS, '$(SAPI_FPM_PATH)')
case $host_alias in
*aix*)
diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c
index 0a8a0e3..d85df18 100644
--- a/sapi/fpm/fpm/fpm_conf.c
+++ b/sapi/fpm/fpm/fpm_conf.c
@@ -45,6 +45,10 @@
#include "fpm_log.h"
#include "fpm_events.h"
#include "zlog.h"
+#ifdef HAVE_SYSTEMD
+#include "fpm_systemd.h"
+#endif
+
#define STR2STR(a) (a ? a : "undefined")
#define BOOL2STR(a) (a ? "yes" : "no")
@@ -73,6 +77,10 @@ struct fpm_global_config_s fpm_global_config = {
#endif
.process_max = 0,
.process_priority = 64, /* 64 means unset */
+#ifdef HAVE_SYSTEMD
+ .systemd_watchdog = 0,
+ .systemd_interval = -1, /* -1 means not set */
+#endif
};
static struct fpm_worker_pool_s *current_wp = NULL;
static int ini_recursion = 0;
@@ -100,6 +108,9 @@ static struct ini_value_parser_s ini_fpm_global_options[] =
{
{ "rlimit_files", &fpm_conf_set_integer,
GO(rlimit_files) },
{ "rlimit_core", &fpm_conf_set_rlimit_core,
GO(rlimit_core) },
{ "events.mechanism", &fpm_conf_set_string,
GO(events_mechanism) },
+#ifdef HAVE_SYSTEMD
+ { "systemd_interval", &fpm_conf_set_time,
GO(systemd_interval) },
+#endif
{ 0, 0, 0 }
};
@@ -1152,6 +1163,12 @@ static int fpm_conf_post_process(int force_daemon
TSRMLS_DC) /* {{{ */
fpm_global_config.error_log = strdup("log/php-fpm.log");
}
+#ifdef HAVE_SYSTEMD
+ if (0 > fpm_systemd_conf()) {
+ return -1;
+ }
+#endif
+
#ifdef HAVE_SYSLOG_H
if (!fpm_global_config.syslog_ident) {
fpm_global_config.syslog_ident = strdup("php-fpm");
@@ -1540,6 +1557,9 @@ static void fpm_conf_dump() /* {{{ */
zlog(ZLOG_NOTICE, "\trlimit_files = %d",
fpm_global_config.rlimit_files);
zlog(ZLOG_NOTICE, "\trlimit_core = %d",
fpm_global_config.rlimit_core);
zlog(ZLOG_NOTICE, "\tevents.mechanism = %s",
fpm_event_machanism_name());
+#ifdef HAVE_SYSTEMD
+ zlog(ZLOG_NOTICE, "\tsystemd_interval = %ds",
fpm_global_config.systemd_interval/1000);
+#endif
zlog(ZLOG_NOTICE, " ");
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
diff --git a/sapi/fpm/fpm/fpm_conf.h b/sapi/fpm/fpm/fpm_conf.h
index dc54133..efd65dc 100644
--- a/sapi/fpm/fpm/fpm_conf.h
+++ b/sapi/fpm/fpm/fpm_conf.h
@@ -40,6 +40,10 @@ struct fpm_global_config_s {
int rlimit_files;
int rlimit_core;
char *events_mechanism;
+#ifdef HAVE_SYSTEMD
+ int systemd_watchdog;
+ int systemd_interval;
+#endif
};
extern struct fpm_global_config_s fpm_global_config;
diff --git a/sapi/fpm/fpm/fpm_events.c b/sapi/fpm/fpm/fpm_events.c
index d5835f0..ce5d543 100644
--- a/sapi/fpm/fpm/fpm_events.c
+++ b/sapi/fpm/fpm/fpm_events.c
@@ -29,6 +29,10 @@
#include "events/port.h"
#include "events/kqueue.h"
+#ifdef HAVE_SYSTEMD
+#include "fpm_systemd.h"
+#endif
+
#define fpm_event_set_timeout(ev, now) timeradd(&(now), &(ev)->frequency,
&(ev)->timeout);
static void fpm_event_cleanup(int which, void *arg);
@@ -361,6 +365,10 @@ void fpm_event_loop(int err) /* {{{ */
zlog(ZLOG_DEBUG, "%zu bytes have been reserved in SHM",
fpm_shm_get_size_allocated());
zlog(ZLOG_NOTICE, "ready to handle connections");
+
+#ifdef HAVE_SYSTEMD
+ fpm_systemd_heartbeat(NULL, 0, NULL);
+#endif
}
while (1) {
diff --git a/sapi/fpm/fpm/fpm_systemd.c b/sapi/fpm/fpm/fpm_systemd.c
new file mode 100644
index 0000000..c4d7ec1
--- /dev/null
+++ b/sapi/fpm/fpm/fpm_systemd.c
@@ -0,0 +1,113 @@
+#include "fpm_config.h"
+
+#include <sys/types.h>
+#include <systemd/sd-daemon.h>
+
+#include "fpm.h"
+#include "fpm_clock.h"
+#include "fpm_worker_pool.h"
+#include "fpm_scoreboard.h"
+#include "zlog.h"
+#include "fpm_systemd.h"
+
+
+static void fpm_systemd() /* {{{ */
+{
+ static unsigned long int last=0;
+ struct fpm_worker_pool_s *wp;
+ unsigned long int requests=0, slow_req=0;
+ int active=0, idle=0;
+
+
+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
+ if (wp->scoreboard) {
+ active += wp->scoreboard->active;
+ idle += wp->scoreboard->idle;
+ requests += wp->scoreboard->requests;
+ slow_req += wp->scoreboard->slow_rq;
+ }
+ }
+
+/*
+ zlog(ZLOG_DEBUG, "systemd %s (Processes active:%d, idle:%d,
Requests:%lu, slow:%lu, Traffic:%.3greq/sec)",
+ fpm_global_config.systemd_watchdog ? "watchdog" :
"heartbeat",
+ active, idle, requests, slow_req, ((float)requests -
last) * 1000.0 / fpm_global_config.systemd_interval);
+*/
+
+ if (0 > sd_notifyf(0, "READY=1\n%s"
+ "STATUS=Processes active: %d, idle: %d,
Requests: %lu, slow: %lu, Traffic: %.3greq/sec",
+ fpm_global_config.systemd_watchdog ?
"WATCHDOG=1\n" : "",
+ active, idle, requests, slow_req,
((float)requests - last) * 1000.0 / fpm_global_config.systemd_interval)) {
+ zlog(ZLOG_NOTICE, "failed to notify status to systemd");
+ }
+
+ last = requests;
+}
+/* }}} */
+
+void fpm_systemd_heartbeat(struct fpm_event_s *ev, short which, void *arg) /*
{{{ */
+{
+ static struct fpm_event_s heartbeat;
+
+ if (fpm_globals.parent_pid != getpid()) {
+ return; /* sanity check */
+ }
+
+ if (which == FPM_EV_TIMEOUT) {
+ fpm_systemd();
+
+ return;
+ }
+
+ if (0 > sd_notifyf(0, "READY=1\n"
+ "STATUS=Ready to handle connections\n"
+ "MAINPID=%lu",
+ (unsigned long) getpid())) {
+ zlog(ZLOG_WARNING, "failed to notify start to systemd");
+ } else {
+ zlog(ZLOG_DEBUG, "have notify start to systemd");
+ }
+
+ /* first call without setting which to initialize the timer */
+ if (fpm_global_config.systemd_interval > 0) {
+ fpm_event_set_timer(&heartbeat, FPM_EV_PERSIST,
&fpm_systemd_heartbeat, NULL);
+ fpm_event_add(&heartbeat, fpm_global_config.systemd_interval);
+ zlog(ZLOG_NOTICE, "systemd monitor interval set to %dms",
fpm_global_config.systemd_interval);
+ } else {
+ zlog(ZLOG_NOTICE, "systemd monitor disabled");
+ }
+}
+/* }}} */
+
+int fpm_systemd_conf() /* {{{ */
+{
+ char *watchdog;
+ int interval = 0;
+
+ watchdog = getenv("WATCHDOG_USEC");
+ if (watchdog) {
+ /* usec to msec, and half the configured delay */
+ interval = (int)(atol(watchdog) / 2000L);
+ zlog(ZLOG_DEBUG, "WATCHDOG_USEC=%s, interval=%d", watchdog,
interval);
+ }
+
+ if (interval > 1000) {
+ if (fpm_global_config.systemd_interval > 0) {
+ zlog(ZLOG_WARNING, "systemd_interval option ignored");
+ }
+ zlog(ZLOG_NOTICE, "systemd watchdog configured to %.3gsec",
(float)interval / 1000.0);
+ fpm_global_config.systemd_watchdog = 1;
+ fpm_global_config.systemd_interval = interval;
+
+ } else if (fpm_global_config.systemd_interval < 0) {
+ /* not set => default value */
+ fpm_global_config.systemd_interval =
FPM_SYSTEMD_DEFAULT_HEARTBEAT;
+
+ } else {
+ /* sec to msec */
+ fpm_global_config.systemd_interval *= 1000;
+ }
+ return 0;
+}
+/* }}} */
+
diff --git a/sapi/fpm/fpm/fpm_systemd.h b/sapi/fpm/fpm/fpm_systemd.h
new file mode 100644
index 0000000..3ee6217
--- /dev/null
+++ b/sapi/fpm/fpm/fpm_systemd.h
@@ -0,0 +1,13 @@
+#ifndef FPM_SYSTEMD_H
+#define FPM_SYSTEMD_H 1
+
+#include "fpm_events.h"
+
+/* 10s (in ms) heartbeat for systemd status */
+#define FPM_SYSTEMD_DEFAULT_HEARTBEAT (10000)
+
+void fpm_systemd_heartbeat(struct fpm_event_s *ev, short which, void *arg);
+int fpm_systemd_conf();
+
+#endif
+
diff --git a/sapi/fpm/php-fpm.conf.in b/sapi/fpm/php-fpm.conf.in
index a63dec7..f4d6e06 100644
--- a/sapi/fpm/php-fpm.conf.in
+++ b/sapi/fpm/php-fpm.conf.in
@@ -105,7 +105,15 @@
; - /dev/poll (Solaris >= 7)
; - port (Solaris >= 10)
; Default Value: not set (auto detection)
-; events.mechanism = epoll
+;events.mechanism = epoll
+
+; When FPM is build with systemd integration, specify the interval,
+; in second, between health report notification to systemd.
+; Set to 0 to disable.
+; Available Units: s(econds), m(inutes), h(ours)
+; Default Unit: seconds
+; Default value: 10
+;systemd_interval = 10
;;;;;;;;;;;;;;;;;;;;
; Pool Definitions ;
diff --git a/sapi/fpm/php-fpm.service.in b/sapi/fpm/php-fpm.service.in
index 396a88d..a2df30e 100644
--- a/sapi/fpm/php-fpm.service.in
+++ b/sapi/fpm/php-fpm.service.in
@@ -3,6 +3,7 @@ Description=The PHP FastCGI Process Manager
After=syslog.target network.target
[Service]
+Type=@php_fpm_systemd@
PIDFile=@localstatedir@/run/php-fpm.pid
ExecStart=@sbindir@/php-fpm --nodaemonize --fpm-config
@sysconfdir@/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php