1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
|
diff -up ../sapi/fpm/config.m4.systemd ../sapi/fpm/config.m4
--- ../sapi/fpm/config.m4.systemd 2012-12-05 11:40:54.000000000 +0100
+++ ../sapi/fpm/config.m4 2013-05-20 09:44:23.436365510 +0200
@@ -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
@@ -631,7 +651,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 -up ../sapi/fpm/fpm/fpm_conf.c.systemd ../sapi/fpm/fpm/fpm_conf.c
--- ../sapi/fpm/fpm/fpm_conf.c.systemd 2013-05-02 14:36:45.000000000 +0200
+++ ../sapi/fpm/fpm/fpm_conf.c 2013-05-20 09:59:29.632807378 +0200
@@ -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_co
#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
{ "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 for
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 -up ../sapi/fpm/fpm/fpm_conf.h.systemd ../sapi/fpm/fpm/fpm_conf.h
--- ../sapi/fpm/fpm/fpm_conf.h.systemd 2012-12-05 11:40:39.000000000 +0100
+++ ../sapi/fpm/fpm/fpm_conf.h 2013-05-20 09:44:23.438365518 +0200
@@ -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 -up ../sapi/fpm/fpm/fpm_events.c.systemd ../sapi/fpm/fpm/fpm_events.c
--- ../sapi/fpm/fpm/fpm_events.c.systemd 2012-12-05 11:40:39.000000000 +0100
+++ ../sapi/fpm/fpm/fpm_events.c 2013-05-20 09:44:23.439365522 +0200
@@ -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 -up ../sapi/fpm/fpm/fpm_systemd.c.systemd ../sapi/fpm/fpm/fpm_systemd.c
--- ../sapi/fpm/fpm/fpm_systemd.c.systemd 2013-05-20 09:44:23.439365522 +0200
+++ ../sapi/fpm/fpm/fpm_systemd.c 2013-05-20 09:44:23.439365522 +0200
@@ -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 -up ../sapi/fpm/fpm/fpm_systemd.h.systemd ../sapi/fpm/fpm/fpm_systemd.h
--- ../sapi/fpm/fpm/fpm_systemd.h.systemd 2013-05-20 09:44:23.440365526 +0200
+++ ../sapi/fpm/fpm/fpm_systemd.h 2013-05-20 09:44:23.440365526 +0200
@@ -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 -up ../sapi/fpm/php-fpm.conf.in.systemd ../sapi/fpm/php-fpm.conf.in
--- ../sapi/fpm/php-fpm.conf.in.systemd 2013-05-20 09:53:48.718512646 +0200
+++ ../sapi/fpm/php-fpm.conf.in 2013-05-20 09:58:26.831568875 +0200
@@ -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 -up ../sapi/fpm/php-fpm.service.in.systemd ../sapi/fpm/php-fpm.service.in
--- ../sapi/fpm/php-fpm.service.in.systemd 2012-12-05 11:40:39.000000000 +0100
+++ ../sapi/fpm/php-fpm.service.in 2013-05-20 09:44:23.440365526 +0200
@@ -3,6 +3,7 @@ Description=The PHP FastCGI Process Mana
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
|