root/sapi/fpm/fpm/events/poll.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fpm_event_poll_module
  2. fpm_event_poll_init
  3. fpm_event_poll_clean
  4. fpm_event_poll_wait
  5. fpm_event_poll_add
  6. fpm_event_poll_remove

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Jerome Loyet <jerome@loyet.net>                             |
  16    +----------------------------------------------------------------------+
  17 */
  18 
  19 /* $Id$ */
  20 
  21 #include "../fpm_config.h"
  22 #include "../fpm_events.h"
  23 #include "../fpm.h"
  24 #include "../zlog.h"
  25 
  26 #if HAVE_POLL
  27 
  28 #include <poll.h>
  29 #include <errno.h>
  30 #include <string.h>
  31 
  32 static int fpm_event_poll_init(int max);
  33 static int fpm_event_poll_clean();
  34 static int fpm_event_poll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
  35 static int fpm_event_poll_add(struct fpm_event_s *ev);
  36 static int fpm_event_poll_remove(struct fpm_event_s *ev);
  37 
  38 static struct fpm_event_module_s poll_module = {
  39         .name = "poll",
  40         .support_edge_trigger = 0,
  41         .init = fpm_event_poll_init,
  42         .clean = fpm_event_poll_clean,
  43         .wait = fpm_event_poll_wait,
  44         .add = fpm_event_poll_add,
  45         .remove = fpm_event_poll_remove,
  46 };
  47 
  48 static struct pollfd *pollfds = NULL;
  49 static struct pollfd *active_pollfds = NULL;
  50 static int npollfds = 0;
  51 static int next_free_slot = 0;
  52 #endif /* HAVE_POLL */
  53 
  54 /*
  55  * return the module configuration
  56  */
  57 struct fpm_event_module_s *fpm_event_poll_module() /* {{{ */
  58 {
  59 #if HAVE_POLL
  60         return &poll_module;
  61 #else
  62         return NULL;
  63 #endif /* HAVE_POLL */
  64 }
  65 /* }}} */
  66 
  67 #if HAVE_POLL
  68 
  69 /*
  70  * Init the module
  71  */
  72 static int fpm_event_poll_init(int max) /* {{{ */
  73 {
  74         int i;
  75 
  76         if (max < 1) {
  77                 return 0;
  78         }
  79 
  80         /* alloc and clear pollfds */
  81         pollfds = malloc(sizeof(struct pollfd) * max);
  82         if (!pollfds) {
  83                 zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
  84                 return -1;
  85         }
  86         memset(pollfds, 0, sizeof(struct pollfd) * max);
  87 
  88         /* set all fd to -1 in order to ensure it's not set */
  89         for (i = 0; i < max; i++) {
  90                         pollfds[i].fd = -1;
  91         }
  92 
  93         /* alloc and clear active_pollfds */
  94         active_pollfds = malloc(sizeof(struct pollfd) * max);
  95         if (!active_pollfds) {
  96                 free(pollfds);
  97                 zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
  98                 return -1;
  99         }
 100         memset(active_pollfds, 0, sizeof(struct pollfd) * max);
 101 
 102         /* save max */
 103         npollfds = max;
 104         return 0;
 105 }
 106 /* }}} */
 107 
 108 /*
 109  * Clean the module
 110  */
 111 static int fpm_event_poll_clean() /* {{{ */
 112 {
 113         /* free pollfds */
 114         if (pollfds) {
 115                 free(pollfds);
 116                 pollfds = NULL;
 117         }
 118 
 119         /* free active_pollfds */
 120         if (active_pollfds) {
 121                 free(active_pollfds);
 122                 active_pollfds = NULL;
 123         }
 124 
 125         npollfds = 0;
 126         return 0;
 127 }
 128 /* }}} */
 129 
 130 /*
 131  * wait for events or timeout
 132  */
 133 static int fpm_event_poll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
 134 {
 135         int ret;
 136         struct fpm_event_queue_s *q;
 137 
 138         if (npollfds > 0) {
 139                 /* copy pollfds because poll() alters it */
 140                 memcpy(active_pollfds, pollfds, sizeof(struct pollfd) * npollfds);
 141         }
 142 
 143         /* wait for inconming event or timeout */
 144         ret = poll(active_pollfds, npollfds, timeout);
 145         if (ret == -1) {
 146 
 147                 /* trigger error unless signal interrupt */
 148                 if (errno != EINTR) {
 149                         zlog(ZLOG_WARNING, "poll() returns %d", errno);
 150                         return -1;
 151                 }
 152         }
 153 
 154         /* events have been triggered */
 155         if (ret > 0) {
 156 
 157                 /* trigger POLLIN events */
 158                 q = queue;
 159                 while (q) {
 160                         /* ensure ev->index is valid */
 161                         if (q->ev && q->ev->index >= 0 && q->ev->index < npollfds && q->ev->fd == active_pollfds[q->ev->index].fd) {
 162 
 163                                 /* has the event has been triggered ? */
 164                                 if (active_pollfds[q->ev->index].revents & POLLIN) {
 165 
 166                                         /* fire the event */
 167                                         fpm_event_fire(q->ev);
 168 
 169                                         /* sanity check */
 170                                         if (fpm_globals.parent_pid != getpid()) {
 171                                                 return -2;
 172                                         }
 173                                 }
 174                         }
 175                         q = q->next; /* iterate */
 176                 }
 177         }
 178 
 179         return ret;
 180 }
 181 /* }}} */
 182 
 183 /*
 184  * Add a FD to the fd set
 185  */
 186 static int fpm_event_poll_add(struct fpm_event_s *ev) /* {{{ */
 187 {
 188         int i;
 189 
 190         /* do we have a direct free slot */
 191         if (pollfds[next_free_slot].fd == -1) {
 192                 /* register the event */
 193                 pollfds[next_free_slot].fd = ev->fd;
 194                 pollfds[next_free_slot].events = POLLIN;
 195 
 196                 /* remember the event place in the fd list and suppose next slot is free */
 197                 ev->index = next_free_slot++;
 198                 if (next_free_slot >= npollfds) {
 199                         next_free_slot = 0;
 200                 }
 201                 return 0;
 202         }
 203 
 204         /* let's search */
 205         for (i = 0; i < npollfds; i++) {
 206                 if (pollfds[i].fd != -1) {
 207                         /* not free */
 208                         continue;
 209                 }
 210 
 211                 /* register the event */
 212                 pollfds[i].fd = ev->fd;
 213                 pollfds[i].events = POLLIN;
 214 
 215                 /* remember the event place in the fd list and suppose next slot is free */
 216                 ev->index = next_free_slot++;
 217                 if (next_free_slot >= npollfds) {
 218                         next_free_slot = 0;
 219                 }
 220                 return 0;
 221         }
 222 
 223         zlog(ZLOG_ERROR, "poll: not enought space to add event (fd=%d)", ev->fd);
 224         return -1;
 225 }
 226 /* }}} */
 227 
 228 /*
 229  * Remove a FD from the fd set
 230  */
 231 static int fpm_event_poll_remove(struct fpm_event_s *ev) /* {{{ */
 232 {
 233         int i;
 234 
 235         /* do we have a direct access */
 236         if (ev->index >= 0 && ev->index < npollfds && pollfds[ev->index].fd == ev->fd) {
 237                 /* remember this slot as free */
 238                 next_free_slot = ev->index;
 239 
 240                 /* clear event in pollfds */
 241                 pollfds[ev->index].fd = -1;
 242                 pollfds[ev->index].events = 0;
 243 
 244                 /* mark the event as not registered */
 245                 ev->index = -1;
 246 
 247                 return 0;
 248         }
 249 
 250         /* let's search */
 251         for (i = 0; i < npollfds; i++) {
 252 
 253                 if (pollfds[i].fd != ev->fd) {
 254                         /* not found */
 255                         continue;
 256                 }
 257 
 258                 /* remember this slot as free */
 259                 next_free_slot = i;
 260 
 261                 /* clear event in pollfds */
 262                 pollfds[i].fd = -1;
 263                 pollfds[i].events = 0;
 264 
 265                 /* mark the event as not registered */
 266                 ev->index = -1;
 267 
 268                 return 0;
 269         }
 270 
 271         zlog(ZLOG_ERROR, "poll: unable to remove event: not found (fd=%d, index=%d)", ev->fd, ev->index);
 272         return -1;
 273 }
 274 /* }}} */
 275 
 276 #endif /* HAVE_POLL */

/* [<][>][^][v][top][bottom][index][help] */