src/event/ngx_event_accept.c - nginx-1.7.10

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_enable_accept_events(ngx_cycle_t *cycle);
  9. static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle);
  10. static void ngx_close_accepted_connection(ngx_connection_t *c);


  11. void
  12. ngx_event_accept(ngx_event_t *ev)
  13. {
  14.     socklen_t          socklen;
  15.     ngx_err_t          err;
  16.     ngx_log_t         *log;
  17.     ngx_uint_t         level;
  18.     ngx_socket_t       s;
  19.     ngx_event_t       *rev, *wev;
  20.     ngx_listening_t   *ls;
  21.     ngx_connection_t  *c, *lc;
  22.     ngx_event_conf_t  *ecf;
  23.     u_char             sa[NGX_SOCKADDRLEN];
  24. #if (NGX_HAVE_ACCEPT4)
  25.     static ngx_uint_t  use_accept4 = 1;
  26. #endif

  27.     if (ev->timedout) {
  28.         if (ngx_enable_accept_events((ngx_cycle_t *) ngx_cycle) != NGX_OK) {
  29.             return;
  30.         }

  31.         ev->timedout = 0;
  32.     }

  33.     ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);

  34.     if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
  35.         ev->available = 1;

  36.     } else if (!(ngx_event_flags & NGX_USE_KQUEUE_EVENT)) {
  37.         ev->available = ecf->multi_accept;
  38.     }

  39.     lc = ev->data;
  40.     ls = lc->listening;
  41.     ev->ready = 0;

  42.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  43.                    "accept on %V, ready: %d", &ls->addr_text, ev->available);

  44.     do {
  45.         socklen = NGX_SOCKADDRLEN;

  46. #if (NGX_HAVE_ACCEPT4)
  47.         if (use_accept4) {
  48.             s = accept4(lc->fd, (struct sockaddr *) sa, &socklen,
  49.                         SOCK_NONBLOCK);
  50.         } else {
  51.             s = accept(lc->fd, (struct sockaddr *) sa, &socklen);
  52.         }
  53. #else
  54.         s = accept(lc->fd, (struct sockaddr *) sa, &socklen);
  55. #endif

  56.         if (s == (ngx_socket_t) -1) {
  57.             err = ngx_socket_errno;

  58.             if (err == NGX_EAGAIN) {
  59.                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, err,
  60.                                "accept() not ready");
  61.                 return;
  62.             }

  63.             level = NGX_LOG_ALERT;

  64.             if (err == NGX_ECONNABORTED) {
  65.                 level = NGX_LOG_ERR;

  66.             } else if (err == NGX_EMFILE || err == NGX_ENFILE) {
  67.                 level = NGX_LOG_CRIT;
  68.             }

  69. #if (NGX_HAVE_ACCEPT4)
  70.             ngx_log_error(level, ev->log, err,
  71.                           use_accept4 ? "accept4() failed" : "accept() failed");

  72.             if (use_accept4 && err == NGX_ENOSYS) {
  73.                 use_accept4 = 0;
  74.                 ngx_inherited_nonblocking = 0;
  75.                 continue;
  76.             }
  77. #else
  78.             ngx_log_error(level, ev->log, err, "accept() failed");
  79. #endif

  80.             if (err == NGX_ECONNABORTED) {
  81.                 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
  82.                     ev->available--;
  83.                 }

  84.                 if (ev->available) {
  85.                     continue;
  86.                 }
  87.             }

  88.             if (err == NGX_EMFILE || err == NGX_ENFILE) {
  89.                 if (ngx_disable_accept_events((ngx_cycle_t *) ngx_cycle)
  90.                     != NGX_OK)
  91.                 {
  92.                     return;
  93.                 }

  94.                 if (ngx_use_accept_mutex) {
  95.                     if (ngx_accept_mutex_held) {
  96.                         ngx_shmtx_unlock(&ngx_accept_mutex);
  97.                         ngx_accept_mutex_held = 0;
  98.                     }

  99.                     ngx_accept_disabled = 1;

  100.                 } else {
  101.                     ngx_add_timer(ev, ecf->accept_mutex_delay);
  102.                 }
  103.             }

  104.             return;
  105.         }

  106. #if (NGX_STAT_STUB)
  107.         (void) ngx_atomic_fetch_add(ngx_stat_accepted, 1);
  108. #endif

  109.         ngx_accept_disabled = ngx_cycle->connection_n / 8
  110.                               - ngx_cycle->free_connection_n;

  111.         c = ngx_get_connection(s, ev->log);

  112.         if (c == NULL) {
  113.             if (ngx_close_socket(s) == -1) {
  114.                 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
  115.                               ngx_close_socket_n " failed");
  116.             }

  117.             return;
  118.         }

  119. #if (NGX_STAT_STUB)
  120.         (void) ngx_atomic_fetch_add(ngx_stat_active, 1);
  121. #endif

  122.         c->pool = ngx_create_pool(ls->pool_size, ev->log);
  123.         if (c->pool == NULL) {
  124.             ngx_close_accepted_connection(c);
  125.             return;
  126.         }

  127.         c->sockaddr = ngx_palloc(c->pool, socklen);
  128.         if (c->sockaddr == NULL) {
  129.             ngx_close_accepted_connection(c);
  130.             return;
  131.         }

  132.         ngx_memcpy(c->sockaddr, sa, socklen);

  133.         log = ngx_palloc(c->pool, sizeof(ngx_log_t));
  134.         if (log == NULL) {
  135.             ngx_close_accepted_connection(c);
  136.             return;
  137.         }

  138.         /* set a blocking mode for aio and non-blocking mode for others */

  139.         if (ngx_inherited_nonblocking) {
  140.             if (ngx_event_flags & NGX_USE_AIO_EVENT) {
  141.                 if (ngx_blocking(s) == -1) {
  142.                     ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
  143.                                   ngx_blocking_n " failed");
  144.                     ngx_close_accepted_connection(c);
  145.                     return;
  146.                 }
  147.             }

  148.         } else {
  149.             if (!(ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT))) {
  150.                 if (ngx_nonblocking(s) == -1) {
  151.                     ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
  152.                                   ngx_nonblocking_n " failed");
  153.                     ngx_close_accepted_connection(c);
  154.                     return;
  155.                 }
  156.             }
  157.         }

  158.         *log = ls->log;

  159.         c->recv = ngx_recv;
  160.         c->send = ngx_send;
  161.         c->recv_chain = ngx_recv_chain;
  162.         c->send_chain = ngx_send_chain;

  163.         c->log = log;
  164.         c->pool->log = log;

  165.         c->socklen = socklen;
  166.         c->listening = ls;
  167.         c->local_sockaddr = ls->sockaddr;
  168.         c->local_socklen = ls->socklen;

  169.         c->unexpected_eof = 1;

  170. #if (NGX_HAVE_UNIX_DOMAIN)
  171.         if (c->sockaddr->sa_family == AF_UNIX) {
  172.             c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
  173.             c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
  174. #if (NGX_SOLARIS)
  175.             /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */
  176.             c->sendfile = 0;
  177. #endif
  178.         }
  179. #endif

  180.         rev = c->read;
  181.         wev = c->write;

  182.         wev->ready = 1;

  183.         if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) {
  184.             /* rtsig, aio, iocp */
  185.             rev->ready = 1;
  186.         }

  187.         if (ev->deferred_accept) {
  188.             rev->ready = 1;
  189. #if (NGX_HAVE_KQUEUE)
  190.             rev->available = 1;
  191. #endif
  192.         }

  193.         rev->log = log;
  194.         wev->log = log;

  195.         /*
  196.          * TODO: MT: - ngx_atomic_fetch_add()
  197.          *             or protection by critical section or light mutex
  198.          *
  199.          * TODO: MP: - allocated in a shared memory
  200.          *           - ngx_atomic_fetch_add()
  201.          *             or protection by critical section or light mutex
  202.          */

  203.         c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);

  204. #if (NGX_STAT_STUB)
  205.         (void) ngx_atomic_fetch_add(ngx_stat_handled, 1);
  206. #endif

  207.         if (ls->addr_ntop) {
  208.             c->addr_text.data = ngx_pnalloc(c->pool, ls->addr_text_max_len);
  209.             if (c->addr_text.data == NULL) {
  210.                 ngx_close_accepted_connection(c);
  211.                 return;
  212.             }

  213.             c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->socklen,
  214.                                              c->addr_text.data,
  215.                                              ls->addr_text_max_len, 0);
  216.             if (c->addr_text.len == 0) {
  217.                 ngx_close_accepted_connection(c);
  218.                 return;
  219.             }
  220.         }

  221. #if (NGX_DEBUG)
  222.         {

  223.         ngx_str_t             addr;
  224.         struct sockaddr_in   *sin;
  225.         ngx_cidr_t           *cidr;
  226.         ngx_uint_t            i;
  227.         u_char                text[NGX_SOCKADDR_STRLEN];
  228. #if (NGX_HAVE_INET6)
  229.         struct sockaddr_in6  *sin6;
  230.         ngx_uint_t            n;
  231. #endif

  232.         cidr = ecf->debug_connection.elts;
  233.         for (i = 0; i < ecf->debug_connection.nelts; i++) {
  234.             if (cidr[i].family != (ngx_uint_t) c->sockaddr->sa_family) {
  235.                 goto next;
  236.             }

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

  238. #if (NGX_HAVE_INET6)
  239.             case AF_INET6:
  240.                 sin6 = (struct sockaddr_in6 *) c->sockaddr;
  241.                 for (n = 0; n < 16; n++) {
  242.                     if ((sin6->sin6_addr.s6_addr[n]
  243.                         & cidr[i].u.in6.mask.s6_addr[n])
  244.                         != cidr[i].u.in6.addr.s6_addr[n])
  245.                     {
  246.                         goto next;
  247.                     }
  248.                 }
  249.                 break;
  250. #endif

  251. #if (NGX_HAVE_UNIX_DOMAIN)
  252.             case AF_UNIX:
  253.                 break;
  254. #endif

  255.             default: /* AF_INET */
  256.                 sin = (struct sockaddr_in *) c->sockaddr;
  257.                 if ((sin->sin_addr.s_addr & cidr[i].u.in.mask)
  258.                     != cidr[i].u.in.addr)
  259.                 {
  260.                     goto next;
  261.                 }
  262.                 break;
  263.             }

  264.             log->log_level = NGX_LOG_DEBUG_CONNECTION|NGX_LOG_DEBUG_ALL;
  265.             break;

  266.         next:
  267.             continue;
  268.         }

  269.         if (log->log_level & NGX_LOG_DEBUG_EVENT) {
  270.             addr.data = text;
  271.             addr.len = ngx_sock_ntop(c->sockaddr, c->socklen, text,
  272.                                      NGX_SOCKADDR_STRLEN, 1);

  273.             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
  274.                            "*%uA accept: %V fd:%d", c->number, &addr, s);
  275.         }

  276.         }
  277. #endif

  278.         if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
  279.             if (ngx_add_conn(c) == NGX_ERROR) {
  280.                 ngx_close_accepted_connection(c);
  281.                 return;
  282.             }
  283.         }

  284.         log->data = NULL;
  285.         log->handler = NULL;

  286.         ls->handler(c);

  287.         if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
  288.             ev->available--;
  289.         }

  290.     } while (ev->available);
  291. }


  292. ngx_int_t
  293. ngx_trylock_accept_mutex(ngx_cycle_t *cycle)
  294. {
  295.     if (ngx_shmtx_trylock(&ngx_accept_mutex)) {

  296.         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  297.                        "accept mutex locked");

  298.         if (ngx_accept_mutex_held
  299.             && ngx_accept_events == 0
  300.             && !(ngx_event_flags & NGX_USE_RTSIG_EVENT))
  301.         {
  302.             return NGX_OK;
  303.         }

  304.         if (ngx_enable_accept_events(cycle) == NGX_ERROR) {
  305.             ngx_shmtx_unlock(&ngx_accept_mutex);
  306.             return NGX_ERROR;
  307.         }

  308.         ngx_accept_events = 0;
  309.         ngx_accept_mutex_held = 1;

  310.         return NGX_OK;
  311.     }

  312.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  313.                    "accept mutex lock failed: %ui", ngx_accept_mutex_held);

  314.     if (ngx_accept_mutex_held) {
  315.         if (ngx_disable_accept_events(cycle) == NGX_ERROR) {
  316.             return NGX_ERROR;
  317.         }

  318.         ngx_accept_mutex_held = 0;
  319.     }

  320.     return NGX_OK;
  321. }


  322. static ngx_int_t
  323. ngx_enable_accept_events(ngx_cycle_t *cycle)
  324. {
  325.     ngx_uint_t         i;
  326.     ngx_listening_t   *ls;
  327.     ngx_connection_t  *c;

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

  330.         c = ls[i].connection;

  331.         if (c->read->active) {
  332.             continue;
  333.         }

  334.         if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {

  335.             if (ngx_add_conn(c) == NGX_ERROR) {
  336.                 return NGX_ERROR;
  337.             }

  338.         } else {
  339.             if (ngx_add_event(c->read, NGX_READ_EVENT, 0) == NGX_ERROR) {
  340.                 return NGX_ERROR;
  341.             }
  342.         }
  343.     }

  344.     return NGX_OK;
  345. }


  346. static ngx_int_t
  347. ngx_disable_accept_events(ngx_cycle_t *cycle)
  348. {
  349.     ngx_uint_t         i;
  350.     ngx_listening_t   *ls;
  351.     ngx_connection_t  *c;

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

  354.         c = ls[i].connection;

  355.         if (!c->read->active) {
  356.             continue;
  357.         }

  358.         if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
  359.             if (ngx_del_conn(c, NGX_DISABLE_EVENT) == NGX_ERROR) {
  360.                 return NGX_ERROR;
  361.             }

  362.         } else {
  363.             if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT)
  364.                 == NGX_ERROR)
  365.             {
  366.                 return NGX_ERROR;
  367.             }
  368.         }
  369.     }

  370.     return NGX_OK;
  371. }


  372. static void
  373. ngx_close_accepted_connection(ngx_connection_t *c)
  374. {
  375.     ngx_socket_t  fd;

  376.     ngx_free_connection(c);

  377.     fd = c->fd;
  378.     c->fd = (ngx_socket_t) -1;

  379.     if (ngx_close_socket(fd) == -1) {
  380.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
  381.                       ngx_close_socket_n " failed");
  382.     }

  383.     if (c->pool) {
  384.         ngx_destroy_pool(c->pool);
  385.     }

  386. #if (NGX_STAT_STUB)
  387.     (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
  388. #endif
  389. }


  390. u_char *
  391. ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len)
  392. {
  393.     return ngx_snprintf(buf, len, " while accepting new connection on %V",
  394.                         log->data);
  395. }