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 static ngx_int_t ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer);
0014 static void ngx_select_done(ngx_cycle_t *cycle);
0015 static ngx_int_t ngx_select_add_event(ngx_event_t *ev, ngx_int_t event,
0016     ngx_uint_t flags);
0017 static ngx_int_t ngx_select_del_event(ngx_event_t *ev, ngx_int_t event,
0018     ngx_uint_t flags);
0019 static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
0020     ngx_uint_t flags);
0021 static void ngx_select_repair_fd_sets(ngx_cycle_t *cycle);
0022 static char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf);
0023 
0024 
0025 static fd_set         master_read_fd_set;
0026 static fd_set         master_write_fd_set;
0027 static fd_set         work_read_fd_set;
0028 static fd_set         work_write_fd_set;
0029 static fd_set         work_except_fd_set;
0030 
0031 static ngx_uint_t     max_read;
0032 static ngx_uint_t     max_write;
0033 static ngx_uint_t     nevents;
0034 
0035 static ngx_event_t  **event_index;
0036 
0037 
0038 static ngx_str_t           select_name = ngx_string("select");
0039 
0040 static ngx_event_module_t  ngx_select_module_ctx = {
0041     &select_name,
0042     NULL,                                  /* create configuration */
0043     ngx_select_init_conf,                  /* init configuration */
0044 
0045     {
0046         ngx_select_add_event,              /* add an event */
0047         ngx_select_del_event,              /* delete an event */
0048         ngx_select_add_event,              /* enable an event */
0049         ngx_select_del_event,              /* disable an event */
0050         NULL,                              /* add an connection */
0051         NULL,                              /* delete an connection */
0052         NULL,                              /* trigger a notify */
0053         ngx_select_process_events,         /* process the events */
0054         ngx_select_init,                   /* init the events */
0055         ngx_select_done                    /* done the events */
0056     }
0057 
0058 };
0059 
0060 ngx_module_t  ngx_select_module = {
0061     NGX_MODULE_V1,
0062     &ngx_select_module_ctx,                /* module context */
0063     NULL,                                  /* module directives */
0064     NGX_EVENT_MODULE,                      /* module type */
0065     NULL,                                  /* init master */
0066     NULL,                                  /* init module */
0067     NULL,                                  /* init process */
0068     NULL,                                  /* init thread */
0069     NULL,                                  /* exit thread */
0070     NULL,                                  /* exit process */
0071     NULL,                                  /* exit master */
0072     NGX_MODULE_V1_PADDING
0073 };
0074 
0075 
0076 static ngx_int_t
0077 ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer)
0078 {
0079     ngx_event_t  **index;
0080 
0081     if (event_index == NULL) {
0082         FD_ZERO(&master_read_fd_set);
0083         FD_ZERO(&master_write_fd_set);
0084         nevents = 0;
0085     }
0086 
0087     if (ngx_process >= NGX_PROCESS_WORKER
0088         || cycle->old_cycle == NULL
0089         || cycle->old_cycle->connection_n < cycle->connection_n)
0090     {
0091         index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
0092                           cycle->log);
0093         if (index == NULL) {
0094             return NGX_ERROR;
0095         }
0096 
0097         if (event_index) {
0098             ngx_memcpy(index, event_index, sizeof(ngx_event_t *) * nevents);
0099             ngx_free(event_index);
0100         }
0101 
0102         event_index = index;
0103     }
0104 
0105     ngx_io = ngx_os_io;
0106 
0107     ngx_event_actions = ngx_select_module_ctx.actions;
0108 
0109     ngx_event_flags = NGX_USE_LEVEL_EVENT;
0110 
0111     max_read = 0;
0112     max_write = 0;
0113 
0114     return NGX_OK;
0115 }
0116 
0117 
0118 static void
0119 ngx_select_done(ngx_cycle_t *cycle)
0120 {
0121     ngx_free(event_index);
0122 
0123     event_index = NULL;
0124 }
0125 
0126 
0127 static ngx_int_t
0128 ngx_select_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
0129 {
0130     ngx_connection_t  *c;
0131 
0132     c = ev->data;
0133 
0134     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0135                    "select add event fd:%d ev:%i", c->fd, event);
0136 
0137     if (ev->index != NGX_INVALID_INDEX) {
0138         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
0139                       "select event fd:%d ev:%i is already set", c->fd, event);
0140         return NGX_OK;
0141     }
0142 
0143     if ((event == NGX_READ_EVENT && ev->write)
0144         || (event == NGX_WRITE_EVENT && !ev->write))
0145     {
0146         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
0147                       "invalid select %s event fd:%d ev:%i",
0148                       ev->write ? "write" : "read", c->fd, event);
0149         return NGX_ERROR;
0150     }
0151 
0152     if ((event == NGX_READ_EVENT && max_read >= FD_SETSIZE)
0153         || (event == NGX_WRITE_EVENT && max_write >= FD_SETSIZE))
0154     {
0155         ngx_log_error(NGX_LOG_ERR, ev->log, 0,
0156                       "maximum number of descriptors "
0157                       "supported by select() is %d", FD_SETSIZE);
0158         return NGX_ERROR;
0159     }
0160 
0161     if (event == NGX_READ_EVENT) {
0162         FD_SET(c->fd, &master_read_fd_set);
0163         max_read++;
0164 
0165     } else if (event == NGX_WRITE_EVENT) {
0166         FD_SET(c->fd, &master_write_fd_set);
0167         max_write++;
0168     }
0169 
0170     ev->active = 1;
0171 
0172     event_index[nevents] = ev;
0173     ev->index = nevents;
0174     nevents++;
0175 
0176     return NGX_OK;
0177 }
0178 
0179 
0180 static ngx_int_t
0181 ngx_select_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
0182 {
0183     ngx_event_t       *e;
0184     ngx_connection_t  *c;
0185 
0186     c = ev->data;
0187 
0188     ev->active = 0;
0189 
0190     if (ev->index == NGX_INVALID_INDEX) {
0191         return NGX_OK;
0192     }
0193 
0194     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0195                    "select del event fd:%d ev:%i", c->fd, event);
0196 
0197     if (event == NGX_READ_EVENT) {
0198         FD_CLR(c->fd, &master_read_fd_set);
0199         max_read--;
0200 
0201     } else if (event == NGX_WRITE_EVENT) {
0202         FD_CLR(c->fd, &master_write_fd_set);
0203         max_write--;
0204     }
0205 
0206     if (ev->index < --nevents) {
0207         e = event_index[nevents];
0208         event_index[ev->index] = e;
0209         e->index = ev->index;
0210     }
0211 
0212     ev->index = NGX_INVALID_INDEX;
0213 
0214     return NGX_OK;
0215 }
0216 
0217 
0218 static ngx_int_t
0219 ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
0220     ngx_uint_t flags)
0221 {
0222     int                ready, nready;
0223     ngx_err_t          err;
0224     ngx_uint_t         i, found;
0225     ngx_event_t       *ev;
0226     ngx_queue_t       *queue;
0227     struct timeval     tv, *tp;
0228     ngx_connection_t  *c;
0229 
0230 #if (NGX_DEBUG)
0231     if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
0232         for (i = 0; i < nevents; i++) {
0233             ev = event_index[i];
0234             c = ev->data;
0235             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0236                            "select event: fd:%d wr:%d", c->fd, ev->write);
0237         }
0238     }
0239 #endif
0240 
0241     if (timer == NGX_TIMER_INFINITE) {
0242         tp = NULL;
0243 
0244     } else {
0245         tv.tv_sec = (long) (timer / 1000);
0246         tv.tv_usec = (long) ((timer % 1000) * 1000);
0247         tp = &tv;
0248     }
0249 
0250     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0251                    "select timer: %M", timer);
0252 
0253     work_read_fd_set = master_read_fd_set;
0254     work_write_fd_set = master_write_fd_set;
0255     work_except_fd_set = master_write_fd_set;
0256 
0257     if (max_read || max_write) {
0258         ready = select(0, &work_read_fd_set, &work_write_fd_set,
0259                        &work_except_fd_set, tp);
0260 
0261     } else {
0262 
0263         /*
0264          * Winsock select() requires that at least one descriptor set must be
0265          * be non-null, and any non-null descriptor set must contain at least
0266          * one handle to a socket.  Otherwise select() returns WSAEINVAL.
0267          */
0268 
0269         ngx_msleep(timer);
0270 
0271         ready = 0;
0272     }
0273 
0274     err = (ready == -1) ? ngx_socket_errno : 0;
0275 
0276     if (flags & NGX_UPDATE_TIME) {
0277         ngx_time_update();
0278     }
0279 
0280     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0281                    "select ready %d", ready);
0282 
0283     if (err) {
0284         ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed");
0285 
0286         if (err == WSAENOTSOCK) {
0287             ngx_select_repair_fd_sets(cycle);
0288         }
0289 
0290         return NGX_ERROR;
0291     }
0292 
0293     if (ready == 0) {
0294         if (timer != NGX_TIMER_INFINITE) {
0295             return NGX_OK;
0296         }
0297 
0298         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0299                       "select() returned no events without timeout");
0300         return NGX_ERROR;
0301     }
0302 
0303     nready = 0;
0304 
0305     for (i = 0; i < nevents; i++) {
0306         ev = event_index[i];
0307         c = ev->data;
0308         found = 0;
0309 
0310         if (ev->write) {
0311             if (FD_ISSET(c->fd, &work_write_fd_set)) {
0312                 found++;
0313                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0314                                "select write %d", c->fd);
0315             }
0316 
0317             if (FD_ISSET(c->fd, &work_except_fd_set)) {
0318                 found++;
0319                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0320                                "select except %d", c->fd);
0321             }
0322 
0323         } else {
0324             if (FD_ISSET(c->fd, &work_read_fd_set)) {
0325                 found++;
0326                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0327                                "select read %d", c->fd);
0328             }
0329         }
0330 
0331         if (found) {
0332             ev->ready = 1;
0333 
0334             queue = ev->accept ? &ngx_posted_accept_events
0335                                : &ngx_posted_events;
0336 
0337             ngx_post_event(ev, queue);
0338 
0339             nready += found;
0340         }
0341     }
0342 
0343     if (ready != nready) {
0344         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0345                       "select ready != events: %d:%d", ready, nready);
0346 
0347         ngx_select_repair_fd_sets(cycle);
0348     }
0349 
0350     return NGX_OK;
0351 }
0352 
0353 
0354 static void
0355 ngx_select_repair_fd_sets(ngx_cycle_t *cycle)
0356 {
0357     int           n;
0358     u_int         i;
0359     socklen_t     len;
0360     ngx_err_t     err;
0361     ngx_socket_t  s;
0362 
0363     for (i = 0; i < master_read_fd_set.fd_count; i++) {
0364 
0365         s = master_read_fd_set.fd_array[i];
0366         len = sizeof(int);
0367 
0368         if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
0369             err = ngx_socket_errno;
0370 
0371             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
0372                           "invalid descriptor #%d in read fd_set", s);
0373 
0374             FD_CLR(s, &master_read_fd_set);
0375         }
0376     }
0377 
0378     for (i = 0; i < master_write_fd_set.fd_count; i++) {
0379 
0380         s = master_write_fd_set.fd_array[i];
0381         len = sizeof(int);
0382 
0383         if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
0384             err = ngx_socket_errno;
0385 
0386             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
0387                           "invalid descriptor #%d in write fd_set", s);
0388 
0389             FD_CLR(s, &master_write_fd_set);
0390         }
0391     }
0392 }
0393 
0394 
0395 static char *
0396 ngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
0397 {
0398     ngx_event_conf_t  *ecf;
0399 
0400     ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
0401 
0402     if (ecf->use != ngx_select_module.ctx_index) {
0403         return NGX_CONF_OK;
0404     }
0405 
0406     return NGX_CONF_OK;
0407 }