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