src/event/modules/ngx_poll_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_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
  9. static void ngx_poll_done(ngx_cycle_t *cycle);
  10. static ngx_int_t ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event,
  11.     ngx_uint_t flags);
  12. static ngx_int_t ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event,
  13.     ngx_uint_t flags);
  14. static ngx_int_t ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
  15.     ngx_uint_t flags);
  16. static char *ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf);


  17. static struct pollfd  *event_list;
  18. static ngx_uint_t      nevents;


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

  20. ngx_event_module_t  ngx_poll_module_ctx = {
  21.     &poll_name,
  22.     NULL,                                  /* create configuration */
  23.     ngx_poll_init_conf,                    /* init configuration */

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

  36. };

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



  51. static ngx_int_t
  52. ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
  53. {
  54.     struct pollfd   *list;

  55.     if (event_list == NULL) {
  56.         nevents = 0;
  57.     }

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

  67.         if (event_list) {
  68.             ngx_memcpy(list, event_list, sizeof(ngx_event_t *) * nevents);
  69.             ngx_free(event_list);
  70.         }

  71.         event_list = list;
  72.     }

  73.     ngx_io = ngx_os_io;

  74.     ngx_event_actions = ngx_poll_module_ctx.actions;

  75.     ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_FD_EVENT;

  76.     return NGX_OK;
  77. }


  78. static void
  79. ngx_poll_done(ngx_cycle_t *cycle)
  80. {
  81.     ngx_free(event_list);

  82.     event_list = NULL;
  83. }


  84. static ngx_int_t
  85. ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  86. {
  87.     ngx_event_t       *e;
  88.     ngx_connection_t  *c;

  89.     c = ev->data;

  90.     ev->active = 1;

  91.     if (ev->index != NGX_INVALID_INDEX) {
  92.         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
  93.                       "poll event fd:%d ev:%i is already set", c->fd, event);
  94.         return NGX_OK;
  95.     }

  96.     if (event == NGX_READ_EVENT) {
  97.         e = c->write;
  98. #if (NGX_READ_EVENT != POLLIN)
  99.         event = POLLIN;
  100. #endif

  101.     } else {
  102.         e = c->read;
  103. #if (NGX_WRITE_EVENT != POLLOUT)
  104.         event = POLLOUT;
  105. #endif
  106.     }

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

  109.     if (e == NULL || e->index == NGX_INVALID_INDEX) {
  110.         event_list[nevents].fd = c->fd;
  111.         event_list[nevents].events = (short) event;
  112.         event_list[nevents].revents = 0;

  113.         ev->index = nevents;
  114.         nevents++;

  115.     } else {
  116.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  117.                        "poll add index: %i", e->index);

  118.         event_list[e->index].events |= (short) event;
  119.         ev->index = e->index;
  120.     }

  121.     return NGX_OK;
  122. }


  123. static ngx_int_t
  124. ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  125. {
  126.     ngx_event_t       *e;
  127.     ngx_connection_t  *c;

  128.     c = ev->data;

  129.     ev->active = 0;

  130.     if (ev->index == NGX_INVALID_INDEX) {
  131.         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
  132.                       "poll event fd:%d ev:%i is already deleted",
  133.                       c->fd, event);
  134.         return NGX_OK;
  135.     }

  136.     if (event == NGX_READ_EVENT) {
  137.         e = c->write;
  138. #if (NGX_READ_EVENT != POLLIN)
  139.         event = POLLIN;
  140. #endif

  141.     } else {
  142.         e = c->read;
  143. #if (NGX_WRITE_EVENT != POLLOUT)
  144.         event = POLLOUT;
  145. #endif
  146.     }

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

  149.     if (e == NULL || e->index == NGX_INVALID_INDEX) {
  150.         nevents--;

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

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

  154.             event_list[ev->index] = event_list[nevents];

  155.             c = ngx_cycle->files[event_list[nevents].fd];

  156.             if (c->fd == -1) {
  157.                 ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
  158.                               "unexpected last event");

  159.             } else {
  160.                 if (c->read->index == nevents) {
  161.                     c->read->index = ev->index;
  162.                 }

  163.                 if (c->write->index == nevents) {
  164.                     c->write->index = ev->index;
  165.                 }
  166.             }
  167.         }

  168.     } else {
  169.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  170.                        "poll del index: %i", e->index);

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

  173.     ev->index = NGX_INVALID_INDEX;

  174.     return NGX_OK;
  175. }


  176. static ngx_int_t
  177. ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
  178. {
  179.     int                 ready, revents;
  180.     ngx_err_t           err;
  181.     ngx_uint_t          i, found, level;
  182.     ngx_event_t        *ev;
  183.     ngx_queue_t        *queue;
  184.     ngx_connection_t   *c;

  185.     /* NGX_TIMER_INFINITE == INFTIM */

  186. #if (NGX_DEBUG0)
  187.     if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
  188.         for (i = 0; i < nevents; i++) {
  189.             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  190.                            "poll: %ui: fd:%d ev:%04Xd",
  191.                            i, event_list[i].fd, event_list[i].events);
  192.         }
  193.     }
  194. #endif

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

  196.     ready = poll(event_list, (u_int) nevents, (int) timer);

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

  198.     if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
  199.         ngx_time_update();
  200.     }

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

  203.     if (err) {
  204.         if (err == NGX_EINTR) {

  205.             if (ngx_event_timer_alarm) {
  206.                 ngx_event_timer_alarm = 0;
  207.                 return NGX_OK;
  208.             }

  209.             level = NGX_LOG_INFO;

  210.         } else {
  211.             level = NGX_LOG_ALERT;
  212.         }

  213.         ngx_log_error(level, cycle->log, err, "poll() failed");
  214.         return NGX_ERROR;
  215.     }

  216.     if (ready == 0) {
  217.         if (timer != NGX_TIMER_INFINITE) {
  218.             return NGX_OK;
  219.         }

  220.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  221.                       "poll() returned no events without timeout");
  222.         return NGX_ERROR;
  223.     }

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

  225.         revents = event_list[i].revents;

  226. #if 1
  227.         ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  228.                        "poll: %ui: fd:%d ev:%04Xd rev:%04Xd",
  229.                        i, event_list[i].fd, event_list[i].events, revents);
  230. #else
  231.         if (revents) {
  232.             ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  233.                            "poll: %ui: fd:%d ev:%04Xd rev:%04Xd",
  234.                            i, event_list[i].fd, event_list[i].events, revents);
  235.         }
  236. #endif

  237.         if (revents & POLLNVAL) {
  238.             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  239.                           "poll() error fd:%d ev:%04Xd rev:%04Xd",
  240.                           event_list[i].fd, event_list[i].events, revents);
  241.         }

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

  247.         if (event_list[i].fd == -1) {
  248.             /*
  249.              * the disabled event, a workaround for our possible bug,
  250.              * see the comment below
  251.              */
  252.             continue;
  253.         }

  254.         c = ngx_cycle->files[event_list[i].fd];

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

  257.             /*
  258.              * it is certainly our fault and it should be investigated,
  259.              * in the meantime we disable this event to avoid a CPU spinning
  260.              */

  261.             if (i == nevents - 1) {
  262.                 nevents--;
  263.             } else {
  264.                 event_list[i].fd = -1;
  265.             }

  266.             continue;
  267.         }

  268.         if ((revents & (POLLERR|POLLHUP|POLLNVAL))
  269.              && (revents & (POLLIN|POLLOUT)) == 0)
  270.         {
  271.             /*
  272.              * if the error events were returned without POLLIN or POLLOUT,
  273.              * then add these flags to handle the events at least in one
  274.              * active handler
  275.              */

  276.             revents |= POLLIN|POLLOUT;
  277.         }

  278.         found = 0;

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

  281.             ev = c->read;
  282.             ev->ready = 1;

  283.             queue = ev->accept ? &ngx_posted_accept_events
  284.                                : &ngx_posted_events;

  285.             ngx_post_event(ev, queue);
  286.         }

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

  289.             ev = c->write;
  290.             ev->ready = 1;

  291.             ngx_post_event(ev, &ngx_posted_events);
  292.         }

  293.         if (found) {
  294.             ready--;
  295.             continue;
  296.         }
  297.     }

  298.     if (ready != 0) {
  299.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "poll ready != events");
  300.     }

  301.     return NGX_OK;
  302. }


  303. static char *
  304. ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf)
  305. {
  306.     ngx_event_conf_t  *ecf;

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

  308.     if (ecf->use != ngx_poll_module.ctx_index) {
  309.         return NGX_CONF_OK;
  310.     }

  311. #if (NGX_THREADS)

  312.     ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  313.                   "poll() is not supported in the threaded mode");
  314.     return NGX_CONF_ERROR;

  315. #else

  316.     return NGX_CONF_OK;

  317. #endif
  318. }