src/event/ngx_event.c - nginx-1.7.10

Global variables defined

Functions defined

Macros 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. #define DEFAULT_CONNECTIONS  512


  9. extern ngx_module_t ngx_kqueue_module;
  10. extern ngx_module_t ngx_eventport_module;
  11. extern ngx_module_t ngx_devpoll_module;
  12. extern ngx_module_t ngx_epoll_module;
  13. extern ngx_module_t ngx_rtsig_module;
  14. extern ngx_module_t ngx_select_module;


  15. static char *ngx_event_init_conf(ngx_cycle_t *cycle, void *conf);
  16. static ngx_int_t ngx_event_module_init(ngx_cycle_t *cycle);
  17. static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle);
  18. static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

  19. static char *ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd,
  20.     void *conf);
  21. static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  22. static char *ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd,
  23.     void *conf);

  24. static void *ngx_event_core_create_conf(ngx_cycle_t *cycle);
  25. static char *ngx_event_core_init_conf(ngx_cycle_t *cycle, void *conf);


  26. static ngx_uint_t     ngx_timer_resolution;
  27. sig_atomic_t          ngx_event_timer_alarm;

  28. static ngx_uint_t     ngx_event_max_module;

  29. ngx_uint_t            ngx_event_flags;
  30. ngx_event_actions_t   ngx_event_actions;


  31. static ngx_atomic_t   connection_counter = 1;
  32. ngx_atomic_t         *ngx_connection_counter = &connection_counter;


  33. ngx_atomic_t         *ngx_accept_mutex_ptr;
  34. ngx_shmtx_t           ngx_accept_mutex;
  35. ngx_uint_t            ngx_use_accept_mutex;
  36. ngx_uint_t            ngx_accept_events;
  37. ngx_uint_t            ngx_accept_mutex_held;
  38. ngx_msec_t            ngx_accept_mutex_delay;
  39. ngx_int_t             ngx_accept_disabled;


  40. #if (NGX_STAT_STUB)

  41. ngx_atomic_t   ngx_stat_accepted0;
  42. ngx_atomic_t  *ngx_stat_accepted = &ngx_stat_accepted0;
  43. ngx_atomic_t   ngx_stat_handled0;
  44. ngx_atomic_t  *ngx_stat_handled = &ngx_stat_handled0;
  45. ngx_atomic_t   ngx_stat_requests0;
  46. ngx_atomic_t  *ngx_stat_requests = &ngx_stat_requests0;
  47. ngx_atomic_t   ngx_stat_active0;
  48. ngx_atomic_t  *ngx_stat_active = &ngx_stat_active0;
  49. ngx_atomic_t   ngx_stat_reading0;
  50. ngx_atomic_t  *ngx_stat_reading = &ngx_stat_reading0;
  51. ngx_atomic_t   ngx_stat_writing0;
  52. ngx_atomic_t  *ngx_stat_writing = &ngx_stat_writing0;
  53. ngx_atomic_t   ngx_stat_waiting0;
  54. ngx_atomic_t  *ngx_stat_waiting = &ngx_stat_waiting0;

  55. #endif



  56. static ngx_command_t  ngx_events_commands[] = {

  57.     { ngx_string("events"),
  58.       NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
  59.       ngx_events_block,
  60.       0,
  61.       0,
  62.       NULL },

  63.       ngx_null_command
  64. };


  65. static ngx_core_module_t  ngx_events_module_ctx = {
  66.     ngx_string("events"),
  67.     NULL,
  68.     ngx_event_init_conf
  69. };


  70. ngx_module_t  ngx_events_module = {
  71.     NGX_MODULE_V1,
  72.     &ngx_events_module_ctx,                /* module context */
  73.     ngx_events_commands,                   /* module directives */
  74.     NGX_CORE_MODULE,                       /* module type */
  75.     NULL,                                  /* init master */
  76.     NULL,                                  /* init module */
  77.     NULL,                                  /* init process */
  78.     NULL,                                  /* init thread */
  79.     NULL,                                  /* exit thread */
  80.     NULL,                                  /* exit process */
  81.     NULL,                                  /* exit master */
  82.     NGX_MODULE_V1_PADDING
  83. };


  84. static ngx_str_t  event_core_name = ngx_string("event_core");


  85. static ngx_command_t  ngx_event_core_commands[] = {

  86.     { ngx_string("worker_connections"),
  87.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  88.       ngx_event_connections,
  89.       0,
  90.       0,
  91.       NULL },

  92.     { ngx_string("connections"),
  93.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  94.       ngx_event_connections,
  95.       0,
  96.       0,
  97.       NULL },

  98.     { ngx_string("use"),
  99.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  100.       ngx_event_use,
  101.       0,
  102.       0,
  103.       NULL },

  104.     { ngx_string("multi_accept"),
  105.       NGX_EVENT_CONF|NGX_CONF_FLAG,
  106.       ngx_conf_set_flag_slot,
  107.       0,
  108.       offsetof(ngx_event_conf_t, multi_accept),
  109.       NULL },

  110.     { ngx_string("accept_mutex"),
  111.       NGX_EVENT_CONF|NGX_CONF_FLAG,
  112.       ngx_conf_set_flag_slot,
  113.       0,
  114.       offsetof(ngx_event_conf_t, accept_mutex),
  115.       NULL },

  116.     { ngx_string("accept_mutex_delay"),
  117.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  118.       ngx_conf_set_msec_slot,
  119.       0,
  120.       offsetof(ngx_event_conf_t, accept_mutex_delay),
  121.       NULL },

  122.     { ngx_string("debug_connection"),
  123.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  124.       ngx_event_debug_connection,
  125.       0,
  126.       0,
  127.       NULL },

  128.       ngx_null_command
  129. };


  130. ngx_event_module_t  ngx_event_core_module_ctx = {
  131.     &event_core_name,
  132.     ngx_event_core_create_conf,            /* create configuration */
  133.     ngx_event_core_init_conf,              /* init configuration */

  134.     { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
  135. };


  136. ngx_module_t  ngx_event_core_module = {
  137.     NGX_MODULE_V1,
  138.     &ngx_event_core_module_ctx,            /* module context */
  139.     ngx_event_core_commands,               /* module directives */
  140.     NGX_EVENT_MODULE,                      /* module type */
  141.     NULL,                                  /* init master */
  142.     ngx_event_module_init,                 /* init module */
  143.     ngx_event_process_init,                /* init process */
  144.     NULL,                                  /* init thread */
  145.     NULL,                                  /* exit thread */
  146.     NULL,                                  /* exit process */
  147.     NULL,                                  /* exit master */
  148.     NGX_MODULE_V1_PADDING
  149. };


  150. void
  151. ngx_process_events_and_timers(ngx_cycle_t *cycle)
  152. {
  153.     ngx_uint_t  flags;
  154.     ngx_msec_t  timer, delta;

  155.     if (ngx_timer_resolution) {
  156.         timer = NGX_TIMER_INFINITE;
  157.         flags = 0;

  158.     } else {
  159.         timer = ngx_event_find_timer();
  160.         flags = NGX_UPDATE_TIME;

  161. #if (NGX_THREADS)

  162.         if (timer == NGX_TIMER_INFINITE || timer > 500) {
  163.             timer = 500;
  164.         }

  165. #endif
  166.     }

  167.     if (ngx_use_accept_mutex) {
  168.         if (ngx_accept_disabled > 0) {
  169.             ngx_accept_disabled--;

  170.         } else {
  171.             if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
  172.                 return;
  173.             }

  174.             if (ngx_accept_mutex_held) {
  175.                 flags |= NGX_POST_EVENTS;

  176.             } else {
  177.                 if (timer == NGX_TIMER_INFINITE
  178.                     || timer > ngx_accept_mutex_delay)
  179.                 {
  180.                     timer = ngx_accept_mutex_delay;
  181.                 }
  182.             }
  183.         }
  184.     }

  185.     delta = ngx_current_msec;

  186.     (void) ngx_process_events(cycle, timer, flags);

  187.     delta = ngx_current_msec - delta;

  188.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  189.                    "timer delta: %M", delta);

  190.     ngx_event_process_posted(cycle, &ngx_posted_accept_events);

  191.     if (ngx_accept_mutex_held) {
  192.         ngx_shmtx_unlock(&ngx_accept_mutex);
  193.     }

  194.     if (delta) {
  195.         ngx_event_expire_timers();
  196.     }

  197.     ngx_event_process_posted(cycle, &ngx_posted_events);
  198. }


  199. ngx_int_t
  200. ngx_handle_read_event(ngx_event_t *rev, ngx_uint_t flags)
  201. {
  202.     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {

  203.         /* kqueue, epoll */

  204.         if (!rev->active && !rev->ready) {
  205.             if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT)
  206.                 == NGX_ERROR)
  207.             {
  208.                 return NGX_ERROR;
  209.             }
  210.         }

  211.         return NGX_OK;

  212.     } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {

  213.         /* select, poll, /dev/poll */

  214.         if (!rev->active && !rev->ready) {
  215.             if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
  216.                 == NGX_ERROR)
  217.             {
  218.                 return NGX_ERROR;
  219.             }

  220.             return NGX_OK;
  221.         }

  222.         if (rev->active && (rev->ready || (flags & NGX_CLOSE_EVENT))) {
  223.             if (ngx_del_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT | flags)
  224.                 == NGX_ERROR)
  225.             {
  226.                 return NGX_ERROR;
  227.             }

  228.             return NGX_OK;
  229.         }

  230.     } else if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {

  231.         /* event ports */

  232.         if (!rev->active && !rev->ready) {
  233.             if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  234.                 return NGX_ERROR;
  235.             }

  236.             return NGX_OK;
  237.         }

  238.         if (rev->oneshot && !rev->ready) {
  239.             if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  240.                 return NGX_ERROR;
  241.             }

  242.             return NGX_OK;
  243.         }
  244.     }

  245.     /* aio, iocp, rtsig */

  246.     return NGX_OK;
  247. }


  248. ngx_int_t
  249. ngx_handle_write_event(ngx_event_t *wev, size_t lowat)
  250. {
  251.     ngx_connection_t  *c;

  252.     if (lowat) {
  253.         c = wev->data;

  254.         if (ngx_send_lowat(c, lowat) == NGX_ERROR) {
  255.             return NGX_ERROR;
  256.         }
  257.     }

  258.     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {

  259.         /* kqueue, epoll */

  260.         if (!wev->active && !wev->ready) {
  261.             if (ngx_add_event(wev, NGX_WRITE_EVENT,
  262.                               NGX_CLEAR_EVENT | (lowat ? NGX_LOWAT_EVENT : 0))
  263.                 == NGX_ERROR)
  264.             {
  265.                 return NGX_ERROR;
  266.             }
  267.         }

  268.         return NGX_OK;

  269.     } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {

  270.         /* select, poll, /dev/poll */

  271.         if (!wev->active && !wev->ready) {
  272.             if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT)
  273.                 == NGX_ERROR)
  274.             {
  275.                 return NGX_ERROR;
  276.             }

  277.             return NGX_OK;
  278.         }

  279.         if (wev->active && wev->ready) {
  280.             if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT)
  281.                 == NGX_ERROR)
  282.             {
  283.                 return NGX_ERROR;
  284.             }

  285.             return NGX_OK;
  286.         }

  287.     } else if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {

  288.         /* event ports */

  289.         if (!wev->active && !wev->ready) {
  290.             if (ngx_add_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
  291.                 return NGX_ERROR;
  292.             }

  293.             return NGX_OK;
  294.         }

  295.         if (wev->oneshot && wev->ready) {
  296.             if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
  297.                 return NGX_ERROR;
  298.             }

  299.             return NGX_OK;
  300.         }
  301.     }

  302.     /* aio, iocp, rtsig */

  303.     return NGX_OK;
  304. }


  305. static char *
  306. ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
  307. {
  308.     if (ngx_get_conf(cycle->conf_ctx, ngx_events_module) == NULL) {
  309.         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  310.                       "no \"events\" section in configuration");
  311.         return NGX_CONF_ERROR;
  312.     }

  313.     return NGX_CONF_OK;
  314. }


  315. static ngx_int_t
  316. ngx_event_module_init(ngx_cycle_t *cycle)
  317. {
  318.     void              ***cf;
  319.     u_char              *shared;
  320.     size_t               size, cl;
  321.     ngx_shm_t            shm;
  322.     ngx_time_t          *tp;
  323.     ngx_core_conf_t     *ccf;
  324.     ngx_event_conf_t    *ecf;

  325.     cf = ngx_get_conf(cycle->conf_ctx, ngx_events_module);
  326.     ecf = (*cf)[ngx_event_core_module.ctx_index];

  327.     if (!ngx_test_config && ngx_process <= NGX_PROCESS_MASTER) {
  328.         ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
  329.                       "using the \"%s\" event method", ecf->name);
  330.     }

  331.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

  332.     ngx_timer_resolution = ccf->timer_resolution;

  333. #if !(NGX_WIN32)
  334.     {
  335.     ngx_int_t      limit;
  336.     struct rlimit  rlmt;

  337.     if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
  338.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  339.                       "getrlimit(RLIMIT_NOFILE) failed, ignored");

  340.     } else {
  341.         if (ecf->connections > (ngx_uint_t) rlmt.rlim_cur
  342.             && (ccf->rlimit_nofile == NGX_CONF_UNSET
  343.                 || ecf->connections > (ngx_uint_t) ccf->rlimit_nofile))
  344.         {
  345.             limit = (ccf->rlimit_nofile == NGX_CONF_UNSET) ?
  346.                          (ngx_int_t) rlmt.rlim_cur : ccf->rlimit_nofile;

  347.             ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
  348.                           "%ui worker_connections exceed "
  349.                           "open file resource limit: %i",
  350.                           ecf->connections, limit);
  351.         }
  352.     }
  353.     }
  354. #endif /* !(NGX_WIN32) */


  355.     if (ccf->master == 0) {
  356.         return NGX_OK;
  357.     }

  358.     if (ngx_accept_mutex_ptr) {
  359.         return NGX_OK;
  360.     }


  361.     /* cl should be equal to or greater than cache line size */

  362.     cl = 128;

  363.     size = cl            /* ngx_accept_mutex */
  364.            + cl          /* ngx_connection_counter */
  365.            + cl;         /* ngx_temp_number */

  366. #if (NGX_STAT_STUB)

  367.     size += cl           /* ngx_stat_accepted */
  368.            + cl          /* ngx_stat_handled */
  369.            + cl          /* ngx_stat_requests */
  370.            + cl          /* ngx_stat_active */
  371.            + cl          /* ngx_stat_reading */
  372.            + cl          /* ngx_stat_writing */
  373.            + cl;         /* ngx_stat_waiting */

  374. #endif

  375.     shm.size = size;
  376.     shm.name.len = sizeof("nginx_shared_zone");
  377.     shm.name.data = (u_char *) "nginx_shared_zone";
  378.     shm.log = cycle->log;

  379.     if (ngx_shm_alloc(&shm) != NGX_OK) {
  380.         return NGX_ERROR;
  381.     }

  382.     shared = shm.addr;

  383.     ngx_accept_mutex_ptr = (ngx_atomic_t *) shared;
  384.     ngx_accept_mutex.spin = (ngx_uint_t) -1;

  385.     if (ngx_shmtx_create(&ngx_accept_mutex, (ngx_shmtx_sh_t *) shared,
  386.                          cycle->lock_file.data)
  387.         != NGX_OK)
  388.     {
  389.         return NGX_ERROR;
  390.     }

  391.     ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl);

  392.     (void) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1);

  393.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  394.                    "counter: %p, %d",
  395.                    ngx_connection_counter, *ngx_connection_counter);

  396.     ngx_temp_number = (ngx_atomic_t *) (shared + 2 * cl);

  397.     tp = ngx_timeofday();

  398.     ngx_random_number = (tp->msec << 16) + ngx_pid;

  399. #if (NGX_STAT_STUB)

  400.     ngx_stat_accepted = (ngx_atomic_t *) (shared + 3 * cl);
  401.     ngx_stat_handled = (ngx_atomic_t *) (shared + 4 * cl);
  402.     ngx_stat_requests = (ngx_atomic_t *) (shared + 5 * cl);
  403.     ngx_stat_active = (ngx_atomic_t *) (shared + 6 * cl);
  404.     ngx_stat_reading = (ngx_atomic_t *) (shared + 7 * cl);
  405.     ngx_stat_writing = (ngx_atomic_t *) (shared + 8 * cl);
  406.     ngx_stat_waiting = (ngx_atomic_t *) (shared + 9 * cl);

  407. #endif

  408.     return NGX_OK;
  409. }


  410. #if !(NGX_WIN32)

  411. static void
  412. ngx_timer_signal_handler(int signo)
  413. {
  414.     ngx_event_timer_alarm = 1;

  415. #if 1
  416.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, "timer signal");
  417. #endif
  418. }

  419. #endif


  420. static ngx_int_t
  421. ngx_event_process_init(ngx_cycle_t *cycle)
  422. {
  423.     ngx_uint_t           m, i;
  424.     ngx_event_t         *rev, *wev;
  425.     ngx_listening_t     *ls;
  426.     ngx_connection_t    *c, *next, *old;
  427.     ngx_core_conf_t     *ccf;
  428.     ngx_event_conf_t    *ecf;
  429.     ngx_event_module_t  *module;

  430.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
  431.     ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);

  432.     if (ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex) {
  433.         ngx_use_accept_mutex = 1;
  434.         ngx_accept_mutex_held = 0;
  435.         ngx_accept_mutex_delay = ecf->accept_mutex_delay;

  436.     } else {
  437.         ngx_use_accept_mutex = 0;
  438.     }

  439. #if (NGX_WIN32)

  440.     /*
  441.      * disable accept mutex on win32 as it may cause deadlock if
  442.      * grabbed by a process which can't accept connections
  443.      */

  444.     ngx_use_accept_mutex = 0;

  445. #endif

  446.     ngx_queue_init(&ngx_posted_accept_events);
  447.     ngx_queue_init(&ngx_posted_events);

  448.     if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
  449.         return NGX_ERROR;
  450.     }

  451.     for (m = 0; ngx_modules[m]; m++) {
  452.         if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
  453.             continue;
  454.         }

  455.         if (ngx_modules[m]->ctx_index != ecf->use) {
  456.             continue;
  457.         }

  458.         module = ngx_modules[m]->ctx;

  459.         if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
  460.             /* fatal */
  461.             exit(2);
  462.         }

  463.         break;
  464.     }

  465. #if !(NGX_WIN32)

  466.     if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) {
  467.         struct sigaction  sa;
  468.         struct itimerval  itv;

  469.         ngx_memzero(&sa, sizeof(struct sigaction));
  470.         sa.sa_handler = ngx_timer_signal_handler;
  471.         sigemptyset(&sa.sa_mask);

  472.         if (sigaction(SIGALRM, &sa, NULL) == -1) {
  473.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  474.                           "sigaction(SIGALRM) failed");
  475.             return NGX_ERROR;
  476.         }

  477.         itv.it_interval.tv_sec = ngx_timer_resolution / 1000;
  478.         itv.it_interval.tv_usec = (ngx_timer_resolution % 1000) * 1000;
  479.         itv.it_value.tv_sec = ngx_timer_resolution / 1000;
  480.         itv.it_value.tv_usec = (ngx_timer_resolution % 1000 ) * 1000;

  481.         if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
  482.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  483.                           "setitimer() failed");
  484.         }
  485.     }

  486.     if (ngx_event_flags & NGX_USE_FD_EVENT) {
  487.         struct rlimit  rlmt;

  488.         if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
  489.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  490.                           "getrlimit(RLIMIT_NOFILE) failed");
  491.             return NGX_ERROR;
  492.         }

  493.         cycle->files_n = (ngx_uint_t) rlmt.rlim_cur;

  494.         cycle->files = ngx_calloc(sizeof(ngx_connection_t *) * cycle->files_n,
  495.                                   cycle->log);
  496.         if (cycle->files == NULL) {
  497.             return NGX_ERROR;
  498.         }
  499.     }

  500. #endif

  501.     cycle->connections =
  502.         ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);
  503.     if (cycle->connections == NULL) {
  504.         return NGX_ERROR;
  505.     }

  506.     c = cycle->connections;

  507.     cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
  508.                                    cycle->log);
  509.     if (cycle->read_events == NULL) {
  510.         return NGX_ERROR;
  511.     }

  512.     rev = cycle->read_events;
  513.     for (i = 0; i < cycle->connection_n; i++) {
  514.         rev[i].closed = 1;
  515.         rev[i].instance = 1;
  516.     }

  517.     cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
  518.                                     cycle->log);
  519.     if (cycle->write_events == NULL) {
  520.         return NGX_ERROR;
  521.     }

  522.     wev = cycle->write_events;
  523.     for (i = 0; i < cycle->connection_n; i++) {
  524.         wev[i].closed = 1;
  525.     }

  526.     i = cycle->connection_n;
  527.     next = NULL;

  528.     do {
  529.         i--;

  530.         c[i].data = next;
  531.         c[i].read = &cycle->read_events[i];
  532.         c[i].write = &cycle->write_events[i];
  533.         c[i].fd = (ngx_socket_t) -1;

  534.         next = &c[i];

  535. #if (NGX_THREADS)
  536.         c[i].lock = 0;
  537. #endif
  538.     } while (i);

  539.     cycle->free_connections = next;
  540.     cycle->free_connection_n = cycle->connection_n;

  541.     /* for each listening socket */

  542.     ls = cycle->listening.elts;
  543.     for (i = 0; i < cycle->listening.nelts; i++) {

  544.         c = ngx_get_connection(ls[i].fd, cycle->log);

  545.         if (c == NULL) {
  546.             return NGX_ERROR;
  547.         }

  548.         c->log = &ls[i].log;

  549.         c->listening = &ls[i];
  550.         ls[i].connection = c;

  551.         rev = c->read;

  552.         rev->log = c->log;
  553.         rev->accept = 1;

  554. #if (NGX_HAVE_DEFERRED_ACCEPT)
  555.         rev->deferred_accept = ls[i].deferred_accept;
  556. #endif

  557.         if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
  558.             if (ls[i].previous) {

  559.                 /*
  560.                  * delete the old accept events that were bound to
  561.                  * the old cycle read events array
  562.                  */

  563.                 old = ls[i].previous->connection;

  564.                 if (ngx_del_event(old->read, NGX_READ_EVENT, NGX_CLOSE_EVENT)
  565.                     == NGX_ERROR)
  566.                 {
  567.                     return NGX_ERROR;
  568.                 }

  569.                 old->fd = (ngx_socket_t) -1;
  570.             }
  571.         }

  572. #if (NGX_WIN32)

  573.         if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
  574.             ngx_iocp_conf_t  *iocpcf;

  575.             rev->handler = ngx_event_acceptex;

  576.             if (ngx_use_accept_mutex) {
  577.                 continue;
  578.             }

  579.             if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) {
  580.                 return NGX_ERROR;
  581.             }

  582.             ls[i].log.handler = ngx_acceptex_log_error;

  583.             iocpcf = ngx_event_get_conf(cycle->conf_ctx, ngx_iocp_module);
  584.             if (ngx_event_post_acceptex(&ls[i], iocpcf->post_acceptex)
  585.                 == NGX_ERROR)
  586.             {
  587.                 return NGX_ERROR;
  588.             }

  589.         } else {
  590.             rev->handler = ngx_event_accept;

  591.             if (ngx_use_accept_mutex) {
  592.                 continue;
  593.             }

  594.             if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  595.                 return NGX_ERROR;
  596.             }
  597.         }

  598. #else

  599.         rev->handler = ngx_event_accept;

  600.         if (ngx_use_accept_mutex) {
  601.             continue;
  602.         }

  603.         if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
  604.             if (ngx_add_conn(c) == NGX_ERROR) {
  605.                 return NGX_ERROR;
  606.             }

  607.         } else {
  608.             if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  609.                 return NGX_ERROR;
  610.             }
  611.         }

  612. #endif

  613.     }

  614.     return NGX_OK;
  615. }


  616. ngx_int_t
  617. ngx_send_lowat(ngx_connection_t *c, size_t lowat)
  618. {
  619.     int  sndlowat;

  620. #if (NGX_HAVE_LOWAT_EVENT)

  621.     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
  622.         c->write->available = lowat;
  623.         return NGX_OK;
  624.     }

  625. #endif

  626.     if (lowat == 0 || c->sndlowat) {
  627.         return NGX_OK;
  628.     }

  629.     sndlowat = (int) lowat;

  630.     if (setsockopt(c->fd, SOL_SOCKET, SO_SNDLOWAT,
  631.                    (const void *) &sndlowat, sizeof(int))
  632.         == -1)
  633.     {
  634.         ngx_connection_error(c, ngx_socket_errno,
  635.                              "setsockopt(SO_SNDLOWAT) failed");
  636.         return NGX_ERROR;
  637.     }

  638.     c->sndlowat = 1;

  639.     return NGX_OK;
  640. }


  641. static char *
  642. ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  643. {
  644.     char                 *rv;
  645.     void               ***ctx;
  646.     ngx_uint_t            i;
  647.     ngx_conf_t            pcf;
  648.     ngx_event_module_t   *m;

  649.     if (*(void **) conf) {
  650.         return "is duplicate";
  651.     }

  652.     /* count the number of the event modules and set up their indices */

  653.     ngx_event_max_module = 0;
  654.     for (i = 0; ngx_modules[i]; i++) {
  655.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
  656.             continue;
  657.         }

  658.         ngx_modules[i]->ctx_index = ngx_event_max_module++;
  659.     }

  660.     ctx = ngx_pcalloc(cf->pool, sizeof(void *));
  661.     if (ctx == NULL) {
  662.         return NGX_CONF_ERROR;
  663.     }

  664.     *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));
  665.     if (*ctx == NULL) {
  666.         return NGX_CONF_ERROR;
  667.     }

  668.     *(void **) conf = ctx;

  669.     for (i = 0; ngx_modules[i]; i++) {
  670.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
  671.             continue;
  672.         }

  673.         m = ngx_modules[i]->ctx;

  674.         if (m->create_conf) {
  675.             (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);
  676.             if ((*ctx)[ngx_modules[i]->ctx_index] == NULL) {
  677.                 return NGX_CONF_ERROR;
  678.             }
  679.         }
  680.     }

  681.     pcf = *cf;
  682.     cf->ctx = ctx;
  683.     cf->module_type = NGX_EVENT_MODULE;
  684.     cf->cmd_type = NGX_EVENT_CONF;

  685.     rv = ngx_conf_parse(cf, NULL);

  686.     *cf = pcf;

  687.     if (rv != NGX_CONF_OK)
  688.         return rv;

  689.     for (i = 0; ngx_modules[i]; i++) {
  690.         if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
  691.             continue;
  692.         }

  693.         m = ngx_modules[i]->ctx;

  694.         if (m->init_conf) {
  695.             rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i]->ctx_index]);
  696.             if (rv != NGX_CONF_OK) {
  697.                 return rv;
  698.             }
  699.         }
  700.     }

  701.     return NGX_CONF_OK;
  702. }


  703. static char *
  704. ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  705. {
  706.     ngx_event_conf_t  *ecf = conf;

  707.     ngx_str_t  *value;

  708.     if (ecf->connections != NGX_CONF_UNSET_UINT) {
  709.         return "is duplicate";
  710.     }

  711.     if (ngx_strcmp(cmd->name.data, "connections") == 0) {
  712.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  713.                            "the \"connections\" directive is deprecated, "
  714.                            "use the \"worker_connections\" directive instead");
  715.     }

  716.     value = cf->args->elts;
  717.     ecf->connections = ngx_atoi(value[1].data, value[1].len);
  718.     if (ecf->connections == (ngx_uint_t) NGX_ERROR) {
  719.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  720.                            "invalid number \"%V\"", &value[1]);

  721.         return NGX_CONF_ERROR;
  722.     }

  723.     cf->cycle->connection_n = ecf->connections;

  724.     return NGX_CONF_OK;
  725. }


  726. static char *
  727. ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  728. {
  729.     ngx_event_conf_t  *ecf = conf;

  730.     ngx_int_t             m;
  731.     ngx_str_t            *value;
  732.     ngx_event_conf_t     *old_ecf;
  733.     ngx_event_module_t   *module;

  734.     if (ecf->use != NGX_CONF_UNSET_UINT) {
  735.         return "is duplicate";
  736.     }

  737.     value = cf->args->elts;

  738.     if (cf->cycle->old_cycle->conf_ctx) {
  739.         old_ecf = ngx_event_get_conf(cf->cycle->old_cycle->conf_ctx,
  740.                                      ngx_event_core_module);
  741.     } else {
  742.         old_ecf = NULL;
  743.     }


  744.     for (m = 0; ngx_modules[m]; m++) {
  745.         if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
  746.             continue;
  747.         }

  748.         module = ngx_modules[m]->ctx;
  749.         if (module->name->len == value[1].len) {
  750.             if (ngx_strcmp(module->name->data, value[1].data) == 0) {
  751.                 ecf->use = ngx_modules[m]->ctx_index;
  752.                 ecf->name = module->name->data;

  753.                 if (ngx_process == NGX_PROCESS_SINGLE
  754.                     && old_ecf
  755.                     && old_ecf->use != ecf->use)
  756.                 {
  757.                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  758.                                "when the server runs without a master process "
  759.                                "the \"%V\" event type must be the same as "
  760.                                "in previous configuration - \"%s\" "
  761.                                "and it cannot be changed on the fly, "
  762.                                "to change it you need to stop server "
  763.                                "and start it again",
  764.                                &value[1], old_ecf->name);

  765.                     return NGX_CONF_ERROR;
  766.                 }

  767.                 return NGX_CONF_OK;
  768.             }
  769.         }
  770.     }

  771.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  772.                        "invalid event type \"%V\"", &value[1]);

  773.     return NGX_CONF_ERROR;
  774. }


  775. static char *
  776. ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  777. {
  778. #if (NGX_DEBUG)
  779.     ngx_event_conf_t  *ecf = conf;

  780.     ngx_int_t             rc;
  781.     ngx_str_t            *value;
  782.     ngx_url_t             u;
  783.     ngx_cidr_t            c, *cidr;
  784.     ngx_uint_t            i;
  785.     struct sockaddr_in   *sin;
  786. #if (NGX_HAVE_INET6)
  787.     struct sockaddr_in6  *sin6;
  788. #endif

  789.     value = cf->args->elts;

  790. #if (NGX_HAVE_UNIX_DOMAIN)

  791.     if (ngx_strcmp(value[1].data, "unix:") == 0) {
  792.         cidr = ngx_array_push(&ecf->debug_connection);
  793.         if (cidr == NULL) {
  794.             return NGX_CONF_ERROR;
  795.         }

  796.         cidr->family = AF_UNIX;
  797.         return NGX_CONF_OK;
  798.     }

  799. #endif

  800.     rc = ngx_ptocidr(&value[1], &c);

  801.     if (rc != NGX_ERROR) {
  802.         if (rc == NGX_DONE) {
  803.             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  804.                                "low address bits of %V are meaningless",
  805.                                &value[1]);
  806.         }

  807.         cidr = ngx_array_push(&ecf->debug_connection);
  808.         if (cidr == NULL) {
  809.             return NGX_CONF_ERROR;
  810.         }

  811.         *cidr = c;

  812.         return NGX_CONF_OK;
  813.     }

  814.     ngx_memzero(&u, sizeof(ngx_url_t));
  815.     u.host = value[1];

  816.     if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
  817.         if (u.err) {
  818.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  819.                                "%s in debug_connection \"%V\"",
  820.                                u.err, &u.host);
  821.         }

  822.         return NGX_CONF_ERROR;
  823.     }

  824.     cidr = ngx_array_push_n(&ecf->debug_connection, u.naddrs);
  825.     if (cidr == NULL) {
  826.         return NGX_CONF_ERROR;
  827.     }

  828.     ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t));

  829.     for (i = 0; i < u.naddrs; i++) {
  830.         cidr[i].family = u.addrs[i].sockaddr->sa_family;

  831.         switch (cidr[i].family) {

  832. #if (NGX_HAVE_INET6)
  833.         case AF_INET6:
  834.             sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr;
  835.             cidr[i].u.in6.addr = sin6->sin6_addr;
  836.             ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16);
  837.             break;
  838. #endif

  839.         default: /* AF_INET */
  840.             sin = (struct sockaddr_in *) u.addrs[i].sockaddr;
  841.             cidr[i].u.in.addr = sin->sin_addr.s_addr;
  842.             cidr[i].u.in.mask = 0xffffffff;
  843.             break;
  844.         }
  845.     }

  846. #else

  847.     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  848.                        "\"debug_connection\" is ignored, you need to rebuild "
  849.                        "nginx using --with-debug option to enable it");

  850. #endif

  851.     return NGX_CONF_OK;
  852. }


  853. static void *
  854. ngx_event_core_create_conf(ngx_cycle_t *cycle)
  855. {
  856.     ngx_event_conf_t  *ecf;

  857.     ecf = ngx_palloc(cycle->pool, sizeof(ngx_event_conf_t));
  858.     if (ecf == NULL) {
  859.         return NULL;
  860.     }

  861.     ecf->connections = NGX_CONF_UNSET_UINT;
  862.     ecf->use = NGX_CONF_UNSET_UINT;
  863.     ecf->multi_accept = NGX_CONF_UNSET;
  864.     ecf->accept_mutex = NGX_CONF_UNSET;
  865.     ecf->accept_mutex_delay = NGX_CONF_UNSET_MSEC;
  866.     ecf->name = (void *) NGX_CONF_UNSET;

  867. #if (NGX_DEBUG)

  868.     if (ngx_array_init(&ecf->debug_connection, cycle->pool, 4,
  869.                        sizeof(ngx_cidr_t)) == NGX_ERROR)
  870.     {
  871.         return NULL;
  872.     }

  873. #endif

  874.     return ecf;
  875. }


  876. static char *
  877. ngx_event_core_init_conf(ngx_cycle_t *cycle, void *conf)
  878. {
  879.     ngx_event_conf_t  *ecf = conf;

  880. #if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL)
  881.     int                  fd;
  882. #endif
  883. #if (NGX_HAVE_RTSIG)
  884.     ngx_uint_t           rtsig;
  885.     ngx_core_conf_t     *ccf;
  886. #endif
  887.     ngx_int_t            i;
  888.     ngx_module_t        *module;
  889.     ngx_event_module_t  *event_module;

  890.     module = NULL;

  891. #if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL)

  892.     fd = epoll_create(100);

  893.     if (fd != -1) {
  894.         (void) close(fd);
  895.         module = &ngx_epoll_module;

  896.     } else if (ngx_errno != NGX_ENOSYS) {
  897.         module = &ngx_epoll_module;
  898.     }

  899. #endif

  900. #if (NGX_HAVE_RTSIG)

  901.     if (module == NULL) {
  902.         module = &ngx_rtsig_module;
  903.         rtsig = 1;

  904.     } else {
  905.         rtsig = 0;
  906.     }

  907. #endif

  908. #if (NGX_HAVE_DEVPOLL)

  909.     module = &ngx_devpoll_module;

  910. #endif

  911. #if (NGX_HAVE_KQUEUE)

  912.     module = &ngx_kqueue_module;

  913. #endif

  914. #if (NGX_HAVE_SELECT)

  915.     if (module == NULL) {
  916.         module = &ngx_select_module;
  917.     }

  918. #endif

  919.     if (module == NULL) {
  920.         for (i = 0; ngx_modules[i]; i++) {

  921.             if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
  922.                 continue;
  923.             }

  924.             event_module = ngx_modules[i]->ctx;

  925.             if (ngx_strcmp(event_module->name->data, event_core_name.data) == 0)
  926.             {
  927.                 continue;
  928.             }

  929.             module = ngx_modules[i];
  930.             break;
  931.         }
  932.     }

  933.     if (module == NULL) {
  934.         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "no events module found");
  935.         return NGX_CONF_ERROR;
  936.     }

  937.     ngx_conf_init_uint_value(ecf->connections, DEFAULT_CONNECTIONS);
  938.     cycle->connection_n = ecf->connections;

  939.     ngx_conf_init_uint_value(ecf->use, module->ctx_index);

  940.     event_module = module->ctx;
  941.     ngx_conf_init_ptr_value(ecf->name, event_module->name->data);

  942.     ngx_conf_init_value(ecf->multi_accept, 0);
  943.     ngx_conf_init_value(ecf->accept_mutex, 1);
  944.     ngx_conf_init_msec_value(ecf->accept_mutex_delay, 500);


  945. #if (NGX_HAVE_RTSIG)

  946.     if (!rtsig) {
  947.         return NGX_CONF_OK;
  948.     }

  949.     if (ecf->accept_mutex) {
  950.         return NGX_CONF_OK;
  951.     }

  952.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

  953.     if (ccf->worker_processes == 0) {
  954.         return NGX_CONF_OK;
  955.     }

  956.     ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  957.                   "the \"rtsig\" method requires \"accept_mutex\" to be on");

  958.     return NGX_CONF_ERROR;

  959. #else

  960.     return NGX_CONF_OK;

  961. #endif
  962. }