Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

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 static ngx_int_t ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
0014 static void ngx_poll_done(ngx_cycle_t *cycle);
0015 static ngx_int_t ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event,
0016     ngx_uint_t flags);
0017 static ngx_int_t ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event,
0018     ngx_uint_t flags);
0019 static ngx_int_t ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
0020     ngx_uint_t flags);
0021 static char *ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf);
0022 
0023 
0024 static struct pollfd  *event_list;
0025 static ngx_uint_t      nevents;
0026 
0027 
0028 static ngx_str_t           poll_name = ngx_string("poll");
0029 
0030 static ngx_event_module_t  ngx_poll_module_ctx = {
0031     &poll_name,
0032     NULL,                                  /* create configuration */
0033     ngx_poll_init_conf,                    /* init configuration */
0034 
0035     {
0036         ngx_poll_add_event,                /* add an event */
0037         ngx_poll_del_event,                /* delete an event */
0038         ngx_poll_add_event,                /* enable an event */
0039         ngx_poll_del_event,                /* disable an event */
0040         NULL,                              /* add an connection */
0041         NULL,                              /* delete an connection */
0042         NULL,                              /* trigger a notify */
0043         ngx_poll_process_events,           /* process the events */
0044         ngx_poll_init,                     /* init the events */
0045         ngx_poll_done                      /* done the events */
0046     }
0047 
0048 };
0049 
0050 ngx_module_t  ngx_poll_module = {
0051     NGX_MODULE_V1,
0052     &ngx_poll_module_ctx,                  /* module context */
0053     NULL,                                  /* module directives */
0054     NGX_EVENT_MODULE,                      /* module type */
0055     NULL,                                  /* init master */
0056     NULL,                                  /* init module */
0057     NULL,                                  /* init process */
0058     NULL,                                  /* init thread */
0059     NULL,                                  /* exit thread */
0060     NULL,                                  /* exit process */
0061     NULL,                                  /* exit master */
0062     NGX_MODULE_V1_PADDING
0063 };
0064 
0065 
0066 
0067 static ngx_int_t
0068 ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
0069 {
0070     struct pollfd   *list;
0071 
0072     if (event_list == NULL) {
0073         nevents = 0;
0074     }
0075 
0076     if (ngx_process >= NGX_PROCESS_WORKER
0077         || cycle->old_cycle == NULL
0078         || cycle->old_cycle->connection_n < cycle->connection_n)
0079     {
0080         list = ngx_alloc(sizeof(struct pollfd) * cycle->connection_n,
0081                          cycle->log);
0082         if (list == NULL) {
0083             return NGX_ERROR;
0084         }
0085 
0086         if (event_list) {
0087             ngx_memcpy(list, event_list, sizeof(ngx_event_t *) * nevents);
0088             ngx_free(event_list);
0089         }
0090 
0091         event_list = list;
0092     }
0093 
0094     ngx_io = ngx_os_io;
0095 
0096     ngx_event_actions = ngx_poll_module_ctx.actions;
0097 
0098     ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_FD_EVENT;
0099 
0100     return NGX_OK;
0101 }
0102 
0103 
0104 static void
0105 ngx_poll_done(ngx_cycle_t *cycle)
0106 {
0107     ngx_free(event_list);
0108 
0109     event_list = NULL;
0110 }
0111 
0112 
0113 static ngx_int_t
0114 ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
0115 {
0116     ngx_event_t       *e;
0117     ngx_connection_t  *c;
0118 
0119     c = ev->data;
0120 
0121     ev->active = 1;
0122 
0123     if (ev->index != NGX_INVALID_INDEX) {
0124         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
0125                       "poll event fd:%d ev:%i is already set", c->fd, event);
0126         return NGX_OK;
0127     }
0128 
0129     if (event == NGX_READ_EVENT) {
0130         e = c->write;
0131 #if (NGX_READ_EVENT != POLLIN)
0132         event = POLLIN;
0133 #endif
0134 
0135     } else {
0136         e = c->read;
0137 #if (NGX_WRITE_EVENT != POLLOUT)
0138         event = POLLOUT;
0139 #endif
0140     }
0141 
0142     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0143                    "poll add event: fd:%d ev:%i", c->fd, event);
0144 
0145     if (e == NULL || e->index == NGX_INVALID_INDEX) {
0146         event_list[nevents].fd = c->fd;
0147         event_list[nevents].events = (short) event;
0148         event_list[nevents].revents = 0;
0149 
0150         ev->index = nevents;
0151         nevents++;
0152 
0153     } else {
0154         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0155                        "poll add index: %i", e->index);
0156 
0157         event_list[e->index].events |= (short) event;
0158         ev->index = e->index;
0159     }
0160 
0161     return NGX_OK;
0162 }
0163 
0164 
0165 static ngx_int_t
0166 ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
0167 {
0168     ngx_event_t       *e;
0169     ngx_connection_t  *c;
0170 
0171     c = ev->data;
0172 
0173     ev->active = 0;
0174 
0175     if (ev->index == NGX_INVALID_INDEX) {
0176         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
0177                       "poll event fd:%d ev:%i is already deleted",
0178                       c->fd, event);
0179         return NGX_OK;
0180     }
0181 
0182     if (event == NGX_READ_EVENT) {
0183         e = c->write;
0184 #if (NGX_READ_EVENT != POLLIN)
0185         event = POLLIN;
0186 #endif
0187 
0188     } else {
0189         e = c->read;
0190 #if (NGX_WRITE_EVENT != POLLOUT)
0191         event = POLLOUT;
0192 #endif
0193     }
0194 
0195     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0196                    "poll del event: fd:%d ev:%i", c->fd, event);
0197 
0198     if (e == NULL || e->index == NGX_INVALID_INDEX) {
0199         nevents--;
0200 
0201         if (ev->index < nevents) {
0202 
0203             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0204                            "index: copy event %ui to %i", nevents, ev->index);
0205 
0206             event_list[ev->index] = event_list[nevents];
0207 
0208             c = ngx_cycle->files[event_list[nevents].fd];
0209 
0210             if (c->fd == -1) {
0211                 ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
0212                               "unexpected last event");
0213 
0214             } else {
0215                 if (c->read->index == nevents) {
0216                     c->read->index = ev->index;
0217                 }
0218 
0219                 if (c->write->index == nevents) {
0220                     c->write->index = ev->index;
0221                 }
0222             }
0223         }
0224 
0225     } else {
0226         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0227                        "poll del index: %i", e->index);
0228 
0229         event_list[e->index].events &= (short) ~event;
0230     }
0231 
0232     ev->index = NGX_INVALID_INDEX;
0233 
0234     return NGX_OK;
0235 }
0236 
0237 
0238 static ngx_int_t
0239 ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
0240 {
0241     int                 ready, revents;
0242     ngx_err_t           err;
0243     ngx_uint_t          i, found, level;
0244     ngx_event_t        *ev;
0245     ngx_queue_t        *queue;
0246     ngx_connection_t   *c;
0247 
0248     /* NGX_TIMER_INFINITE == INFTIM */
0249 
0250 #if (NGX_DEBUG0)
0251     if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
0252         for (i = 0; i < nevents; i++) {
0253             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0254                            "poll: %ui: fd:%d ev:%04Xd",
0255                            i, event_list[i].fd, event_list[i].events);
0256         }
0257     }
0258 #endif
0259 
0260     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "poll timer: %M", timer);
0261 
0262     ready = poll(event_list, (u_int) nevents, (int) timer);
0263 
0264     err = (ready == -1) ? ngx_errno : 0;
0265 
0266     if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
0267         ngx_time_update();
0268     }
0269 
0270     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0271                    "poll ready %d of %ui", ready, nevents);
0272 
0273     if (err) {
0274         if (err == NGX_EINTR) {
0275 
0276             if (ngx_event_timer_alarm) {
0277                 ngx_event_timer_alarm = 0;
0278                 return NGX_OK;
0279             }
0280 
0281             level = NGX_LOG_INFO;
0282 
0283         } else {
0284             level = NGX_LOG_ALERT;
0285         }
0286 
0287         ngx_log_error(level, cycle->log, err, "poll() failed");
0288         return NGX_ERROR;
0289     }
0290 
0291     if (ready == 0) {
0292         if (timer != NGX_TIMER_INFINITE) {
0293             return NGX_OK;
0294         }
0295 
0296         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0297                       "poll() returned no events without timeout");
0298         return NGX_ERROR;
0299     }
0300 
0301     for (i = 0; i < nevents && ready; i++) {
0302 
0303         revents = event_list[i].revents;
0304 
0305 #if 1
0306         ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0307                        "poll: %ui: fd:%d ev:%04Xd rev:%04Xd",
0308                        i, event_list[i].fd, event_list[i].events, revents);
0309 #else
0310         if (revents) {
0311             ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0312                            "poll: %ui: fd:%d ev:%04Xd rev:%04Xd",
0313                            i, event_list[i].fd, event_list[i].events, revents);
0314         }
0315 #endif
0316 
0317         if (revents & POLLNVAL) {
0318             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0319                           "poll() error fd:%d ev:%04Xd rev:%04Xd",
0320                           event_list[i].fd, event_list[i].events, revents);
0321         }
0322 
0323         if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
0324             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0325                           "strange poll() events fd:%d ev:%04Xd rev:%04Xd",
0326                           event_list[i].fd, event_list[i].events, revents);
0327         }
0328 
0329         if (event_list[i].fd == -1) {
0330             /*
0331              * the disabled event, a workaround for our possible bug,
0332              * see the comment below
0333              */
0334             continue;
0335         }
0336 
0337         c = ngx_cycle->files[event_list[i].fd];
0338 
0339         if (c->fd == -1) {
0340             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event");
0341 
0342             /*
0343              * it is certainly our fault and it should be investigated,
0344              * in the meantime we disable this event to avoid a CPU spinning
0345              */
0346 
0347             if (i == nevents - 1) {
0348                 nevents--;
0349             } else {
0350                 event_list[i].fd = -1;
0351             }
0352 
0353             continue;
0354         }
0355 
0356         if (revents & (POLLERR|POLLHUP|POLLNVAL)) {
0357 
0358             /*
0359              * if the error events were returned, add POLLIN and POLLOUT
0360              * to handle the events at least in one active handler
0361              */
0362 
0363             revents |= POLLIN|POLLOUT;
0364         }
0365 
0366         found = 0;
0367 
0368         if ((revents & POLLIN) && c->read->active) {
0369             found = 1;
0370 
0371             ev = c->read;
0372             ev->ready = 1;
0373 
0374             queue = ev->accept ? &ngx_posted_accept_events
0375                                : &ngx_posted_events;
0376 
0377             ngx_post_event(ev, queue);
0378         }
0379 
0380         if ((revents & POLLOUT) && c->write->active) {
0381             found = 1;
0382 
0383             ev = c->write;
0384             ev->ready = 1;
0385 
0386             ngx_post_event(ev, &ngx_posted_events);
0387         }
0388 
0389         if (found) {
0390             ready--;
0391             continue;
0392         }
0393     }
0394 
0395     if (ready != 0) {
0396         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "poll ready != events");
0397     }
0398 
0399     return NGX_OK;
0400 }
0401 
0402 
0403 static char *
0404 ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf)
0405 {
0406     ngx_event_conf_t  *ecf;
0407 
0408     ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
0409 
0410     if (ecf->use != ngx_poll_module.ctx_index) {
0411         return NGX_CONF_OK;
0412     }
0413 
0414     return NGX_CONF_OK;
0415 }