Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 
0012 
0013 #if (NGX_TEST_BUILD_DEVPOLL)
0014 
0015 /* Solaris declarations */
0016 
0017 #ifndef POLLREMOVE
0018 #define POLLREMOVE   0x0800
0019 #endif
0020 #define DP_POLL      0xD001
0021 #define DP_ISPOLLED  0xD002
0022 
0023 struct dvpoll {
0024     struct pollfd  *dp_fds;
0025     int             dp_nfds;
0026     int             dp_timeout;
0027 };
0028 
0029 #endif
0030 
0031 
0032 typedef struct {
0033     ngx_uint_t      changes;
0034     ngx_uint_t      events;
0035 } ngx_devpoll_conf_t;
0036 
0037 
0038 static ngx_int_t ngx_devpoll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
0039 static void ngx_devpoll_done(ngx_cycle_t *cycle);
0040 static ngx_int_t ngx_devpoll_add_event(ngx_event_t *ev, ngx_int_t event,
0041     ngx_uint_t flags);
0042 static ngx_int_t ngx_devpoll_del_event(ngx_event_t *ev, ngx_int_t event,
0043     ngx_uint_t flags);
0044 static ngx_int_t ngx_devpoll_set_event(ngx_event_t *ev, ngx_int_t event,
0045     ngx_uint_t flags);
0046 static ngx_int_t ngx_devpoll_process_events(ngx_cycle_t *cycle,
0047     ngx_msec_t timer, ngx_uint_t flags);
0048 
0049 static void *ngx_devpoll_create_conf(ngx_cycle_t *cycle);
0050 static char *ngx_devpoll_init_conf(ngx_cycle_t *cycle, void *conf);
0051 
0052 static int              dp = -1;
0053 static struct pollfd   *change_list, *event_list;
0054 static ngx_uint_t       nchanges, max_changes, nevents;
0055 
0056 static ngx_event_t    **change_index;
0057 
0058 
0059 static ngx_str_t      devpoll_name = ngx_string("/dev/poll");
0060 
0061 static ngx_command_t  ngx_devpoll_commands[] = {
0062 
0063     { ngx_string("devpoll_changes"),
0064       NGX_EVENT_CONF|NGX_CONF_TAKE1,
0065       ngx_conf_set_num_slot,
0066       0,
0067       offsetof(ngx_devpoll_conf_t, changes),
0068       NULL },
0069 
0070     { ngx_string("devpoll_events"),
0071       NGX_EVENT_CONF|NGX_CONF_TAKE1,
0072       ngx_conf_set_num_slot,
0073       0,
0074       offsetof(ngx_devpoll_conf_t, events),
0075       NULL },
0076 
0077       ngx_null_command
0078 };
0079 
0080 
0081 static ngx_event_module_t  ngx_devpoll_module_ctx = {
0082     &devpoll_name,
0083     ngx_devpoll_create_conf,               /* create configuration */
0084     ngx_devpoll_init_conf,                 /* init configuration */
0085 
0086     {
0087         ngx_devpoll_add_event,             /* add an event */
0088         ngx_devpoll_del_event,             /* delete an event */
0089         ngx_devpoll_add_event,             /* enable an event */
0090         ngx_devpoll_del_event,             /* disable an event */
0091         NULL,                              /* add an connection */
0092         NULL,                              /* delete an connection */
0093         NULL,                              /* trigger a notify */
0094         ngx_devpoll_process_events,        /* process the events */
0095         ngx_devpoll_init,                  /* init the events */
0096         ngx_devpoll_done,                  /* done the events */
0097     }
0098 
0099 };
0100 
0101 ngx_module_t  ngx_devpoll_module = {
0102     NGX_MODULE_V1,
0103     &ngx_devpoll_module_ctx,               /* module context */
0104     ngx_devpoll_commands,                  /* module directives */
0105     NGX_EVENT_MODULE,                      /* module type */
0106     NULL,                                  /* init master */
0107     NULL,                                  /* init module */
0108     NULL,                                  /* init process */
0109     NULL,                                  /* init thread */
0110     NULL,                                  /* exit thread */
0111     NULL,                                  /* exit process */
0112     NULL,                                  /* exit master */
0113     NGX_MODULE_V1_PADDING
0114 };
0115 
0116 
0117 static ngx_int_t
0118 ngx_devpoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
0119 {
0120     size_t               n;
0121     ngx_devpoll_conf_t  *dpcf;
0122 
0123     dpcf = ngx_event_get_conf(cycle->conf_ctx, ngx_devpoll_module);
0124 
0125     if (dp == -1) {
0126         dp = open("/dev/poll", O_RDWR);
0127 
0128         if (dp == -1) {
0129             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
0130                           "open(/dev/poll) failed");
0131             return NGX_ERROR;
0132         }
0133     }
0134 
0135     if (max_changes < dpcf->changes) {
0136         if (nchanges) {
0137             n = nchanges * sizeof(struct pollfd);
0138             if (write(dp, change_list, n) != (ssize_t) n) {
0139                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0140                               "write(/dev/poll) failed");
0141                 return NGX_ERROR;
0142             }
0143 
0144             nchanges = 0;
0145         }
0146 
0147         if (change_list) {
0148             ngx_free(change_list);
0149         }
0150 
0151         change_list = ngx_alloc(sizeof(struct pollfd) * dpcf->changes,
0152                                 cycle->log);
0153         if (change_list == NULL) {
0154             return NGX_ERROR;
0155         }
0156 
0157         if (change_index) {
0158             ngx_free(change_index);
0159         }
0160 
0161         change_index = ngx_alloc(sizeof(ngx_event_t *) * dpcf->changes,
0162                                  cycle->log);
0163         if (change_index == NULL) {
0164             return NGX_ERROR;
0165         }
0166     }
0167 
0168     max_changes = dpcf->changes;
0169 
0170     if (nevents < dpcf->events) {
0171         if (event_list) {
0172             ngx_free(event_list);
0173         }
0174 
0175         event_list = ngx_alloc(sizeof(struct pollfd) * dpcf->events,
0176                                cycle->log);
0177         if (event_list == NULL) {
0178             return NGX_ERROR;
0179         }
0180     }
0181 
0182     nevents = dpcf->events;
0183 
0184     ngx_io = ngx_os_io;
0185 
0186     ngx_event_actions = ngx_devpoll_module_ctx.actions;
0187 
0188     ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_FD_EVENT;
0189 
0190     return NGX_OK;
0191 }
0192 
0193 
0194 static void
0195 ngx_devpoll_done(ngx_cycle_t *cycle)
0196 {
0197     if (close(dp) == -1) {
0198         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0199                       "close(/dev/poll) failed");
0200     }
0201 
0202     dp = -1;
0203 
0204     ngx_free(change_list);
0205     ngx_free(event_list);
0206     ngx_free(change_index);
0207 
0208     change_list = NULL;
0209     event_list = NULL;
0210     change_index = NULL;
0211     max_changes = 0;
0212     nchanges = 0;
0213     nevents = 0;
0214 }
0215 
0216 
0217 static ngx_int_t
0218 ngx_devpoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
0219 {
0220 #if (NGX_DEBUG)
0221     ngx_connection_t *c;
0222 #endif
0223 
0224 #if (NGX_READ_EVENT != POLLIN)
0225     event = (event == NGX_READ_EVENT) ? POLLIN : POLLOUT;
0226 #endif
0227 
0228 #if (NGX_DEBUG)
0229     c = ev->data;
0230     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0231                    "devpoll add event: fd:%d ev:%04Xi", c->fd, event);
0232 #endif
0233 
0234     ev->active = 1;
0235 
0236     return ngx_devpoll_set_event(ev, event, 0);
0237 }
0238 
0239 
0240 static ngx_int_t
0241 ngx_devpoll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
0242 {
0243     ngx_event_t       *e;
0244     ngx_connection_t  *c;
0245 
0246     c = ev->data;
0247 
0248 #if (NGX_READ_EVENT != POLLIN)
0249     event = (event == NGX_READ_EVENT) ? POLLIN : POLLOUT;
0250 #endif
0251 
0252     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0253                    "devpoll del event: fd:%d ev:%04Xi", c->fd, event);
0254 
0255     if (ngx_devpoll_set_event(ev, POLLREMOVE, flags) == NGX_ERROR) {
0256         return NGX_ERROR;
0257     }
0258 
0259     ev->active = 0;
0260 
0261     if (flags & NGX_CLOSE_EVENT) {
0262         e = (event == POLLIN) ? c->write : c->read;
0263 
0264         if (e) {
0265             e->active = 0;
0266         }
0267 
0268         return NGX_OK;
0269     }
0270 
0271     /* restore the pair event if it exists */
0272 
0273     if (event == POLLIN) {
0274         e = c->write;
0275         event = POLLOUT;
0276 
0277     } else {
0278         e = c->read;
0279         event = POLLIN;
0280     }
0281 
0282     if (e && e->active) {
0283         return ngx_devpoll_set_event(e, event, 0);
0284     }
0285 
0286     return NGX_OK;
0287 }
0288 
0289 
0290 static ngx_int_t
0291 ngx_devpoll_set_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
0292 {
0293     size_t             n;
0294     ngx_connection_t  *c;
0295 
0296     c = ev->data;
0297 
0298     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0299                    "devpoll fd:%d ev:%04Xi fl:%04Xi", c->fd, event, flags);
0300 
0301     if (nchanges >= max_changes) {
0302         ngx_log_error(NGX_LOG_WARN, ev->log, 0,
0303                       "/dev/pool change list is filled up");
0304 
0305         n = nchanges * sizeof(struct pollfd);
0306         if (write(dp, change_list, n) != (ssize_t) n) {
0307             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
0308                           "write(/dev/poll) failed");
0309             return NGX_ERROR;
0310         }
0311 
0312         nchanges = 0;
0313     }
0314 
0315     change_list[nchanges].fd = c->fd;
0316     change_list[nchanges].events = (short) event;
0317     change_list[nchanges].revents = 0;
0318 
0319     change_index[nchanges] = ev;
0320     ev->index = nchanges;
0321 
0322     nchanges++;
0323 
0324     if (flags & NGX_CLOSE_EVENT) {
0325         n = nchanges * sizeof(struct pollfd);
0326         if (write(dp, change_list, n) != (ssize_t) n) {
0327             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
0328                           "write(/dev/poll) failed");
0329             return NGX_ERROR;
0330         }
0331 
0332         nchanges = 0;
0333     }
0334 
0335     return NGX_OK;
0336 }
0337 
0338 
0339 static ngx_int_t
0340 ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
0341     ngx_uint_t flags)
0342 {
0343     int                 events, revents, rc;
0344     size_t              n;
0345     ngx_fd_t            fd;
0346     ngx_err_t           err;
0347     ngx_int_t           i;
0348     ngx_uint_t          level, instance;
0349     ngx_event_t        *rev, *wev;
0350     ngx_queue_t        *queue;
0351     ngx_connection_t   *c;
0352     struct pollfd       pfd;
0353     struct dvpoll       dvp;
0354 
0355     /* NGX_TIMER_INFINITE == INFTIM */
0356 
0357     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0358                    "devpoll timer: %M", timer);
0359 
0360     if (nchanges) {
0361         n = nchanges * sizeof(struct pollfd);
0362         if (write(dp, change_list, n) != (ssize_t) n) {
0363             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0364                           "write(/dev/poll) failed");
0365             return NGX_ERROR;
0366         }
0367 
0368         nchanges = 0;
0369     }
0370 
0371     dvp.dp_fds = event_list;
0372     dvp.dp_nfds = (int) nevents;
0373     dvp.dp_timeout = timer;
0374     events = ioctl(dp, DP_POLL, &dvp);
0375 
0376     err = (events == -1) ? ngx_errno : 0;
0377 
0378     if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
0379         ngx_time_update();
0380     }
0381 
0382     if (err) {
0383         if (err == NGX_EINTR) {
0384 
0385             if (ngx_event_timer_alarm) {
0386                 ngx_event_timer_alarm = 0;
0387                 return NGX_OK;
0388             }
0389 
0390             level = NGX_LOG_INFO;
0391 
0392         } else {
0393             level = NGX_LOG_ALERT;
0394         }
0395 
0396         ngx_log_error(level, cycle->log, err, "ioctl(DP_POLL) failed");
0397         return NGX_ERROR;
0398     }
0399 
0400     if (events == 0) {
0401         if (timer != NGX_TIMER_INFINITE) {
0402             return NGX_OK;
0403         }
0404 
0405         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0406                       "ioctl(DP_POLL) returned no events without timeout");
0407         return NGX_ERROR;
0408     }
0409 
0410     for (i = 0; i < events; i++) {
0411 
0412         fd = event_list[i].fd;
0413         revents = event_list[i].revents;
0414 
0415         c = ngx_cycle->files[fd];
0416 
0417         if (c == NULL || c->fd == -1) {
0418 
0419             pfd.fd = fd;
0420             pfd.events = 0;
0421             pfd.revents = 0;
0422 
0423             rc = ioctl(dp, DP_ISPOLLED, &pfd);
0424 
0425             switch (rc) {
0426 
0427             case -1:
0428                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0429                     "ioctl(DP_ISPOLLED) failed for socket %d, event %04Xd",
0430                     fd, revents);
0431                 break;
0432 
0433             case 0:
0434                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0435                     "phantom event %04Xd for closed and removed socket %d",
0436                     revents, fd);
0437                 break;
0438 
0439             default:
0440                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0441                     "unexpected event %04Xd for closed and removed socket %d, "
0442                     "ioctl(DP_ISPOLLED) returned rc:%d, fd:%d, event %04Xd",
0443                     revents, fd, rc, pfd.fd, pfd.revents);
0444 
0445                 pfd.fd = fd;
0446                 pfd.events = POLLREMOVE;
0447                 pfd.revents = 0;
0448 
0449                 if (write(dp, &pfd, sizeof(struct pollfd))
0450                     != (ssize_t) sizeof(struct pollfd))
0451                 {
0452                     ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0453                                   "write(/dev/poll) for %d failed", fd);
0454                 }
0455 
0456                 if (close(fd) == -1) {
0457                     ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0458                                   "close(%d) failed", fd);
0459                 }
0460 
0461                 break;
0462             }
0463 
0464             continue;
0465         }
0466 
0467         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0468                        "devpoll: fd:%d, ev:%04Xd, rev:%04Xd",
0469                        fd, event_list[i].events, revents);
0470 
0471         if (revents & (POLLERR|POLLHUP|POLLNVAL)) {
0472             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0473                           "ioctl(DP_POLL) error fd:%d ev:%04Xd rev:%04Xd",
0474                           fd, event_list[i].events, revents);
0475         }
0476 
0477         if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
0478             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0479                           "strange ioctl(DP_POLL) events "
0480                           "fd:%d ev:%04Xd rev:%04Xd",
0481                           fd, event_list[i].events, revents);
0482         }
0483 
0484         if (revents & (POLLERR|POLLHUP|POLLNVAL)) {
0485 
0486             /*
0487              * if the error events were returned, add POLLIN and POLLOUT
0488              * to handle the events at least in one active handler
0489              */
0490 
0491             revents |= POLLIN|POLLOUT;
0492         }
0493 
0494         rev = c->read;
0495 
0496         if ((revents & POLLIN) && rev->active) {
0497             rev->ready = 1;
0498 
0499             if (flags & NGX_POST_EVENTS) {
0500                 queue = rev->accept ? &ngx_posted_accept_events
0501                                     : &ngx_posted_events;
0502 
0503                 ngx_post_event(rev, queue);
0504 
0505             } else {
0506                 instance = rev->instance;
0507 
0508                 rev->handler(rev);
0509 
0510                 if (c->fd == -1 || rev->instance != instance) {
0511                     continue;
0512                 }
0513             }
0514         }
0515 
0516         wev = c->write;
0517 
0518         if ((revents & POLLOUT) && wev->active) {
0519             wev->ready = 1;
0520 
0521             if (flags & NGX_POST_EVENTS) {
0522                 ngx_post_event(wev, &ngx_posted_events);
0523 
0524             } else {
0525                 wev->handler(wev);
0526             }
0527         }
0528     }
0529 
0530     return NGX_OK;
0531 }
0532 
0533 
0534 static void *
0535 ngx_devpoll_create_conf(ngx_cycle_t *cycle)
0536 {
0537     ngx_devpoll_conf_t  *dpcf;
0538 
0539     dpcf = ngx_palloc(cycle->pool, sizeof(ngx_devpoll_conf_t));
0540     if (dpcf == NULL) {
0541         return NULL;
0542     }
0543 
0544     dpcf->changes = NGX_CONF_UNSET;
0545     dpcf->events = NGX_CONF_UNSET;
0546 
0547     return dpcf;
0548 }
0549 
0550 
0551 static char *
0552 ngx_devpoll_init_conf(ngx_cycle_t *cycle, void *conf)
0553 {
0554     ngx_devpoll_conf_t *dpcf = conf;
0555 
0556     ngx_conf_init_uint_value(dpcf->changes, 32);
0557     ngx_conf_init_uint_value(dpcf->events, 32);
0558 
0559     return NGX_CONF_OK;
0560 }