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