~clint-fewbar/ubuntu/precise/php5/php5-5.4-merge

« back to all changes in this revision

Viewing changes to sapi/fpm/fpm/fpm_events.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-02-22 09:46:37 UTC
  • mfrom: (1.1.20) (0.3.18 sid)
  • Revision ID: package-import@ubuntu.com-20110222094637-nlu2tvb7oqgaarl0
Tags: 5.3.5-1ubuntu1
* Merge from debian/unstable. Remaining changes:
 - debian/control:
    * Dropped firebird2.1-dev, libc-client-dev, libmcrypt-dev as it is in universe.
    * Dropped libmysqlclient15-dev, build against mysql 5.1.
    * Dropped libcurl-dev not in the archive.
    * Suggest php5-suhosin rather than recommends.
    * Dropped php5-imap, php5-interbase, php5-mcrypt since we have versions 
      already in universe.
    * Dropped libonig-dev and libqgdbm since its in universe. (will be re-added in lucid+1)
    * Dropped locales-all.
  - modulelist: Drop imap, interbase, sybase, and mcrypt.
  - debian/rules:
    * Dropped building of mcrypt, imap, and interbase.
    * Install apport hook for php5.
    * stop mysql instance on clean just in case we failed in tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
#include <stdlib.h> /* for putenv */
10
10
#include <string.h>
11
11
 
 
12
#include <php.h>
 
13
#include <php_network.h>
 
14
 
12
15
#include "fpm.h"
13
16
#include "fpm_process_ctl.h"
14
17
#include "fpm_events.h"
17
20
#include "fpm_signals.h"
18
21
#include "fpm_children.h"
19
22
#include "zlog.h"
 
23
#include "fpm_clock.h"
 
24
 
 
25
#define fpm_event_set_timeout(ev, now) timeradd(&(now), &(ev)->frequency, &(ev)->timeout);
 
26
 
 
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;
 
31
} fpm_event_queue;
 
32
 
 
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);
 
39
 
 
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;
20
44
 
21
45
static void fpm_event_cleanup(int which, void *arg) /* {{{ */
22
46
{
23
 
        struct event_base *base = (struct event_base *)arg;
24
 
        event_base_free(base);
 
47
        if (fpm_event_ufds) {
 
48
                free(fpm_event_ufds);
 
49
        }
 
50
        fpm_event_queue_destroy(&fpm_event_queue_timer);
 
51
        fpm_event_queue_destroy(&fpm_event_queue_fd);
25
52
}
26
53
/* }}} */
27
54
 
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) /* {{{ */
29
56
{
30
57
        char c;
31
58
        int res;
32
 
        struct event_base *base = (struct event_base *)arg;
 
59
        int fd = ev->fd;;
33
60
 
34
61
        do {
35
62
                do {
38
65
 
39
66
                if (res <= 0) {
40
67
                        if (res < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
41
 
                                zlog(ZLOG_STUFF, ZLOG_SYSERROR, "read() failed");
 
68
                                zlog(ZLOG_SYSERROR, "read() failed");
42
69
                        }
43
70
                        return;
44
71
                }
45
72
 
46
73
                switch (c) {
47
74
                        case 'C' :                  /* SIGCHLD */
48
 
                                zlog(ZLOG_STUFF, ZLOG_DEBUG, "received SIGCHLD");
49
 
                                fpm_children_bury(base);
 
75
                                zlog(ZLOG_DEBUG, "received SIGCHLD");
 
76
                                fpm_children_bury();
50
77
                                break;
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);
55
82
                                break;
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);
60
87
                                break;
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);
65
92
                                break;
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");
70
97
                                } else {
71
 
                                        zlog(ZLOG_STUFF, ZLOG_ERROR, "unable to re-opened log file");
 
98
                                        zlog(ZLOG_ERROR, "unable to re-opened log file");
72
99
                                }
73
100
                                break;
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);
78
105
                                break;
79
106
                }
80
107
 
86
113
}
87
114
/* }}} */
88
115
 
89
 
int fpm_event_init_main(struct event_base **base) /* {{{ */
90
 
{
91
 
        *base = event_base_new();
92
 
 
93
 
        zlog(ZLOG_STUFF, ZLOG_DEBUG, "libevent: using %s", event_base_get_method(*base));
94
 
 
95
 
        if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_event_cleanup, *base)) {
96
 
                return -1;
97
 
        }
98
 
        return 0;
99
 
}
100
 
/* }}} */
101
 
 
102
 
int fpm_event_loop(struct event_base *base) /* {{{ */
103
 
{
104
 
        static struct event signal_fd_event;
105
 
 
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);
113
 
        return 0;
114
 
}
115
 
/* }}} */
116
 
 
117
 
int fpm_event_add(int fd, struct event_base *base, struct event *ev, void (*callback)(int, short, void *), void *arg) /* {{{ */
118
 
{
119
 
        event_set(ev, fd, EV_PERSIST | EV_READ, callback, arg);
120
 
        event_base_set(base, ev);
121
 
        return event_add(ev, 0);
122
 
}
123
 
/* }}} */
124
 
 
125
 
int fpm_event_del(struct event *ev) /* {{{ */
126
 
{
127
 
        return event_del(ev);
128
 
}
129
 
/* }}} */
130
 
 
131
 
void fpm_event_exit_loop(struct event_base *base) /* {{{ */
132
 
{
133
 
        event_base_loopbreak(base);
134
 
}
135
 
/* }}} */
136
 
 
137
 
void fpm_event_fire(struct event *ev) /* {{{ */
138
 
{
139
 
        (*ev->ev_callback)( (int) ev->ev_fd, (short) ev->ev_res, ev->ev_arg);   
140
 
}
141
 
/* }}} */
142
 
 
 
116
static struct fpm_event_s *fpm_event_queue_isset(struct fpm_event_queue_s *queue, struct fpm_event_s *ev) /* {{{ */
 
117
{
 
118
        if (!ev) {
 
119
                return NULL;
 
120
        }
 
121
 
 
122
        while (queue) {
 
123
                if (queue->ev == ev) {
 
124
                        return ev;
 
125
                }
 
126
                queue = queue->next;
 
127
        }
 
128
 
 
129
        return NULL;
 
130
}
 
131
/* }}} */
 
132
 
 
133
static int fpm_event_queue_add(struct fpm_event_queue_s **queue, struct fpm_event_s *ev) /* {{{ */
 
134
{
 
135
        struct fpm_event_queue_s *elt;
 
136
 
 
137
        if (!queue || !ev) {
 
138
                return -1;
 
139
        }
 
140
 
 
141
        if (fpm_event_queue_isset(*queue, ev)) {
 
142
                return 0;
 
143
        }
 
144
 
 
145
        if (!(elt = malloc(sizeof(struct fpm_event_queue_s)))) {
 
146
                zlog(ZLOG_SYSERROR, "malloc() failed");
 
147
                return -1;
 
148
        }
 
149
        elt->prev = NULL;
 
150
        elt->next = NULL;
 
151
        elt->ev = ev;
 
152
 
 
153
        if (*queue) {
 
154
                (*queue)->prev = elt;
 
155
                elt->next = *queue;
 
156
        }
 
157
        *queue = elt;
 
158
 
 
159
        return 0;       
 
160
}
 
161
/* }}} */
 
162
 
 
163
static int fpm_event_queue_del(struct fpm_event_queue_s **queue, struct fpm_event_s *ev) /* {{{ */
 
164
{
 
165
        struct fpm_event_queue_s *q;
 
166
        if (!queue || !ev) {
 
167
                return -1;
 
168
        }
 
169
        q = *queue;
 
170
        while (q) {
 
171
                if (q->ev == ev) {
 
172
                        if (q->prev) {
 
173
                                q->prev->next = q->next;
 
174
                        }
 
175
                        if (q->next) {
 
176
                                q->next->prev = q->prev;
 
177
                        }
 
178
                        if (q == *queue) {
 
179
                                *queue = q->next;
 
180
                                (*queue)->prev = NULL;
 
181
                        }
 
182
                        free(q);
 
183
                        return 0;
 
184
                }
 
185
                q = q->next;
 
186
        }
 
187
        return -1;
 
188
}
 
189
/* }}} */
 
190
 
 
191
static void fpm_event_queue_destroy(struct fpm_event_queue_s **queue) /* {{{ */
 
192
{
 
193
        struct fpm_event_queue_s *q, *tmp;
 
194
 
 
195
        if (!queue) {
 
196
                return;
 
197
        }
 
198
        q = *queue;
 
199
        while (q) {
 
200
                tmp = q;
 
201
                q = q->next;
 
202
                /* q->prev = NULL */
 
203
                free(tmp);
 
204
        }
 
205
        *queue = NULL;
 
206
}
 
207
/* }}} */
 
208
 
 
209
int fpm_event_init_main() /* {{{ */
 
210
{
 
211
        struct fpm_worker_pool_s *wp;
 
212
 
 
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);
 
219
                }
 
220
        }
 
221
 
 
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");
 
226
                return -1;
 
227
        }
 
228
 
 
229
        zlog(ZLOG_DEBUG, "%d fds have been reserved", fpm_event_nfds_max);
 
230
 
 
231
        if (0 > fpm_cleanup_add(FPM_CLEANUP_ALL, fpm_event_cleanup, NULL)) {
 
232
                return -1;
 
233
        }
 
234
        return 0;
 
235
}
 
236
/* }}} */
 
237
 
 
238
void fpm_event_loop() /* {{{ */
 
239
{
 
240
        static struct fpm_event_s signal_fd_event;
 
241
 
 
242
        /* sanity check */
 
243
        if (fpm_globals.parent_pid != getpid()) {
 
244
                return;
 
245
        }
 
246
 
 
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);
 
249
 
 
250
        /* add timers */
 
251
        fpm_pctl_heartbeat(NULL, 0, NULL);
 
252
        fpm_pctl_perform_idle_server_maintenance_heartbeat(NULL, 0, NULL);
 
253
 
 
254
        zlog(ZLOG_NOTICE, "ready to handle connections");
 
255
 
 
256
        while (1) {
 
257
                struct fpm_event_queue_s *q, *q2;
 
258
                struct timeval ms;
 
259
                struct timeval tmp;
 
260
                struct timeval now;
 
261
                unsigned long int timeout;
 
262
                int i, ret;
 
263
 
 
264
                /* sanity check */
 
265
                if (fpm_globals.parent_pid != getpid()) {
 
266
                        return;
 
267
                }
 
268
 
 
269
                fpm_clock_get(&now);
 
270
                timerclear(&ms);
 
271
 
 
272
                /* search in the timeout queue for the next timer to trigger */
 
273
                q = fpm_event_queue_timer;
 
274
                while (q) {
 
275
                        if (!timerisset(&ms)) {
 
276
                                ms = q->ev->timeout;
 
277
                        } else {
 
278
                                if (timercmp(&q->ev->timeout, &ms, <)) {
 
279
                                        ms = q->ev->timeout;
 
280
                                }
 
281
                        }
 
282
                        q = q->next;
 
283
                }
 
284
 
 
285
                /* 1s timeout if none has been set */
 
286
                if (!timerisset(&ms) || timercmp(&ms, &now, <) || timercmp(&ms, &now, ==)) {
 
287
                        timeout = 1000;
 
288
                } else {
 
289
                        timersub(&ms, &now, &tmp);
 
290
                        timeout = (tmp.tv_sec * 1000) + (tmp.tv_usec / 1000) + 1;
 
291
                }
 
292
 
 
293
                /* init fpm_event_ufds for php_poll2 */
 
294
                memset(fpm_event_ufds, 0, sizeof(php_pollfd) * fpm_event_nfds_max);
 
295
                i = 0;
 
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;
 
300
                        q->ev->index = i++;
 
301
                        q = q->next;
 
302
                }
 
303
 
 
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);
 
308
                        }
 
309
                } else if (ret > 0) {
 
310
 
 
311
                        /* trigger POLLIN events */
 
312
                        q = fpm_event_queue_fd;
 
313
                        while (q) {
 
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);
 
318
                                                        /* sanity check */
 
319
                                                        if (fpm_globals.parent_pid != getpid()) {
 
320
                                                                return;
 
321
                                                        }
 
322
                                                }
 
323
                                        }
 
324
                                        q->ev->index = -1;
 
325
                                }
 
326
                                q = q->next;
 
327
                        }
 
328
                }
 
329
 
 
330
                /* trigger timers */
 
331
                q = fpm_event_queue_timer;
 
332
                while (q) {
 
333
                        fpm_clock_get(&now);
 
334
                        if (q->ev) {
 
335
                                if (timercmp(&now, &q->ev->timeout, >) || timercmp(&now, &q->ev->timeout, ==)) {
 
336
                                        fpm_event_fire(q->ev);
 
337
                                        /* sanity check */
 
338
                                        if (fpm_globals.parent_pid != getpid()) {
 
339
                                                return;
 
340
                                        }
 
341
                                        if (q->ev->flags & FPM_EV_PERSIST) {
 
342
                                                fpm_event_set_timeout(q->ev, now);
 
343
                                        } else { /* delete the event */
 
344
                                                q2 = q;
 
345
                                                if (q->prev) {
 
346
                                                        q->prev->next = q->next;
 
347
                                                }
 
348
                                                if (q->next) {
 
349
                                                        q->next->prev = q->prev;
 
350
                                                }
 
351
                                                if (q == fpm_event_queue_timer) {
 
352
                                                        fpm_event_queue_timer = q->next;
 
353
                                                        fpm_event_queue_timer->prev = NULL;
 
354
                                                }
 
355
                                                q = q->next;
 
356
                                                free(q2);
 
357
                                                continue;
 
358
                                        }
 
359
                                }
 
360
                        }
 
361
                        q = q->next;
 
362
                }
 
363
        }
 
364
}
 
365
/* }}} */
 
366
 
 
367
void fpm_event_fire(struct fpm_event_s *ev) /* {{{ */
 
368
{
 
369
        if (!ev || !ev->callback) {
 
370
                return;
 
371
        }
 
372
 
 
373
        (*ev->callback)( (struct fpm_event_s *) ev, ev->which, ev->arg);        
 
374
}
 
375
/* }}} */
 
376
 
 
377
int fpm_event_set(struct fpm_event_s *ev, int fd, int flags, void (*callback)(struct fpm_event_s *, short, void *), void *arg) /* {{{ */
 
378
{
 
379
        if (!ev || !callback || fd < -1) {
 
380
                return -1;
 
381
        }
 
382
        memset(ev, 0, sizeof(struct fpm_event_s));
 
383
        ev->fd = fd;
 
384
        ev->callback = callback;
 
385
        ev->arg = arg;
 
386
        ev->flags = flags;
 
387
        return 0;
 
388
}
 
389
/* }}} */
 
390
 
 
391
int fpm_event_add(struct fpm_event_s *ev, unsigned long int frequency) /* {{{ */
 
392
{
 
393
        struct timeval now;
 
394
        struct timeval tmp;
 
395
 
 
396
        if (!ev) {
 
397
                return -1;
 
398
        }
 
399
 
 
400
        ev->index = -1;
 
401
 
 
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) {
 
406
                        return -1;
 
407
                }
 
408
                return 0;
 
409
        }
 
410
 
 
411
        /* it's a timer event */
 
412
        ev->which = FPM_EV_TIMEOUT;
 
413
 
 
414
        fpm_clock_get(&now);
 
415
        if (frequency >= 1000) {
 
416
                tmp.tv_sec = frequency / 1000;
 
417
                tmp.tv_usec = (frequency % 1000) * 1000;
 
418
        } else {
 
419
                tmp.tv_sec = 0;
 
420
                tmp.tv_usec = frequency * 1000;
 
421
        }
 
422
        ev->frequency = tmp;
 
423
        fpm_event_set_timeout(ev, now);
 
424
 
 
425
        if (fpm_event_queue_add(&fpm_event_queue_timer, ev) != 0) {
 
426
                return -1;
 
427
        }
 
428
 
 
429
        return 0;
 
430
}
 
431
/* }}} */
 
432
 
 
433
int fpm_event_del(struct fpm_event_s *ev) /* {{{ */
 
434
{
 
435
        if (fpm_event_queue_del(&fpm_event_queue_fd, ev) != 0) {
 
436
                return -1;
 
437
        }
 
438
 
 
439
        if (fpm_event_queue_del(&fpm_event_queue_timer, ev) != 0) {
 
440
                return -1;
 
441
        }
 
442
 
 
443
        return 0;
 
444
}
 
445
/* }}} */
 
446
 
 
447
/* }}} */