Annotation of embedaddon/nginx/src/event/modules/ngx_win32_select_module.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: #include <ngx_event.h>
                     11: 
                     12: 
                     13: static ngx_int_t ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer);
                     14: static void ngx_select_done(ngx_cycle_t *cycle);
                     15: static ngx_int_t ngx_select_add_event(ngx_event_t *ev, ngx_int_t event,
                     16:     ngx_uint_t flags);
                     17: static ngx_int_t ngx_select_del_event(ngx_event_t *ev, ngx_int_t event,
                     18:     ngx_uint_t flags);
                     19: static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
                     20:     ngx_uint_t flags);
                     21: static void ngx_select_repair_fd_sets(ngx_cycle_t *cycle);
                     22: static char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf);
                     23: 
                     24: 
                     25: static fd_set         master_read_fd_set;
                     26: static fd_set         master_write_fd_set;
                     27: static fd_set         work_read_fd_set;
                     28: static fd_set         work_write_fd_set;
                     29: 
                     30: static ngx_uint_t     max_read;
                     31: static ngx_uint_t     max_write;
                     32: static ngx_uint_t     nevents;
                     33: 
                     34: static ngx_event_t  **event_index;
                     35: 
                     36: 
                     37: static ngx_str_t    select_name = ngx_string("select");
                     38: 
                     39: ngx_event_module_t  ngx_select_module_ctx = {
                     40:     &select_name,
                     41:     NULL,                                  /* create configuration */
                     42:     ngx_select_init_conf,                  /* init configuration */
                     43: 
                     44:     {
                     45:         ngx_select_add_event,              /* add an event */
                     46:         ngx_select_del_event,              /* delete an event */
                     47:         ngx_select_add_event,              /* enable an event */
                     48:         ngx_select_del_event,              /* disable an event */
                     49:         NULL,                              /* add an connection */
                     50:         NULL,                              /* delete an connection */
                     51:         NULL,                              /* process the changes */
                     52:         ngx_select_process_events,         /* process the events */
                     53:         ngx_select_init,                   /* init the events */
                     54:         ngx_select_done                    /* done the events */
                     55:     }
                     56: 
                     57: };
                     58: 
                     59: ngx_module_t  ngx_select_module = {
                     60:     NGX_MODULE_V1,
                     61:     &ngx_select_module_ctx,                /* module context */
                     62:     NULL,                                  /* module directives */
                     63:     NGX_EVENT_MODULE,                      /* module type */
                     64:     NULL,                                  /* init master */
                     65:     NULL,                                  /* init module */
                     66:     NULL,                                  /* init process */
                     67:     NULL,                                  /* init thread */
                     68:     NULL,                                  /* exit thread */
                     69:     NULL,                                  /* exit process */
                     70:     NULL,                                  /* exit master */
                     71:     NGX_MODULE_V1_PADDING
                     72: };
                     73: 
                     74: 
                     75: static ngx_int_t
                     76: ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer)
                     77: {
                     78:     ngx_event_t  **index;
                     79: 
                     80:     if (event_index == NULL) {
                     81:         FD_ZERO(&master_read_fd_set);
                     82:         FD_ZERO(&master_write_fd_set);
                     83:         nevents = 0;
                     84:     }
                     85: 
                     86:     if (ngx_process >= NGX_PROCESS_WORKER
                     87:         || cycle->old_cycle == NULL
                     88:         || cycle->old_cycle->connection_n < cycle->connection_n)
                     89:     {
                     90:         index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
                     91:                           cycle->log);
                     92:         if (index == NULL) {
                     93:             return NGX_ERROR;
                     94:         }
                     95: 
                     96:         if (event_index) {
                     97:             ngx_memcpy(index, event_index, sizeof(ngx_event_t *) * nevents);
                     98:             ngx_free(event_index);
                     99:         }
                    100: 
                    101:         event_index = index;
                    102:     }
                    103: 
                    104:     ngx_io = ngx_os_io;
                    105: 
                    106:     ngx_event_actions = ngx_select_module_ctx.actions;
                    107: 
                    108:     ngx_event_flags = NGX_USE_LEVEL_EVENT;
                    109: 
                    110:     max_read = 0;
                    111:     max_write = 0;
                    112: 
                    113:     return NGX_OK;
                    114: }
                    115: 
                    116: 
                    117: static void
                    118: ngx_select_done(ngx_cycle_t *cycle)
                    119: {
                    120:     ngx_free(event_index);
                    121: 
                    122:     event_index = NULL;
                    123: }
                    124: 
                    125: 
                    126: static ngx_int_t
                    127: ngx_select_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
                    128: {
                    129:     ngx_connection_t  *c;
                    130: 
                    131:     c = ev->data;
                    132: 
                    133:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                    134:                    "select add event fd:%d ev:%i", c->fd, event);
                    135: 
                    136:     if (ev->index != NGX_INVALID_INDEX) {
                    137:         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
                    138:                       "select event fd:%d ev:%i is already set", c->fd, event);
                    139:         return NGX_OK;
                    140:     }
                    141: 
                    142:     if ((event == NGX_READ_EVENT && ev->write)
                    143:         || (event == NGX_WRITE_EVENT && !ev->write))
                    144:     {
                    145:         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
                    146:                       "invalid select %s event fd:%d ev:%i",
                    147:                       ev->write ? "write" : "read", c->fd, event);
                    148:         return NGX_ERROR;
                    149:     }
                    150: 
                    151:     if ((event == NGX_READ_EVENT) && (max_read >= FD_SETSIZE)
                    152:         || (event == NGX_WRITE_EVENT) && (max_write >= FD_SETSIZE))
                    153:     {
                    154:         ngx_log_error(NGX_LOG_ERR, ev->log, 0,
                    155:                       "maximum number of descriptors "
                    156:                       "supported by select() is %d", FD_SETSIZE);
                    157:         return NGX_ERROR;
                    158:     }
                    159: 
                    160:     if (event == NGX_READ_EVENT) {
                    161:         FD_SET(c->fd, &master_read_fd_set);
                    162:         max_read++;
                    163: 
                    164:     } else if (event == NGX_WRITE_EVENT) {
                    165:         FD_SET(c->fd, &master_write_fd_set);
                    166:         max_write++;
                    167:     }
                    168: 
                    169:     ev->active = 1;
                    170: 
                    171:     event_index[nevents] = ev;
                    172:     ev->index = nevents;
                    173:     nevents++;
                    174: 
                    175:     return NGX_OK;
                    176: }
                    177: 
                    178: 
                    179: static ngx_int_t
                    180: ngx_select_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
                    181: {
                    182:     ngx_event_t       *e;
                    183:     ngx_connection_t  *c;
                    184: 
                    185:     c = ev->data;
                    186: 
                    187:     ev->active = 0;
                    188: 
                    189:     if (ev->index == NGX_INVALID_INDEX) {
                    190:         return NGX_OK;
                    191:     }
                    192: 
                    193:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                    194:                    "select del event fd:%d ev:%i", c->fd, event);
                    195: 
                    196:     if (event == NGX_READ_EVENT) {
                    197:         FD_CLR(c->fd, &master_read_fd_set);
                    198:         max_read--;
                    199: 
                    200:     } else if (event == NGX_WRITE_EVENT) {
                    201:         FD_CLR(c->fd, &master_write_fd_set);
                    202:         max_write--;
                    203:     }
                    204: 
                    205:     if (ev->index < --nevents) {
                    206:         e = event_index[nevents];
                    207:         event_index[ev->index] = e;
                    208:         e->index = ev->index;
                    209:     }
                    210: 
                    211:     ev->index = NGX_INVALID_INDEX;
                    212: 
                    213:     return NGX_OK;
                    214: }
                    215: 
                    216: 
                    217: static ngx_int_t
                    218: ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
                    219:     ngx_uint_t flags)
                    220: {
                    221:     int                ready, nready;
                    222:     ngx_err_t          err;
                    223:     ngx_uint_t         i, found;
                    224:     ngx_event_t       *ev, **queue;
                    225:     struct timeval     tv, *tp;
                    226:     ngx_connection_t  *c;
                    227: 
                    228: #if (NGX_DEBUG)
                    229:     if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
                    230:         for (i = 0; i < nevents; i++) {
                    231:             ev = event_index[i];
                    232:             c = ev->data;
                    233:             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    234:                            "select event: fd:%d wr:%d", c->fd, ev->write);
                    235:         }
                    236:     }
                    237: #endif
                    238: 
                    239:     if (timer == NGX_TIMER_INFINITE) {
                    240:         tp = NULL;
                    241: 
                    242:     } else {
                    243:         tv.tv_sec = (long) (timer / 1000);
                    244:         tv.tv_usec = (long) ((timer % 1000) * 1000);
                    245:         tp = &tv;
                    246:     }
                    247: 
                    248:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    249:                    "select timer: %M", timer);
                    250: 
                    251:     work_read_fd_set = master_read_fd_set;
                    252:     work_write_fd_set = master_write_fd_set;
                    253: 
                    254:     if (max_read || max_write) {
                    255:         ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp);
                    256: 
                    257:     } else {
                    258: 
                    259:         /*
                    260:          * Winsock select() requires that at least one descriptor set must be
                    261:          * be non-null, and any non-null descriptor set must contain at least
                    262:          * one handle to a socket.  Otherwise select() returns WSAEINVAL.
                    263:          */
                    264: 
                    265:         ngx_msleep(timer);
                    266: 
                    267:         ready = 0;
                    268:     }
                    269: 
                    270:     err = (ready == -1) ? ngx_socket_errno : 0;
                    271: 
                    272:     if (flags & NGX_UPDATE_TIME) {
                    273:         ngx_time_update();
                    274:     }
                    275: 
                    276:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    277:                    "select ready %d", ready);
                    278: 
                    279:     if (err) {
                    280:         ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed");
                    281: 
                    282:         if (err == WSAENOTSOCK) {
                    283:             ngx_select_repair_fd_sets(cycle);
                    284:         }
                    285: 
                    286:         return NGX_ERROR;
                    287:     }
                    288: 
                    289:     if (ready == 0) {
                    290:         if (timer != NGX_TIMER_INFINITE) {
                    291:             return NGX_OK;
                    292:         }
                    293: 
                    294:         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                    295:                       "select() returned no events without timeout");
                    296:         return NGX_ERROR;
                    297:     }
                    298: 
                    299:     ngx_mutex_lock(ngx_posted_events_mutex);
                    300: 
                    301:     nready = 0;
                    302: 
                    303:     for (i = 0; i < nevents; i++) {
                    304:         ev = event_index[i];
                    305:         c = ev->data;
                    306:         found = 0;
                    307: 
                    308:         if (ev->write) {
                    309:             if (FD_ISSET(c->fd, &work_write_fd_set)) {
                    310:                 found = 1;
                    311:                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    312:                                "select write %d", c->fd);
                    313:             }
                    314: 
                    315:         } else {
                    316:             if (FD_ISSET(c->fd, &work_read_fd_set)) {
                    317:                 found = 1;
                    318:                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    319:                                "select read %d", c->fd);
                    320:             }
                    321:         }
                    322: 
                    323:         if (found) {
                    324:             ev->ready = 1;
                    325: 
                    326:             queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events:
                    327:                                                    &ngx_posted_events);
                    328:             ngx_locked_post_event(ev, queue);
                    329: 
                    330:             nready++;
                    331:         }
                    332:     }
                    333: 
                    334:     ngx_mutex_unlock(ngx_posted_events_mutex);
                    335: 
                    336:     if (ready != nready) {
                    337:         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                    338:                       "select ready != events: %d:%d", ready, nready);
                    339: 
                    340:         ngx_select_repair_fd_sets(cycle);
                    341:     }
                    342: 
                    343:     return NGX_OK;
                    344: }
                    345: 
                    346: 
                    347: static void
                    348: ngx_select_repair_fd_sets(ngx_cycle_t *cycle)
                    349: {
                    350:     int           n;
                    351:     u_int         i;
                    352:     socklen_t     len;
                    353:     ngx_err_t     err;
                    354:     ngx_socket_t  s;
                    355: 
                    356:     for (i = 0; i < master_read_fd_set.fd_count; i++) {
                    357: 
                    358:         s = master_read_fd_set.fd_array[i];
                    359:         len = sizeof(int);
                    360: 
                    361:         if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
                    362:             err = ngx_socket_errno;
                    363: 
                    364:             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
                    365:                           "invalid descriptor #%d in read fd_set", s);
                    366: 
                    367:             FD_CLR(s, &master_read_fd_set);
                    368:         }
                    369:     }
                    370: 
                    371:     for (i = 0; i < master_write_fd_set.fd_count; i++) {
                    372: 
                    373:         s = master_write_fd_set.fd_array[i];
                    374:         len = sizeof(int);
                    375: 
                    376:         if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
                    377:             err = ngx_socket_errno;
                    378: 
                    379:             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
                    380:                           "invalid descriptor #%d in write fd_set", s);
                    381: 
                    382:             FD_CLR(s, &master_write_fd_set);
                    383:         }
                    384:     }
                    385: }
                    386: 
                    387: 
                    388: static char *
                    389: ngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
                    390: {
                    391:     ngx_event_conf_t  *ecf;
                    392: 
                    393:     ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
                    394: 
                    395:     if (ecf->use != ngx_select_module.ctx_index) {
                    396:         return NGX_CONF_OK;
                    397:     }
                    398: 
                    399:     return NGX_CONF_OK;
                    400: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>