src/event/modules/ngx_win32_select_module.c - nginx-1.7.10

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>


  8. static ngx_int_t ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer);
  9. static void ngx_select_done(ngx_cycle_t *cycle);
  10. static ngx_int_t ngx_select_add_event(ngx_event_t *ev, ngx_int_t event,
  11.     ngx_uint_t flags);
  12. static ngx_int_t ngx_select_del_event(ngx_event_t *ev, ngx_int_t event,
  13.     ngx_uint_t flags);
  14. static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
  15.     ngx_uint_t flags);
  16. static void ngx_select_repair_fd_sets(ngx_cycle_t *cycle);
  17. static char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf);


  18. static fd_set         master_read_fd_set;
  19. static fd_set         master_write_fd_set;
  20. static fd_set         work_read_fd_set;
  21. static fd_set         work_write_fd_set;

  22. static ngx_uint_t     max_read;
  23. static ngx_uint_t     max_write;
  24. static ngx_uint_t     nevents;

  25. static ngx_event_t  **event_index;


  26. static ngx_str_t    select_name = ngx_string("select");

  27. ngx_event_module_t  ngx_select_module_ctx = {
  28.     &select_name,
  29.     NULL,                                  /* create configuration */
  30.     ngx_select_init_conf,                  /* init configuration */

  31.     {
  32.         ngx_select_add_event,              /* add an event */
  33.         ngx_select_del_event,              /* delete an event */
  34.         ngx_select_add_event,              /* enable an event */
  35.         ngx_select_del_event,              /* disable an event */
  36.         NULL,                              /* add an connection */
  37.         NULL,                              /* delete an connection */
  38.         NULL,                              /* process the changes */
  39.         ngx_select_process_events,         /* process the events */
  40.         ngx_select_init,                   /* init the events */
  41.         ngx_select_done                    /* done the events */
  42.     }

  43. };

  44. ngx_module_t  ngx_select_module = {
  45.     NGX_MODULE_V1,
  46.     &ngx_select_module_ctx,                /* module context */
  47.     NULL,                                  /* module directives */
  48.     NGX_EVENT_MODULE,                      /* module type */
  49.     NULL,                                  /* init master */
  50.     NULL,                                  /* init module */
  51.     NULL,                                  /* init process */
  52.     NULL,                                  /* init thread */
  53.     NULL,                                  /* exit thread */
  54.     NULL,                                  /* exit process */
  55.     NULL,                                  /* exit master */
  56.     NGX_MODULE_V1_PADDING
  57. };


  58. static ngx_int_t
  59. ngx_select_init(ngx_cycle_t *cycle, ngx_msec_t timer)
  60. {
  61.     ngx_event_t  **index;

  62.     if (event_index == NULL) {
  63.         FD_ZERO(&master_read_fd_set);
  64.         FD_ZERO(&master_write_fd_set);
  65.         nevents = 0;
  66.     }

  67.     if (ngx_process >= NGX_PROCESS_WORKER
  68.         || cycle->old_cycle == NULL
  69.         || cycle->old_cycle->connection_n < cycle->connection_n)
  70.     {
  71.         index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
  72.                           cycle->log);
  73.         if (index == NULL) {
  74.             return NGX_ERROR;
  75.         }

  76.         if (event_index) {
  77.             ngx_memcpy(index, event_index, sizeof(ngx_event_t *) * nevents);
  78.             ngx_free(event_index);
  79.         }

  80.         event_index = index;
  81.     }

  82.     ngx_io = ngx_os_io;

  83.     ngx_event_actions = ngx_select_module_ctx.actions;

  84.     ngx_event_flags = NGX_USE_LEVEL_EVENT;

  85.     max_read = 0;
  86.     max_write = 0;

  87.     return NGX_OK;
  88. }


  89. static void
  90. ngx_select_done(ngx_cycle_t *cycle)
  91. {
  92.     ngx_free(event_index);

  93.     event_index = NULL;
  94. }


  95. static ngx_int_t
  96. ngx_select_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  97. {
  98.     ngx_connection_t  *c;

  99.     c = ev->data;

  100.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  101.                    "select add event fd:%d ev:%i", c->fd, event);

  102.     if (ev->index != NGX_INVALID_INDEX) {
  103.         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
  104.                       "select event fd:%d ev:%i is already set", c->fd, event);
  105.         return NGX_OK;
  106.     }

  107.     if ((event == NGX_READ_EVENT && ev->write)
  108.         || (event == NGX_WRITE_EVENT && !ev->write))
  109.     {
  110.         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
  111.                       "invalid select %s event fd:%d ev:%i",
  112.                       ev->write ? "write" : "read", c->fd, event);
  113.         return NGX_ERROR;
  114.     }

  115.     if ((event == NGX_READ_EVENT && max_read >= FD_SETSIZE)
  116.         || (event == NGX_WRITE_EVENT && max_write >= FD_SETSIZE))
  117.     {
  118.         ngx_log_error(NGX_LOG_ERR, ev->log, 0,
  119.                       "maximum number of descriptors "
  120.                       "supported by select() is %d", FD_SETSIZE);
  121.         return NGX_ERROR;
  122.     }

  123.     if (event == NGX_READ_EVENT) {
  124.         FD_SET(c->fd, &master_read_fd_set);
  125.         max_read++;

  126.     } else if (event == NGX_WRITE_EVENT) {
  127.         FD_SET(c->fd, &master_write_fd_set);
  128.         max_write++;
  129.     }

  130.     ev->active = 1;

  131.     event_index[nevents] = ev;
  132.     ev->index = nevents;
  133.     nevents++;

  134.     return NGX_OK;
  135. }


  136. static ngx_int_t
  137. ngx_select_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  138. {
  139.     ngx_event_t       *e;
  140.     ngx_connection_t  *c;

  141.     c = ev->data;

  142.     ev->active = 0;

  143.     if (ev->index == NGX_INVALID_INDEX) {
  144.         return NGX_OK;
  145.     }

  146.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  147.                    "select del event fd:%d ev:%i", c->fd, event);

  148.     if (event == NGX_READ_EVENT) {
  149.         FD_CLR(c->fd, &master_read_fd_set);
  150.         max_read--;

  151.     } else if (event == NGX_WRITE_EVENT) {
  152.         FD_CLR(c->fd, &master_write_fd_set);
  153.         max_write--;
  154.     }

  155.     if (ev->index < --nevents) {
  156.         e = event_index[nevents];
  157.         event_index[ev->index] = e;
  158.         e->index = ev->index;
  159.     }

  160.     ev->index = NGX_INVALID_INDEX;

  161.     return NGX_OK;
  162. }


  163. static ngx_int_t
  164. ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
  165.     ngx_uint_t flags)
  166. {
  167.     int                ready, nready;
  168.     ngx_err_t          err;
  169.     ngx_uint_t         i, found;
  170.     ngx_event_t       *ev;
  171.     ngx_queue_t       *queue;
  172.     struct timeval     tv, *tp;
  173.     ngx_connection_t  *c;

  174. #if (NGX_DEBUG)
  175.     if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
  176.         for (i = 0; i < nevents; i++) {
  177.             ev = event_index[i];
  178.             c = ev->data;
  179.             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  180.                            "select event: fd:%d wr:%d", c->fd, ev->write);
  181.         }
  182.     }
  183. #endif

  184.     if (timer == NGX_TIMER_INFINITE) {
  185.         tp = NULL;

  186.     } else {
  187.         tv.tv_sec = (long) (timer / 1000);
  188.         tv.tv_usec = (long) ((timer % 1000) * 1000);
  189.         tp = &tv;
  190.     }

  191.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  192.                    "select timer: %M", timer);

  193.     work_read_fd_set = master_read_fd_set;
  194.     work_write_fd_set = master_write_fd_set;

  195.     if (max_read || max_write) {
  196.         ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp);

  197.     } else {

  198.         /*
  199.          * Winsock select() requires that at least one descriptor set must be
  200.          * be non-null, and any non-null descriptor set must contain at least
  201.          * one handle to a socket.  Otherwise select() returns WSAEINVAL.
  202.          */

  203.         ngx_msleep(timer);

  204.         ready = 0;
  205.     }

  206.     err = (ready == -1) ? ngx_socket_errno : 0;

  207.     if (flags & NGX_UPDATE_TIME) {
  208.         ngx_time_update();
  209.     }

  210.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  211.                    "select ready %d", ready);

  212.     if (err) {
  213.         ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed");

  214.         if (err == WSAENOTSOCK) {
  215.             ngx_select_repair_fd_sets(cycle);
  216.         }

  217.         return NGX_ERROR;
  218.     }

  219.     if (ready == 0) {
  220.         if (timer != NGX_TIMER_INFINITE) {
  221.             return NGX_OK;
  222.         }

  223.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  224.                       "select() returned no events without timeout");
  225.         return NGX_ERROR;
  226.     }

  227.     nready = 0;

  228.     for (i = 0; i < nevents; i++) {
  229.         ev = event_index[i];
  230.         c = ev->data;
  231.         found = 0;

  232.         if (ev->write) {
  233.             if (FD_ISSET(c->fd, &work_write_fd_set)) {
  234.                 found = 1;
  235.                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  236.                                "select write %d", c->fd);
  237.             }

  238.         } else {
  239.             if (FD_ISSET(c->fd, &work_read_fd_set)) {
  240.                 found = 1;
  241.                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  242.                                "select read %d", c->fd);
  243.             }
  244.         }

  245.         if (found) {
  246.             ev->ready = 1;

  247.             queue = ev->accept ? &ngx_posted_accept_events
  248.                                : &ngx_posted_events;

  249.             ngx_post_event(ev, queue);

  250.             nready++;
  251.         }
  252.     }

  253.     if (ready != nready) {
  254.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  255.                       "select ready != events: %d:%d", ready, nready);

  256.         ngx_select_repair_fd_sets(cycle);
  257.     }

  258.     return NGX_OK;
  259. }


  260. static void
  261. ngx_select_repair_fd_sets(ngx_cycle_t *cycle)
  262. {
  263.     int           n;
  264.     u_int         i;
  265.     socklen_t     len;
  266.     ngx_err_t     err;
  267.     ngx_socket_t  s;

  268.     for (i = 0; i < master_read_fd_set.fd_count; i++) {

  269.         s = master_read_fd_set.fd_array[i];
  270.         len = sizeof(int);

  271.         if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
  272.             err = ngx_socket_errno;

  273.             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
  274.                           "invalid descriptor #%d in read fd_set", s);

  275.             FD_CLR(s, &master_read_fd_set);
  276.         }
  277.     }

  278.     for (i = 0; i < master_write_fd_set.fd_count; i++) {

  279.         s = master_write_fd_set.fd_array[i];
  280.         len = sizeof(int);

  281.         if (getsockopt(s, SOL_SOCKET, SO_TYPE, (char *) &n, &len) == -1) {
  282.             err = ngx_socket_errno;

  283.             ngx_log_error(NGX_LOG_ALERT, cycle->log, err,
  284.                           "invalid descriptor #%d in write fd_set", s);

  285.             FD_CLR(s, &master_write_fd_set);
  286.         }
  287.     }
  288. }


  289. static char *
  290. ngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
  291. {
  292.     ngx_event_conf_t  *ecf;

  293.     ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);

  294.     if (ecf->use != ngx_select_module.ctx_index) {
  295.         return NGX_CONF_OK;
  296.     }

  297.     return NGX_CONF_OK;
  298. }