17
20
#include "fpm_signals.h"
18
21
#include "fpm_children.h"
23
#include "fpm_clock.h"
25
#define fpm_event_set_timeout(ev, now) timeradd(&(now), &(ev)->frequency, &(ev)->timeout);
27
typedef struct fpm_event_queue_s {
28
struct fpm_event_queue_s *prev;
29
struct fpm_event_queue_s *next;
30
struct fpm_event_s *ev;
33
static void fpm_event_cleanup(int which, void *arg);
34
static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg);
35
static struct fpm_event_s *fpm_event_queue_isset(struct fpm_event_queue_s *queue, struct fpm_event_s *ev);
36
static int fpm_event_queue_add(struct fpm_event_queue_s **queue, struct fpm_event_s *ev);
37
static int fpm_event_queue_del(struct fpm_event_queue_s **queue, struct fpm_event_s *ev);
38
static void fpm_event_queue_destroy(struct fpm_event_queue_s **queue);
40
static int fpm_event_nfds_max;
41
static struct fpm_event_queue_s *fpm_event_queue_timer = NULL;
42
static struct fpm_event_queue_s *fpm_event_queue_fd = NULL;
43
static php_pollfd *fpm_event_ufds = NULL;
21
45
static void fpm_event_cleanup(int which, void *arg) /* {{{ */
23
struct event_base *base = (struct event_base *)arg;
24
event_base_free(base);
50
fpm_event_queue_destroy(&fpm_event_queue_timer);
51
fpm_event_queue_destroy(&fpm_event_queue_fd);
28
static void fpm_got_signal(int fd, short ev, void *arg) /* {{{ */
55
static void fpm_got_signal(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
32
struct event_base *base = (struct event_base *)arg;
40
67
if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
41
zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed");
68
zlog(ZLOG_SYSERROR, "read() failed");
47
74
case 'C' : /* SIGCHLD */
48
zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGCHLD");
49
fpm_children_bury(base);
75
zlog(ZLOG_DEBUG, "received SIGCHLD");
51
78
case 'I' : /* SIGINT */
52
zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGINT");
53
zlog(ZLOG_STUFF, ZLOG_NOTICE, "Terminating ...");
54
fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET, base);
79
zlog(ZLOG_DEBUG, "received SIGINT");
80
zlog(ZLOG_NOTICE, "Terminating ...");
81
fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET);
56
83
case 'T' : /* SIGTERM */
57
zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGTERM");
58
zlog(ZLOG_STUFF, ZLOG_NOTICE, "Terminating ...");
59
fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET, base);
84
zlog(ZLOG_DEBUG, "received SIGTERM");
85
zlog(ZLOG_NOTICE, "Terminating ...");
86
fpm_pctl(FPM_PCTL_STATE_TERMINATING, FPM_PCTL_ACTION_SET);
61
88
case 'Q' : /* SIGQUIT */
62
zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGQUIT");
63
zlog(ZLOG_STUFF, ZLOG_NOTICE, "Finishing ...");
64
fpm_pctl(FPM_PCTL_STATE_FINISHING, FPM_PCTL_ACTION_SET, base);
89
zlog(ZLOG_DEBUG, "received SIGQUIT");
90
zlog(ZLOG_NOTICE, "Finishing ...");
91
fpm_pctl(FPM_PCTL_STATE_FINISHING, FPM_PCTL_ACTION_SET);
66
93
case '1' : /* SIGUSR1 */
67
zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGUSR1");
94
zlog(ZLOG_DEBUG, "received SIGUSR1");
68
95
if (0 == fpm_stdio_open_error_log(1)) {
69
zlog(ZLOG_STUFF, ZLOG_NOTICE, "log file re-opened");
96
zlog(ZLOG_NOTICE, "log file re-opened");
71
zlog(ZLOG_STUFF, ZLOG_ERROR, "unable to re-opened log file");
98
zlog(ZLOG_ERROR, "unable to re-opened log file");
74
101
case '2' : /* SIGUSR2 */
75
zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGUSR2");
76
zlog(ZLOG_STUFF, ZLOG_NOTICE, "Reloading in progress ...");
77
fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET, base);
102
zlog(ZLOG_DEBUG, "received SIGUSR2");
103
zlog(ZLOG_NOTICE, "Reloading in progress ...");
104
fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET);
89
int fpm_event_init_main(struct event_base **base) /* {{{ */
91
*base = event_base_new();
93
zlog(ZLOG_STUFF, ZLOG_DEBUG, "libevent: using %s", event_base_get_method(*base));
95
if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_event_cleanup, *base)) {
102
int fpm_event_loop(struct event_base *base) /* {{{ */
104
static struct event signal_fd_event;
106
event_set(&signal_fd_event, fpm_signals_get_fd(), EV_PERSIST | EV_READ, &fpm_got_signal, base);
107
event_base_set(base, &signal_fd_event);
108
event_add(&signal_fd_event, 0);
109
fpm_pctl_heartbeat(-1, 0, base);
110
fpm_pctl_perform_idle_server_maintenance_heartbeat(-1, 0, base);
111
zlog(ZLOG_STUFF, ZLOG_NOTICE, "ready to handle connections");
112
event_base_dispatch(base);
117
int fpm_event_add(int fd, struct event_base *base, struct event *ev, void (*callback)(int, short, void *), void *arg) /* {{{ */
119
event_set(ev, fd, EV_PERSIST | EV_READ, callback, arg);
120
event_base_set(base, ev);
121
return event_add(ev, 0);
125
int fpm_event_del(struct event *ev) /* {{{ */
127
return event_del(ev);
131
void fpm_event_exit_loop(struct event_base *base) /* {{{ */
133
event_base_loopbreak(base);
137
void fpm_event_fire(struct event *ev) /* {{{ */
139
(*ev->ev_callback)( (int) ev->ev_fd, (short) ev->ev_res, ev->ev_arg);
116
static struct fpm_event_s *fpm_event_queue_isset(struct fpm_event_queue_s *queue, struct fpm_event_s *ev) /* {{{ */
123
if (queue->ev == ev) {
133
static int fpm_event_queue_add(struct fpm_event_queue_s **queue, struct fpm_event_s *ev) /* {{{ */
135
struct fpm_event_queue_s *elt;
141
if (fpm_event_queue_isset(*queue, ev)) {
145
if (!(elt = malloc(sizeof(struct fpm_event_queue_s)))) {
146
zlog(ZLOG_SYSERROR, "malloc() failed");
154
(*queue)->prev = elt;
163
static int fpm_event_queue_del(struct fpm_event_queue_s **queue, struct fpm_event_s *ev) /* {{{ */
165
struct fpm_event_queue_s *q;
173
q->prev->next = q->next;
176
q->next->prev = q->prev;
180
(*queue)->prev = NULL;
191
static void fpm_event_queue_destroy(struct fpm_event_queue_s **queue) /* {{{ */
193
struct fpm_event_queue_s *q, *tmp;
209
int fpm_event_init_main() /* {{{ */
211
struct fpm_worker_pool_s *wp;
213
/* count the max number of necessary fds for polling */
214
fpm_event_nfds_max = 1; /* only one FD is necessary at startup for the master process signal pipe */
215
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
216
if (!wp->config) continue;
217
if (wp->config->catch_workers_output && wp->config->pm_max_children > 0) {
218
fpm_event_nfds_max += (wp->config->pm_max_children * 2);
222
/* malloc the max number of necessary fds for polling */
223
fpm_event_ufds = malloc(sizeof(php_pollfd) * fpm_event_nfds_max);
224
if (!fpm_event_ufds) {
225
zlog(ZLOG_SYSERROR, "malloc() failed");
229
zlog(ZLOG_DEBUG, "%d fds have been reserved", fpm_event_nfds_max);
231
if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_event_cleanup, NULL)) {
238
void fpm_event_loop() /* {{{ */
240
static struct fpm_event_s signal_fd_event;
243
if (fpm_globals.parent_pid != getpid()) {
247
fpm_event_set(&signal_fd_event, fpm_signals_get_fd(), FPM_EV_READ, &fpm_got_signal, NULL);
248
fpm_event_add(&signal_fd_event, 0);
251
fpm_pctl_heartbeat(NULL, 0, NULL);
252
fpm_pctl_perform_idle_server_maintenance_heartbeat(NULL, 0, NULL);
254
zlog(ZLOG_NOTICE, "ready to handle connections");
257
struct fpm_event_queue_s *q, *q2;
261
unsigned long int timeout;
265
if (fpm_globals.parent_pid != getpid()) {
272
/* search in the timeout queue for the next timer to trigger */
273
q = fpm_event_queue_timer;
275
if (!timerisset(&ms)) {
278
if (timercmp(&q->ev->timeout, &ms, <)) {
285
/* 1s timeout if none has been set */
286
if (!timerisset(&ms) || timercmp(&ms, &now, <) || timercmp(&ms, &now, ==)) {
289
timersub(&ms, &now, &tmp);
290
timeout = (tmp.tv_sec * 1000) + (tmp.tv_usec / 1000) + 1;
293
/* init fpm_event_ufds for php_poll2 */
294
memset(fpm_event_ufds, 0, sizeof(php_pollfd) * fpm_event_nfds_max);
296
q = fpm_event_queue_fd;
297
while (q && i < fpm_event_nfds_max) {
298
fpm_event_ufds[i].fd = q->ev->fd;
299
fpm_event_ufds[i].events = POLLIN;
304
/* wait for inconming event or timeout */
305
if ((ret = php_poll2(fpm_event_ufds, i, timeout)) == -1) {
306
if (errno != EINTR) {
307
zlog(ZLOG_WARNING, "php_poll2() returns %d", errno);
309
} else if (ret > 0) {
311
/* trigger POLLIN events */
312
q = fpm_event_queue_fd;
314
if (q->ev && q->ev->index >= 0 && q->ev->index < fpm_event_nfds_max) {
315
if (q->ev->fd == fpm_event_ufds[q->ev->index].fd) {
316
if (fpm_event_ufds[q->ev->index].revents & POLLIN) {
317
fpm_event_fire(q->ev);
319
if (fpm_globals.parent_pid != getpid()) {
331
q = fpm_event_queue_timer;
335
if (timercmp(&now, &q->ev->timeout, >) || timercmp(&now, &q->ev->timeout, ==)) {
336
fpm_event_fire(q->ev);
338
if (fpm_globals.parent_pid != getpid()) {
341
if (q->ev->flags & FPM_EV_PERSIST) {
342
fpm_event_set_timeout(q->ev, now);
343
} else { /* delete the event */
346
q->prev->next = q->next;
349
q->next->prev = q->prev;
351
if (q == fpm_event_queue_timer) {
352
fpm_event_queue_timer = q->next;
353
fpm_event_queue_timer->prev = NULL;
367
void fpm_event_fire(struct fpm_event_s *ev) /* {{{ */
369
if (!ev || !ev->callback) {
373
(*ev->callback)( (struct fpm_event_s *) ev, ev->which, ev->arg);
377
int fpm_event_set(struct fpm_event_s *ev, int fd, int flags, void (*callback)(struct fpm_event_s *, short, void *), void *arg) /* {{{ */
379
if (!ev || !callback || fd < -1) {
382
memset(ev, 0, sizeof(struct fpm_event_s));
384
ev->callback = callback;
391
int fpm_event_add(struct fpm_event_s *ev, unsigned long int frequency) /* {{{ */
402
/* it's a triggered event on incoming data */
403
if (ev->flags & FPM_EV_READ) {
404
ev->which = FPM_EV_READ;
405
if (fpm_event_queue_add(&fpm_event_queue_fd, ev) != 0) {
411
/* it's a timer event */
412
ev->which = FPM_EV_TIMEOUT;
415
if (frequency >= 1000) {
416
tmp.tv_sec = frequency / 1000;
417
tmp.tv_usec = (frequency % 1000) * 1000;
420
tmp.tv_usec = frequency * 1000;
423
fpm_event_set_timeout(ev, now);
425
if (fpm_event_queue_add(&fpm_event_queue_timer, ev) != 0) {
433
int fpm_event_del(struct fpm_event_s *ev) /* {{{ */
435
if (fpm_event_queue_del(&fpm_event_queue_fd, ev) != 0) {
439
if (fpm_event_queue_del(&fpm_event_queue_timer, ev) != 0) {