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

Global variables defined

Functions defined

Source code


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


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


  9. static ngx_int_t ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
  10. static void ngx_poll_done(ngx_cycle_t *cycle);
  11. static ngx_int_t ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event,
  12.     ngx_uint_t flags);
  13. static ngx_int_t ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event,
  14.     ngx_uint_t flags);
  15. static ngx_int_t ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
  16.     ngx_uint_t flags);
  17. static char *ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf);


  18. static struct pollfd      *event_list;
  19. static ngx_connection_t  **event_index;
  20. static ngx_uint_t          nevents;


  21. static ngx_str_t           poll_name = ngx_string("poll");

  22. static ngx_event_module_t  ngx_poll_module_ctx = {
  23.     &poll_name,
  24.     NULL,                                  /* create configuration */
  25.     ngx_poll_init_conf,                    /* init configuration */

  26.     {
  27.         ngx_poll_add_event,                /* add an event */
  28.         ngx_poll_del_event,                /* delete an event */
  29.         ngx_poll_add_event,                /* enable an event */
  30.         ngx_poll_del_event,                /* disable an event */
  31.         NULL,                              /* add an connection */
  32.         NULL,                              /* delete an connection */
  33.         NULL,                              /* trigger a notify */
  34.         ngx_poll_process_events,           /* process the events */
  35.         ngx_poll_init,                     /* init the events */
  36.         ngx_poll_done                      /* done the events */
  37.     }

  38. };

  39. ngx_module_t  ngx_poll_module = {
  40.     NGX_MODULE_V1,
  41.     &ngx_poll_module_ctx,                  /* module context */
  42.     NULL,                                  /* module directives */
  43.     NGX_EVENT_MODULE,                      /* module type */
  44.     NULL,                                  /* init master */
  45.     NULL,                                  /* init module */
  46.     NULL,                                  /* init process */
  47.     NULL,                                  /* init thread */
  48.     NULL,                                  /* exit thread */
  49.     NULL,                                  /* exit process */
  50.     NULL,                                  /* exit master */
  51.     NGX_MODULE_V1_PADDING
  52. };



  53. static ngx_int_t
  54. ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
  55. {
  56.     struct pollfd      *list;
  57.     ngx_connection_t  **index;

  58.     if (event_list == NULL) {
  59.         nevents = 0;
  60.     }

  61.     if (ngx_process >= NGX_PROCESS_WORKER
  62.         || cycle->old_cycle == NULL
  63.         || cycle->old_cycle->connection_n < cycle->connection_n)
  64.     {
  65.         list = ngx_alloc(sizeof(struct pollfd) * cycle->connection_n,
  66.                          cycle->log);
  67.         if (list == NULL) {
  68.             return NGX_ERROR;
  69.         }

  70.         if (event_list) {
  71.             ngx_memcpy(list, event_list, sizeof(struct pollfd) * nevents);
  72.             ngx_free(event_list);
  73.         }

  74.         event_list = list;

  75.         index = ngx_alloc(sizeof(ngx_connection_t *) * cycle->connection_n,
  76.                           cycle->log);
  77.         if (index == NULL) {
  78.             return NGX_ERROR;
  79.         }

  80.         if (event_index) {
  81.             ngx_memcpy(index, event_index,
  82.                        sizeof(ngx_connection_t *) * nevents);
  83.             ngx_free(event_index);
  84.         }

  85.         event_index = index;
  86.     }

  87.     ngx_io = ngx_os_io;

  88.     ngx_event_actions = ngx_poll_module_ctx.actions;

  89.     ngx_event_flags = NGX_USE_LEVEL_EVENT;

  90.     return NGX_OK;
  91. }


  92. static void
  93. ngx_poll_done(ngx_cycle_t *cycle)
  94. {
  95.     ngx_free(event_list);
  96.     ngx_free(event_index);

  97.     event_list = NULL;
  98.     event_index = NULL;
  99. }


  100. static ngx_int_t
  101. ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  102. {
  103.     ngx_event_t       *e;
  104.     ngx_connection_t  *c;

  105.     c = ev->data;

  106.     ev->active = 1;

  107.     if (ev->index != NGX_INVALID_INDEX) {
  108.         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
  109.                       "poll event fd:%d ev:%i is already set", c->fd, event);
  110.         return NGX_OK;
  111.     }

  112.     if (event == NGX_READ_EVENT) {
  113.         e = c->write;
  114. #if (NGX_READ_EVENT != POLLIN)
  115.         event = POLLIN;
  116. #endif

  117.     } else {
  118.         e = c->read;
  119. #if (NGX_WRITE_EVENT != POLLOUT)
  120.         event = POLLOUT;
  121. #endif
  122.     }

  123.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  124.                    "poll add event: fd:%d ev:%i", c->fd, event);

  125.     if (e == NULL || e->index == NGX_INVALID_INDEX) {

  126.         event_list[nevents].fd = c->fd;
  127.         event_list[nevents].events = (short) event;
  128.         event_list[nevents].revents = 0;

  129.         event_index[nevents] = c;

  130.         ev->index = nevents;
  131.         nevents++;

  132.     } else {
  133.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  134.                        "poll add index: %i", e->index);

  135.         event_list[e->index].events |= (short) event;
  136.         ev->index = e->index;
  137.     }

  138.     return NGX_OK;
  139. }


  140. static ngx_int_t
  141. ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  142. {
  143.     ngx_event_t       *e;
  144.     ngx_connection_t  *c;

  145.     c = ev->data;

  146.     ev->active = 0;

  147.     if (ev->index == NGX_INVALID_INDEX) {
  148.         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
  149.                       "poll event fd:%d ev:%i is already deleted",
  150.                       c->fd, event);
  151.         return NGX_OK;
  152.     }

  153.     if (event == NGX_READ_EVENT) {
  154.         e = c->write;
  155. #if (NGX_READ_EVENT != POLLIN)
  156.         event = POLLIN;
  157. #endif

  158.     } else {
  159.         e = c->read;
  160. #if (NGX_WRITE_EVENT != POLLOUT)
  161.         event = POLLOUT;
  162. #endif
  163.     }

  164.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  165.                    "poll del event: fd:%d ev:%i", c->fd, event);

  166.     if (e == NULL || e->index == NGX_INVALID_INDEX) {
  167.         nevents--;

  168.         if (ev->index < nevents) {

  169.             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  170.                            "index: copy event %ui to %i", nevents, ev->index);

  171.             event_list[ev->index] = event_list[nevents];
  172.             event_index[ev->index] = event_index[nevents];

  173.             c = event_index[ev->index];

  174.             if (c->fd == (ngx_socket_t) -1) {
  175.                 ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
  176.                               "unexpected last event");

  177.             } else {
  178.                 if (c->read->index == nevents) {
  179.                     c->read->index = ev->index;
  180.                 }

  181.                 if (c->write->index == nevents) {
  182.                     c->write->index = ev->index;
  183.                 }
  184.             }
  185.         }

  186.     } else {
  187.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  188.                        "poll del index: %i", e->index);

  189.         event_list[e->index].events &= (short) ~event;
  190.     }

  191.     ev->index = NGX_INVALID_INDEX;

  192.     return NGX_OK;
  193. }


  194. static ngx_int_t
  195. ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
  196. {
  197.     int                 ready, revents;
  198.     ngx_err_t           err;
  199.     ngx_uint_t          i, found;
  200.     ngx_event_t        *ev;
  201.     ngx_queue_t        *queue;
  202.     ngx_connection_t   *c;

  203.     /* NGX_TIMER_INFINITE == INFTIM */

  204. #if (NGX_DEBUG0)
  205.     if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
  206.         for (i = 0; i < nevents; i++) {
  207.             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  208.                            "poll: %ui: fd:%d ev:%04Xd",
  209.                            i, event_list[i].fd, event_list[i].events);
  210.         }
  211.     }
  212. #endif

  213.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "poll timer: %M", timer);

  214.     ready = WSAPoll(event_list, (u_int) nevents, (int) timer);

  215.     err = (ready == -1) ? ngx_errno : 0;

  216.     if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
  217.         ngx_time_update();
  218.     }

  219.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  220.                    "poll ready %d of %ui", ready, nevents);

  221.     if (err) {
  222.         ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "WSAPoll() failed");
  223.         return NGX_ERROR;
  224.     }

  225.     if (ready == 0) {
  226.         if (timer != NGX_TIMER_INFINITE) {
  227.             return NGX_OK;
  228.         }

  229.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  230.                       "WSAPoll() returned no events without timeout");
  231.         return NGX_ERROR;
  232.     }

  233.     for (i = 0; i < nevents && ready; i++) {

  234.         revents = event_list[i].revents;

  235. #if 1
  236.         ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  237.                        "poll: %ui: fd:%d ev:%04Xd rev:%04Xd",
  238.                        i, event_list[i].fd, event_list[i].events, revents);
  239. #else
  240.         if (revents) {
  241.             ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  242.                            "poll: %ui: fd:%d ev:%04Xd rev:%04Xd",
  243.                            i, event_list[i].fd, event_list[i].events, revents);
  244.         }
  245. #endif

  246.         if (revents & POLLNVAL) {
  247.             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  248.                           "poll() error fd:%d ev:%04Xd rev:%04Xd",
  249.                           event_list[i].fd, event_list[i].events, revents);
  250.         }

  251.         if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
  252.             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  253.                           "strange poll() events fd:%d ev:%04Xd rev:%04Xd",
  254.                           event_list[i].fd, event_list[i].events, revents);
  255.         }

  256.         if (event_list[i].fd == (ngx_socket_t) -1) {
  257.             /*
  258.              * the disabled event, a workaround for our possible bug,
  259.              * see the comment below
  260.              */
  261.             continue;
  262.         }

  263.         c = event_index[i];

  264.         if (c->fd == (ngx_socket_t) -1) {
  265.             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event");

  266.             /*
  267.              * it is certainly our fault and it should be investigated,
  268.              * in the meantime we disable this event to avoid a CPU spinning
  269.              */

  270.             if (i == nevents - 1) {
  271.                 nevents--;
  272.             } else {
  273.                 event_list[i].fd = (ngx_socket_t) -1;
  274.             }

  275.             continue;
  276.         }

  277.         if (revents & (POLLERR|POLLHUP|POLLNVAL)) {

  278.             /*
  279.              * if the error events were returned, add POLLIN and POLLOUT
  280.              * to handle the events at least in one active handler
  281.              */

  282.             revents |= POLLIN|POLLOUT;
  283.         }

  284.         found = 0;

  285.         if ((revents & POLLIN) && c->read->active) {
  286.             found = 1;

  287.             ev = c->read;
  288.             ev->ready = 1;
  289.             ev->available = -1;

  290.             queue = ev->accept ? &ngx_posted_accept_events
  291.                                : &ngx_posted_events;

  292.             ngx_post_event(ev, queue);
  293.         }

  294.         if ((revents & POLLOUT) && c->write->active) {
  295.             found = 1;

  296.             ev = c->write;
  297.             ev->ready = 1;

  298.             ngx_post_event(ev, &ngx_posted_events);
  299.         }

  300.         if (found) {
  301.             ready--;
  302.             continue;
  303.         }
  304.     }

  305.     if (ready != 0) {
  306.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "poll ready != events");
  307.     }

  308.     return NGX_OK;
  309. }


  310. static char *
  311. ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf)
  312. {
  313.     ngx_event_conf_t  *ecf;

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

  315.     if (ecf->use != ngx_poll_module.ctx_index) {
  316.         return NGX_CONF_OK;
  317.     }

  318. #if (NGX_LOAD_WSAPOLL)

  319.     if (!ngx_have_wsapoll) {
  320.         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  321.                       "poll is not available on this platform");
  322.         return NGX_CONF_ERROR;
  323.     }

  324. #endif

  325.     return NGX_CONF_OK;
  326. }