src/event/modules/ngx_win32_select_module.c - nginx source code

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 fd_set         work_except_fd_set;

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

  26. static ngx_event_t  **event_index;


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

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

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

  44. };

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


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

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

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

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

  81.         event_index = index;
  82.     }

  83.     ngx_io = ngx_os_io;

  84.     ngx_event_actions = ngx_select_module_ctx.actions;

  85.     ngx_event_flags = NGX_USE_LEVEL_EVENT;

  86.     max_read = 0;
  87.     max_write = 0;

  88.     return NGX_OK;
  89. }


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

  94.     event_index = NULL;
  95. }


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

  100.     c = ev->data;

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

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

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

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

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

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

  131.     ev->active = 1;

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

  135.     return NGX_OK;
  136. }


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

  142.     c = ev->data;

  143.     ev->active = 0;

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

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

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

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

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

  161.     ev->index = NGX_INVALID_INDEX;

  162.     return NGX_OK;
  163. }


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

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

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

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

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

  194.     work_read_fd_set = master_read_fd_set;
  195.     work_write_fd_set = master_write_fd_set;
  196.     work_except_fd_set = master_write_fd_set;

  197.     if (max_read || max_write) {
  198.         ready = select(0, &work_read_fd_set, &work_write_fd_set,
  199.                        &work_except_fd_set, tp);

  200.     } else {

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

  206.         ngx_msleep(timer);

  207.         ready = 0;
  208.     }

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

  210.     if (flags & NGX_UPDATE_TIME) {
  211.         ngx_time_update();
  212.     }

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

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

  217.         if (err == WSAENOTSOCK) {
  218.             ngx_select_repair_fd_sets(cycle);
  219.         }

  220.         return NGX_ERROR;
  221.     }

  222.     if (ready == 0) {
  223.         if (timer != NGX_TIMER_INFINITE) {
  224.             return NGX_OK;
  225.         }

  226.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  227.                       "select() returned no events without timeout");
  228.         return NGX_ERROR;
  229.     }

  230.     nready = 0;

  231.     for (i = 0; i < nevents; i++) {
  232.         ev = event_index[i];
  233.         c = ev->data;
  234.         found = 0;

  235.         if (ev->write) {
  236.             if (FD_ISSET(c->fd, &work_write_fd_set)) {
  237.                 found++;
  238.                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  239.                                "select write %d", c->fd);
  240.             }

  241.             if (FD_ISSET(c->fd, &work_except_fd_set)) {
  242.                 found++;
  243.                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  244.                                "select except %d", c->fd);
  245.             }

  246.         } else {
  247.             if (FD_ISSET(c->fd, &work_read_fd_set)) {
  248.                 found++;
  249.                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  250.                                "select read %d", c->fd);
  251.             }
  252.         }

  253.         if (found) {
  254.             ev->ready = 1;
  255.             ev->available = -1;

  256.             queue = ev->accept ? &ngx_posted_accept_events
  257.                                : &ngx_posted_events;

  258.             ngx_post_event(ev, queue);

  259.             nready += found;
  260.         }
  261.     }

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

  265.         ngx_select_repair_fd_sets(cycle);
  266.     }

  267.     return NGX_OK;
  268. }


  269. static void
  270. ngx_select_repair_fd_sets(ngx_cycle_t *cycle)
  271. {
  272.     int           n;
  273.     u_int         i;
  274.     socklen_t     len;
  275.     ngx_err_t     err;
  276.     ngx_socket_t  s;

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

  278.         s = master_read_fd_set.fd_array[i];
  279.         len = sizeof(int);

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

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

  284.             FD_CLR(s, &master_read_fd_set);
  285.         }
  286.     }

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

  288.         s = master_write_fd_set.fd_array[i];
  289.         len = sizeof(int);

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

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

  294.             FD_CLR(s, &master_write_fd_set);
  295.         }
  296.     }
  297. }


  298. static char *
  299. ngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
  300. {
  301.     ngx_event_conf_t  *ecf;

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

  303.     if (ecf->use != ngx_select_module.ctx_index) {
  304.         return NGX_CONF_OK;
  305.     }

  306.     return NGX_CONF_OK;
  307. }