src/event/ngx_event.c - nginx source code

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_select_module;


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

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

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


  25. static ngx_uint_t     ngx_timer_resolution;
  26. sig_atomic_t          ngx_event_timer_alarm;

  27. static ngx_uint_t     ngx_event_max_module;

  28. ngx_uint_t            ngx_event_flags;
  29. ngx_event_actions_t   ngx_event_actions;


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


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


  40. #if (NGX_STAT_STUB)

  41. static ngx_atomic_t   ngx_stat_accepted0;
  42. ngx_atomic_t         *ngx_stat_accepted = &ngx_stat_accepted0;
  43. static ngx_atomic_t   ngx_stat_handled0;
  44. ngx_atomic_t         *ngx_stat_handled = &ngx_stat_handled0;
  45. static ngx_atomic_t   ngx_stat_requests0;
  46. ngx_atomic_t         *ngx_stat_requests = &ngx_stat_requests0;
  47. static ngx_atomic_t   ngx_stat_active0;
  48. ngx_atomic_t         *ngx_stat_active = &ngx_stat_active0;
  49. static ngx_atomic_t   ngx_stat_reading0;
  50. ngx_atomic_t         *ngx_stat_reading = &ngx_stat_reading0;
  51. static ngx_atomic_t   ngx_stat_writing0;
  52. ngx_atomic_t         *ngx_stat_writing = &ngx_stat_writing0;
  53. static 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("use"),
  93.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  94.       ngx_event_use,
  95.       0,
  96.       0,
  97.       NULL },

  98.     { ngx_string("multi_accept"),
  99.       NGX_EVENT_CONF|NGX_CONF_FLAG,
  100.       ngx_conf_set_flag_slot,
  101.       0,
  102.       offsetof(ngx_event_conf_t, multi_accept),
  103.       NULL },

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

  110.     { ngx_string("accept_mutex_delay"),
  111.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  112.       ngx_conf_set_msec_slot,
  113.       0,
  114.       offsetof(ngx_event_conf_t, accept_mutex_delay),
  115.       NULL },

  116.     { ngx_string("debug_connection"),
  117.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  118.       ngx_event_debug_connection,
  119.       0,
  120.       0,
  121.       NULL },

  122.       ngx_null_command
  123. };


  124. static ngx_event_module_t  ngx_event_core_module_ctx = {
  125.     &event_core_name,
  126.     ngx_event_core_create_conf,            /* create configuration */
  127.     ngx_event_core_init_conf,              /* init configuration */

  128.     { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
  129. };


  130. ngx_module_t  ngx_event_core_module = {
  131.     NGX_MODULE_V1,
  132.     &ngx_event_core_module_ctx,            /* module context */
  133.     ngx_event_core_commands,               /* module directives */
  134.     NGX_EVENT_MODULE,                      /* module type */
  135.     NULL,                                  /* init master */
  136.     ngx_event_module_init,                 /* init module */
  137.     ngx_event_process_init,                /* init process */
  138.     NULL,                                  /* init thread */
  139.     NULL,                                  /* exit thread */
  140.     NULL,                                  /* exit process */
  141.     NULL,                                  /* exit master */
  142.     NGX_MODULE_V1_PADDING
  143. };


  144. void
  145. ngx_process_events_and_timers(ngx_cycle_t *cycle)
  146. {
  147.     ngx_uint_t  flags;
  148.     ngx_msec_t  timer, delta;

  149.     if (ngx_timer_resolution) {
  150.         timer = NGX_TIMER_INFINITE;
  151.         flags = 0;

  152.     } else {
  153.         timer = ngx_event_find_timer();
  154.         flags = NGX_UPDATE_TIME;

  155. #if (NGX_WIN32)

  156.         /* handle signals from master in case of network inactivity */

  157.         if (timer == NGX_TIMER_INFINITE || timer > 500) {
  158.             timer = 500;
  159.         }

  160. #endif
  161.     }

  162.     if (ngx_use_accept_mutex) {
  163.         if (ngx_accept_disabled > 0) {
  164.             ngx_accept_disabled--;

  165.         } else {
  166.             if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) {
  167.                 return;
  168.             }

  169.             if (ngx_accept_mutex_held) {
  170.                 flags |= NGX_POST_EVENTS;

  171.             } else {
  172.                 if (timer == NGX_TIMER_INFINITE
  173.                     || timer > ngx_accept_mutex_delay)
  174.                 {
  175.                     timer = ngx_accept_mutex_delay;
  176.                 }
  177.             }
  178.         }
  179.     }

  180.     if (!ngx_queue_empty(&ngx_posted_next_events)) {
  181.         ngx_event_move_posted_next(cycle);
  182.         timer = 0;
  183.     }

  184.     delta = ngx_current_msec;

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

  186.     delta = ngx_current_msec - delta;

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

  189.     ngx_event_process_posted(cycle, &ngx_posted_accept_events);

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

  193.     ngx_event_expire_timers();

  194.     ngx_event_process_posted(cycle, &ngx_posted_events);
  195. }


  196. ngx_int_t
  197. ngx_handle_read_event(ngx_event_t *rev, ngx_uint_t flags)
  198. {
  199. #if (NGX_QUIC)

  200.     ngx_connection_t  *c;

  201.     c = rev->data;

  202.     if (c->quic) {
  203.         return NGX_OK;
  204.     }

  205. #endif

  206.     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {

  207.         /* kqueue, epoll */

  208.         if (!rev->active && !rev->ready) {
  209.             if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT)
  210.                 == NGX_ERROR)
  211.             {
  212.                 return NGX_ERROR;
  213.             }
  214.         }

  215.         return NGX_OK;

  216.     } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {

  217.         /* select, poll, /dev/poll */

  218.         if (!rev->active && !rev->ready) {
  219.             if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT)
  220.                 == NGX_ERROR)
  221.             {
  222.                 return NGX_ERROR;
  223.             }

  224.             return NGX_OK;
  225.         }

  226.         if (rev->active && (rev->ready || (flags & NGX_CLOSE_EVENT))) {
  227.             if (ngx_del_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT | flags)
  228.                 == NGX_ERROR)
  229.             {
  230.                 return NGX_ERROR;
  231.             }

  232.             return NGX_OK;
  233.         }

  234.     } else if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {

  235.         /* event ports */

  236.         if (!rev->active && !rev->ready) {
  237.             if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  238.                 return NGX_ERROR;
  239.             }

  240.             return NGX_OK;
  241.         }

  242.         if (rev->oneshot && rev->ready) {
  243.             if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  244.                 return NGX_ERROR;
  245.             }

  246.             return NGX_OK;
  247.         }
  248.     }

  249.     /* iocp */

  250.     return NGX_OK;
  251. }


  252. ngx_int_t
  253. ngx_handle_write_event(ngx_event_t *wev, size_t lowat)
  254. {
  255.     ngx_connection_t  *c;

  256.     c = wev->data;

  257. #if (NGX_QUIC)
  258.     if (c->quic) {
  259.         return NGX_OK;
  260.     }
  261. #endif

  262.     if (lowat) {
  263.         if (ngx_send_lowat(c, lowat) == NGX_ERROR) {
  264.             return NGX_ERROR;
  265.         }
  266.     }

  267.     if (ngx_event_flags & NGX_USE_CLEAR_EVENT) {

  268.         /* kqueue, epoll */

  269.         if (!wev->active && !wev->ready) {
  270.             if (ngx_add_event(wev, NGX_WRITE_EVENT,
  271.                               NGX_CLEAR_EVENT | (lowat ? NGX_LOWAT_EVENT : 0))
  272.                 == NGX_ERROR)
  273.             {
  274.                 return NGX_ERROR;
  275.             }
  276.         }

  277.         return NGX_OK;

  278.     } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) {

  279.         /* select, poll, /dev/poll */

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

  286.             return NGX_OK;
  287.         }

  288.         if (wev->active && wev->ready) {
  289.             if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT)
  290.                 == NGX_ERROR)
  291.             {
  292.                 return NGX_ERROR;
  293.             }

  294.             return NGX_OK;
  295.         }

  296.     } else if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) {

  297.         /* event ports */

  298.         if (!wev->active && !wev->ready) {
  299.             if (ngx_add_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
  300.                 return NGX_ERROR;
  301.             }

  302.             return NGX_OK;
  303.         }

  304.         if (wev->oneshot && wev->ready) {
  305.             if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
  306.                 return NGX_ERROR;
  307.             }

  308.             return NGX_OK;
  309.         }
  310.     }

  311.     /* iocp */

  312.     return NGX_OK;
  313. }


  314. static char *
  315. ngx_event_init_conf(ngx_cycle_t *cycle, void *conf)
  316. {
  317. #if (NGX_HAVE_REUSEPORT)
  318.     ngx_uint_t        i;
  319.     ngx_core_conf_t  *ccf;
  320.     ngx_listening_t  *ls;
  321. #endif

  322.     if (ngx_get_conf(cycle->conf_ctx, ngx_events_module) == NULL) {
  323.         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  324.                       "no \"events\" section in configuration");
  325.         return NGX_CONF_ERROR;
  326.     }

  327.     if (cycle->connection_n < cycle->listening.nelts + 1) {

  328.         /*
  329.          * there should be at least one connection for each listening
  330.          * socket, plus an additional connection for channel
  331.          */

  332.         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  333.                       "%ui worker_connections are not enough "
  334.                       "for %ui listening sockets",
  335.                       cycle->connection_n, cycle->listening.nelts);

  336.         return NGX_CONF_ERROR;
  337.     }

  338. #if (NGX_HAVE_REUSEPORT)

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

  340.     if (!ngx_test_config && ccf->master) {

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

  343.             if (!ls[i].reuseport || ls[i].worker != 0) {
  344.                 continue;
  345.             }

  346.             if (ngx_clone_listening(cycle, &ls[i]) != NGX_OK) {
  347.                 return NGX_CONF_ERROR;
  348.             }

  349.             /* cloning may change cycle->listening.elts */

  350.             ls = cycle->listening.elts;
  351.         }
  352.     }

  353. #endif

  354.     return NGX_CONF_OK;
  355. }


  356. static ngx_int_t
  357. ngx_event_module_init(ngx_cycle_t *cycle)
  358. {
  359.     void              ***cf;
  360.     u_char              *shared;
  361.     size_t               size, cl;
  362.     ngx_shm_t            shm;
  363.     ngx_time_t          *tp;
  364.     ngx_core_conf_t     *ccf;
  365.     ngx_event_conf_t    *ecf;

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

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

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

  373.     ngx_timer_resolution = ccf->timer_resolution;

  374. #if !(NGX_WIN32)
  375.     {
  376.     ngx_int_t      limit;
  377.     struct rlimit  rlmt;

  378.     if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
  379.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  380.                       "getrlimit(RLIMIT_NOFILE) failed, ignored");

  381.     } else {
  382.         if (ecf->connections > (ngx_uint_t) rlmt.rlim_cur
  383.             && (ccf->rlimit_nofile == NGX_CONF_UNSET
  384.                 || ecf->connections > (ngx_uint_t) ccf->rlimit_nofile))
  385.         {
  386.             limit = (ccf->rlimit_nofile == NGX_CONF_UNSET) ?
  387.                          (ngx_int_t) rlmt.rlim_cur : ccf->rlimit_nofile;

  388.             ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
  389.                           "%ui worker_connections exceed "
  390.                           "open file resource limit: %i",
  391.                           ecf->connections, limit);
  392.         }
  393.     }
  394.     }
  395. #endif /* !(NGX_WIN32) */


  396.     if (ccf->master == 0) {
  397.         return NGX_OK;
  398.     }

  399.     if (ngx_accept_mutex_ptr) {
  400.         return NGX_OK;
  401.     }


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

  403.     cl = 128;

  404.     size = cl            /* ngx_accept_mutex */
  405.            + cl          /* ngx_connection_counter */
  406.            + cl;         /* ngx_temp_number */

  407. #if (NGX_STAT_STUB)

  408.     size += cl           /* ngx_stat_accepted */
  409.            + cl          /* ngx_stat_handled */
  410.            + cl          /* ngx_stat_requests */
  411.            + cl          /* ngx_stat_active */
  412.            + cl          /* ngx_stat_reading */
  413.            + cl          /* ngx_stat_writing */
  414.            + cl;         /* ngx_stat_waiting */

  415. #endif

  416.     shm.size = size;
  417.     ngx_str_set(&shm.name, "nginx_shared_zone");
  418.     shm.log = cycle->log;

  419.     if (ngx_shm_alloc(&shm) != NGX_OK) {
  420.         return NGX_ERROR;
  421.     }

  422.     shared = shm.addr;

  423.     ngx_accept_mutex_ptr = (ngx_atomic_t *) shared;
  424.     ngx_accept_mutex.spin = (ngx_uint_t) -1;

  425.     if (ngx_shmtx_create(&ngx_accept_mutex, (ngx_shmtx_sh_t *) shared,
  426.                          cycle->lock_file.data)
  427.         != NGX_OK)
  428.     {
  429.         return NGX_ERROR;
  430.     }

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

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

  433.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  434.                    "counter: %p, %uA",
  435.                    ngx_connection_counter, *ngx_connection_counter);

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

  437.     tp = ngx_timeofday();

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

  439. #if (NGX_STAT_STUB)

  440.     ngx_stat_accepted = (ngx_atomic_t *) (shared + 3 * cl);
  441.     ngx_stat_handled = (ngx_atomic_t *) (shared + 4 * cl);
  442.     ngx_stat_requests = (ngx_atomic_t *) (shared + 5 * cl);
  443.     ngx_stat_active = (ngx_atomic_t *) (shared + 6 * cl);
  444.     ngx_stat_reading = (ngx_atomic_t *) (shared + 7 * cl);
  445.     ngx_stat_writing = (ngx_atomic_t *) (shared + 8 * cl);
  446.     ngx_stat_waiting = (ngx_atomic_t *) (shared + 9 * cl);

  447. #endif

  448.     return NGX_OK;
  449. }


  450. #if !(NGX_WIN32)

  451. static void
  452. ngx_timer_signal_handler(int signo)
  453. {
  454.     ngx_event_timer_alarm = 1;

  455. #if 1
  456.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, "timer signal");
  457. #endif
  458. }

  459. #endif


  460. static ngx_int_t
  461. ngx_event_process_init(ngx_cycle_t *cycle)
  462. {
  463.     ngx_uint_t           m, i;
  464.     ngx_event_t         *rev, *wev;
  465.     ngx_listening_t     *ls;
  466.     ngx_connection_t    *c, *next, *old;
  467.     ngx_core_conf_t     *ccf;
  468.     ngx_event_conf_t    *ecf;
  469.     ngx_event_module_t  *module;

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

  472.     if (ccf->master && ccf->worker_processes > 1 && ecf->accept_mutex) {
  473.         ngx_use_accept_mutex = 1;
  474.         ngx_accept_mutex_held = 0;
  475.         ngx_accept_mutex_delay = ecf->accept_mutex_delay;

  476.     } else {
  477.         ngx_use_accept_mutex = 0;
  478.     }

  479. #if (NGX_WIN32)

  480.     /*
  481.      * disable accept mutex on win32 as it may cause deadlock if
  482.      * grabbed by a process which can't accept connections
  483.      */

  484.     ngx_use_accept_mutex = 0;

  485. #endif

  486.     ngx_use_exclusive_accept = 0;

  487.     ngx_queue_init(&ngx_posted_accept_events);
  488.     ngx_queue_init(&ngx_posted_next_events);
  489.     ngx_queue_init(&ngx_posted_events);

  490.     if (ngx_event_timer_init(cycle->log) == NGX_ERROR) {
  491.         return NGX_ERROR;
  492.     }

  493.     for (m = 0; cycle->modules[m]; m++) {
  494.         if (cycle->modules[m]->type != NGX_EVENT_MODULE) {
  495.             continue;
  496.         }

  497.         if (cycle->modules[m]->ctx_index != ecf->use) {
  498.             continue;
  499.         }

  500.         module = cycle->modules[m]->ctx;

  501.         if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
  502.             /* fatal */
  503.             exit(2);
  504.         }

  505.         break;
  506.     }

  507. #if !(NGX_WIN32)

  508.     if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) {
  509.         struct sigaction  sa;
  510.         struct itimerval  itv;

  511.         ngx_memzero(&sa, sizeof(struct sigaction));
  512.         sa.sa_handler = ngx_timer_signal_handler;
  513.         sigemptyset(&sa.sa_mask);

  514.         if (sigaction(SIGALRM, &sa, NULL) == -1) {
  515.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  516.                           "sigaction(SIGALRM) failed");
  517.             return NGX_ERROR;
  518.         }

  519.         itv.it_interval.tv_sec = ngx_timer_resolution / 1000;
  520.         itv.it_interval.tv_usec = (ngx_timer_resolution % 1000) * 1000;
  521.         itv.it_value.tv_sec = ngx_timer_resolution / 1000;
  522.         itv.it_value.tv_usec = (ngx_timer_resolution % 1000 ) * 1000;

  523.         if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {
  524.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  525.                           "setitimer() failed");
  526.         }
  527.     }

  528.     if (ngx_event_flags & NGX_USE_FD_EVENT) {
  529.         struct rlimit  rlmt;

  530.         if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
  531.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  532.                           "getrlimit(RLIMIT_NOFILE) failed");
  533.             return NGX_ERROR;
  534.         }

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

  536.         cycle->files = ngx_calloc(sizeof(ngx_connection_t *) * cycle->files_n,
  537.                                   cycle->log);
  538.         if (cycle->files == NULL) {
  539.             return NGX_ERROR;
  540.         }
  541.     }

  542. #else

  543.     if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) {
  544.         ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
  545.                       "the \"timer_resolution\" directive is not supported "
  546.                       "with the configured event method, ignored");
  547.         ngx_timer_resolution = 0;
  548.     }

  549. #endif

  550.     cycle->connections =
  551.         ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);
  552.     if (cycle->connections == NULL) {
  553.         return NGX_ERROR;
  554.     }

  555.     c = cycle->connections;

  556.     cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
  557.                                    cycle->log);
  558.     if (cycle->read_events == NULL) {
  559.         return NGX_ERROR;
  560.     }

  561.     rev = cycle->read_events;
  562.     for (i = 0; i < cycle->connection_n; i++) {
  563.         rev[i].closed = 1;
  564.         rev[i].instance = 1;
  565.     }

  566.     cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
  567.                                     cycle->log);
  568.     if (cycle->write_events == NULL) {
  569.         return NGX_ERROR;
  570.     }

  571.     wev = cycle->write_events;
  572.     for (i = 0; i < cycle->connection_n; i++) {
  573.         wev[i].closed = 1;
  574.     }

  575.     i = cycle->connection_n;
  576.     next = NULL;

  577.     do {
  578.         i--;

  579.         c[i].data = next;
  580.         c[i].read = &cycle->read_events[i];
  581.         c[i].write = &cycle->write_events[i];
  582.         c[i].fd = (ngx_socket_t) -1;

  583.         next = &c[i];
  584.     } while (i);

  585.     cycle->free_connections = next;
  586.     cycle->free_connection_n = cycle->connection_n;

  587.     /* for each listening socket */

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

  590. #if (NGX_HAVE_REUSEPORT)
  591.         if (ls[i].reuseport && ls[i].worker != ngx_worker) {
  592.             continue;
  593.         }
  594. #endif

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

  596.         if (c == NULL) {
  597.             return NGX_ERROR;
  598.         }

  599.         c->type = ls[i].type;
  600.         c->log = &ls[i].log;

  601.         c->listening = &ls[i];
  602.         ls[i].connection = c;

  603.         rev = c->read;

  604.         rev->log = c->log;
  605.         rev->accept = 1;

  606. #if (NGX_HAVE_DEFERRED_ACCEPT)
  607.         rev->deferred_accept = ls[i].deferred_accept;
  608. #endif

  609.         if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)
  610.             && cycle->old_cycle)
  611.         {
  612.             if (ls[i].previous) {

  613.                 /*
  614.                  * delete the old accept events that were bound to
  615.                  * the old cycle read events array
  616.                  */

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

  618.                 if (ngx_del_event(old->read, NGX_READ_EVENT, NGX_CLOSE_EVENT)
  619.                     == NGX_ERROR)
  620.                 {
  621.                     return NGX_ERROR;
  622.                 }

  623.                 old->fd = (ngx_socket_t) -1;
  624.             }
  625.         }

  626. #if (NGX_WIN32)

  627.         if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
  628.             ngx_iocp_conf_t  *iocpcf;

  629.             rev->handler = ngx_event_acceptex;

  630.             if (ngx_use_accept_mutex) {
  631.                 continue;
  632.             }

  633.             if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) {
  634.                 return NGX_ERROR;
  635.             }

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

  637.             iocpcf = ngx_event_get_conf(cycle->conf_ctx, ngx_iocp_module);
  638.             if (ngx_event_post_acceptex(&ls[i], iocpcf->post_acceptex)
  639.                 == NGX_ERROR)
  640.             {
  641.                 return NGX_ERROR;
  642.             }

  643.         } else {
  644.             rev->handler = ngx_event_accept;

  645.             if (ngx_use_accept_mutex) {
  646.                 continue;
  647.             }

  648.             if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  649.                 return NGX_ERROR;
  650.             }
  651.         }

  652. #else

  653.         if (c->type == SOCK_STREAM) {
  654.             rev->handler = ngx_event_accept;

  655. #if (NGX_QUIC)
  656.         } else if (ls[i].quic) {
  657.             rev->handler = ngx_quic_recvmsg;
  658. #endif
  659.         } else {
  660.             rev->handler = ngx_event_recvmsg;
  661.         }

  662. #if (NGX_HAVE_REUSEPORT)

  663.         if (ls[i].reuseport) {
  664.             if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  665.                 return NGX_ERROR;
  666.             }

  667.             continue;
  668.         }

  669. #endif

  670.         if (ngx_use_accept_mutex) {
  671.             continue;
  672.         }

  673. #if (NGX_HAVE_EPOLLEXCLUSIVE)

  674.         if ((ngx_event_flags & NGX_USE_EPOLL_EVENT)
  675.             && ccf->worker_processes > 1)
  676.         {
  677.             ngx_use_exclusive_accept = 1;

  678.             if (ngx_add_event(rev, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT)
  679.                 == NGX_ERROR)
  680.             {
  681.                 return NGX_ERROR;
  682.             }

  683.             continue;
  684.         }

  685. #endif

  686.         if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {
  687.             return NGX_ERROR;
  688.         }

  689. #endif

  690.     }

  691.     return NGX_OK;
  692. }


  693. ngx_int_t
  694. ngx_send_lowat(ngx_connection_t *c, size_t lowat)
  695. {
  696.     int  sndlowat;

  697. #if (NGX_HAVE_LOWAT_EVENT)

  698.     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
  699.         c->write->available = lowat;
  700.         return NGX_OK;
  701.     }

  702. #endif

  703.     if (lowat == 0 || c->sndlowat) {
  704.         return NGX_OK;
  705.     }

  706.     sndlowat = (int) lowat;

  707.     if (setsockopt(c->fd, SOL_SOCKET, SO_SNDLOWAT,
  708.                    (const void *) &sndlowat, sizeof(int))
  709.         == -1)
  710.     {
  711.         ngx_connection_error(c, ngx_socket_errno,
  712.                              "setsockopt(SO_SNDLOWAT) failed");
  713.         return NGX_ERROR;
  714.     }

  715.     c->sndlowat = 1;

  716.     return NGX_OK;
  717. }


  718. static char *
  719. ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  720. {
  721.     char                 *rv;
  722.     void               ***ctx;
  723.     ngx_uint_t            i;
  724.     ngx_conf_t            pcf;
  725.     ngx_event_module_t   *m;

  726.     if (*(void **) conf) {
  727.         return "is duplicate";
  728.     }

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

  730.     ngx_event_max_module = ngx_count_modules(cf->cycle, NGX_EVENT_MODULE);

  731.     ctx = ngx_pcalloc(cf->pool, sizeof(void *));
  732.     if (ctx == NULL) {
  733.         return NGX_CONF_ERROR;
  734.     }

  735.     *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));
  736.     if (*ctx == NULL) {
  737.         return NGX_CONF_ERROR;
  738.     }

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

  740.     for (i = 0; cf->cycle->modules[i]; i++) {
  741.         if (cf->cycle->modules[i]->type != NGX_EVENT_MODULE) {
  742.             continue;
  743.         }

  744.         m = cf->cycle->modules[i]->ctx;

  745.         if (m->create_conf) {
  746.             (*ctx)[cf->cycle->modules[i]->ctx_index] =
  747.                                                      m->create_conf(cf->cycle);
  748.             if ((*ctx)[cf->cycle->modules[i]->ctx_index] == NULL) {
  749.                 return NGX_CONF_ERROR;
  750.             }
  751.         }
  752.     }

  753.     pcf = *cf;
  754.     cf->ctx = ctx;
  755.     cf->module_type = NGX_EVENT_MODULE;
  756.     cf->cmd_type = NGX_EVENT_CONF;

  757.     rv = ngx_conf_parse(cf, NULL);

  758.     *cf = pcf;

  759.     if (rv != NGX_CONF_OK) {
  760.         return rv;
  761.     }

  762.     for (i = 0; cf->cycle->modules[i]; i++) {
  763.         if (cf->cycle->modules[i]->type != NGX_EVENT_MODULE) {
  764.             continue;
  765.         }

  766.         m = cf->cycle->modules[i]->ctx;

  767.         if (m->init_conf) {
  768.             rv = m->init_conf(cf->cycle,
  769.                               (*ctx)[cf->cycle->modules[i]->ctx_index]);
  770.             if (rv != NGX_CONF_OK) {
  771.                 return rv;
  772.             }
  773.         }
  774.     }

  775.     return NGX_CONF_OK;
  776. }


  777. static char *
  778. ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  779. {
  780.     ngx_event_conf_t  *ecf = conf;

  781.     ngx_str_t  *value;

  782.     if (ecf->connections != NGX_CONF_UNSET_UINT) {
  783.         return "is duplicate";
  784.     }

  785.     value = cf->args->elts;
  786.     ecf->connections = ngx_atoi(value[1].data, value[1].len);
  787.     if (ecf->connections == (ngx_uint_t) NGX_ERROR) {
  788.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  789.                            "invalid number \"%V\"", &value[1]);

  790.         return NGX_CONF_ERROR;
  791.     }

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

  793.     return NGX_CONF_OK;
  794. }


  795. static char *
  796. ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  797. {
  798.     ngx_event_conf_t  *ecf = conf;

  799.     ngx_int_t             m;
  800.     ngx_str_t            *value;
  801.     ngx_event_conf_t     *old_ecf;
  802.     ngx_event_module_t   *module;

  803.     if (ecf->use != NGX_CONF_UNSET_UINT) {
  804.         return "is duplicate";
  805.     }

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

  807.     if (cf->cycle->old_cycle->conf_ctx) {
  808.         old_ecf = ngx_event_get_conf(cf->cycle->old_cycle->conf_ctx,
  809.                                      ngx_event_core_module);
  810.     } else {
  811.         old_ecf = NULL;
  812.     }


  813.     for (m = 0; cf->cycle->modules[m]; m++) {
  814.         if (cf->cycle->modules[m]->type != NGX_EVENT_MODULE) {
  815.             continue;
  816.         }

  817.         module = cf->cycle->modules[m]->ctx;
  818.         if (module->name->len == value[1].len) {
  819.             if (ngx_strcmp(module->name->data, value[1].data) == 0) {
  820.                 ecf->use = cf->cycle->modules[m]->ctx_index;
  821.                 ecf->name = module->name->data;

  822.                 if (ngx_process == NGX_PROCESS_SINGLE
  823.                     && old_ecf
  824.                     && old_ecf->use != ecf->use)
  825.                 {
  826.                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  827.                                "when the server runs without a master process "
  828.                                "the \"%V\" event type must be the same as "
  829.                                "in previous configuration - \"%s\" "
  830.                                "and it cannot be changed on the fly, "
  831.                                "to change it you need to stop server "
  832.                                "and start it again",
  833.                                &value[1], old_ecf->name);

  834.                     return NGX_CONF_ERROR;
  835.                 }

  836.                 return NGX_CONF_OK;
  837.             }
  838.         }
  839.     }

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

  842.     return NGX_CONF_ERROR;
  843. }


  844. static char *
  845. ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  846. {
  847. #if (NGX_DEBUG)
  848.     ngx_event_conf_t  *ecf = conf;

  849.     ngx_int_t             rc;
  850.     ngx_str_t            *value;
  851.     ngx_url_t             u;
  852.     ngx_cidr_t            c, *cidr;
  853.     ngx_uint_t            i;
  854.     struct sockaddr_in   *sin;
  855. #if (NGX_HAVE_INET6)
  856.     struct sockaddr_in6  *sin6;
  857. #endif

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

  859. #if (NGX_HAVE_UNIX_DOMAIN)

  860.     if (ngx_strcmp(value[1].data, "unix:") == 0) {
  861.         cidr = ngx_array_push(&ecf->debug_connection);
  862.         if (cidr == NULL) {
  863.             return NGX_CONF_ERROR;
  864.         }

  865.         cidr->family = AF_UNIX;
  866.         return NGX_CONF_OK;
  867.     }

  868. #endif

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

  870.     if (rc != NGX_ERROR) {
  871.         if (rc == NGX_DONE) {
  872.             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  873.                                "low address bits of %V are meaningless",
  874.                                &value[1]);
  875.         }

  876.         cidr = ngx_array_push(&ecf->debug_connection);
  877.         if (cidr == NULL) {
  878.             return NGX_CONF_ERROR;
  879.         }

  880.         *cidr = c;

  881.         return NGX_CONF_OK;
  882.     }

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

  885.     if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
  886.         if (u.err) {
  887.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  888.                                "%s in debug_connection \"%V\"",
  889.                                u.err, &u.host);
  890.         }

  891.         return NGX_CONF_ERROR;
  892.     }

  893.     cidr = ngx_array_push_n(&ecf->debug_connection, u.naddrs);
  894.     if (cidr == NULL) {
  895.         return NGX_CONF_ERROR;
  896.     }

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

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

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

  901. #if (NGX_HAVE_INET6)
  902.         case AF_INET6:
  903.             sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr;
  904.             cidr[i].u.in6.addr = sin6->sin6_addr;
  905.             ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16);
  906.             break;
  907. #endif

  908.         default: /* AF_INET */
  909.             sin = (struct sockaddr_in *) u.addrs[i].sockaddr;
  910.             cidr[i].u.in.addr = sin->sin_addr.s_addr;
  911.             cidr[i].u.in.mask = 0xffffffff;
  912.             break;
  913.         }
  914.     }

  915. #else

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

  919. #endif

  920.     return NGX_CONF_OK;
  921. }


  922. static void *
  923. ngx_event_core_create_conf(ngx_cycle_t *cycle)
  924. {
  925.     ngx_event_conf_t  *ecf;

  926.     ecf = ngx_palloc(cycle->pool, sizeof(ngx_event_conf_t));
  927.     if (ecf == NULL) {
  928.         return NULL;
  929.     }

  930.     ecf->connections = NGX_CONF_UNSET_UINT;
  931.     ecf->use = NGX_CONF_UNSET_UINT;
  932.     ecf->multi_accept = NGX_CONF_UNSET;
  933.     ecf->accept_mutex = NGX_CONF_UNSET;
  934.     ecf->accept_mutex_delay = NGX_CONF_UNSET_MSEC;
  935.     ecf->name = (void *) NGX_CONF_UNSET;

  936. #if (NGX_DEBUG)

  937.     if (ngx_array_init(&ecf->debug_connection, cycle->pool, 4,
  938.                        sizeof(ngx_cidr_t)) == NGX_ERROR)
  939.     {
  940.         return NULL;
  941.     }

  942. #endif

  943.     return ecf;
  944. }


  945. static char *
  946. ngx_event_core_init_conf(ngx_cycle_t *cycle, void *conf)
  947. {
  948.     ngx_event_conf_t  *ecf = conf;

  949. #if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL)
  950.     int                  fd;
  951. #endif
  952.     ngx_int_t            i;
  953.     ngx_module_t        *module;
  954.     ngx_event_module_t  *event_module;

  955.     module = NULL;

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

  957.     fd = epoll_create(100);

  958.     if (fd != -1) {
  959.         (void) close(fd);
  960.         module = &ngx_epoll_module;

  961.     } else if (ngx_errno != NGX_ENOSYS) {
  962.         module = &ngx_epoll_module;
  963.     }

  964. #endif

  965. #if (NGX_HAVE_DEVPOLL) && !(NGX_TEST_BUILD_DEVPOLL)

  966.     module = &ngx_devpoll_module;

  967. #endif

  968. #if (NGX_HAVE_KQUEUE)

  969.     module = &ngx_kqueue_module;

  970. #endif

  971. #if (NGX_HAVE_SELECT)

  972.     if (module == NULL) {
  973.         module = &ngx_select_module;
  974.     }

  975. #endif

  976.     if (module == NULL) {
  977.         for (i = 0; cycle->modules[i]; i++) {

  978.             if (cycle->modules[i]->type != NGX_EVENT_MODULE) {
  979.                 continue;
  980.             }

  981.             event_module = cycle->modules[i]->ctx;

  982.             if (ngx_strcmp(event_module->name->data, event_core_name.data) == 0)
  983.             {
  984.                 continue;
  985.             }

  986.             module = cycle->modules[i];
  987.             break;
  988.         }
  989.     }

  990.     if (module == NULL) {
  991.         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "no events module found");
  992.         return NGX_CONF_ERROR;
  993.     }

  994.     ngx_conf_init_uint_value(ecf->connections, DEFAULT_CONNECTIONS);
  995.     cycle->connection_n = ecf->connections;

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

  997.     event_module = module->ctx;
  998.     ngx_conf_init_ptr_value(ecf->name, event_module->name->data);

  999.     ngx_conf_init_value(ecf->multi_accept, 0);
  1000.     ngx_conf_init_value(ecf->accept_mutex, 0);
  1001.     ngx_conf_init_msec_value(ecf->accept_mutex_delay, 500);

  1002.     return NGX_CONF_OK;
  1003. }