Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.19.2 ]​[ nginx-1.18.0 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 
0012 
0013 static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all);
0014 static void ngx_close_accepted_connection(ngx_connection_t *c);
0015 
0016 
0017 void
0018 ngx_event_accept(ngx_event_t *ev)
0019 {
0020     socklen_t          socklen;
0021     ngx_err_t          err;
0022     ngx_log_t         *log;
0023     ngx_uint_t         level;
0024     ngx_socket_t       s;
0025     ngx_event_t       *rev, *wev;
0026     ngx_sockaddr_t     sa;
0027     ngx_listening_t   *ls;
0028     ngx_connection_t  *c, *lc;
0029     ngx_event_conf_t  *ecf;
0030 #if (NGX_HAVE_ACCEPT4)
0031     static ngx_uint_t  use_accept4 = 1;
0032 #endif
0033 
0034     if (ev->timedout) {
0035         if (ngx_enable_accept_events((ngx_cycle_t *) ngx_cycle) != NGX_OK) {
0036             return;
0037         }
0038 
0039         ev->timedout = 0;
0040     }
0041 
0042     ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
0043 
0044     if (!(ngx_event_flags & NGX_USE_KQUEUE_EVENT)) {
0045         ev->available = ecf->multi_accept;
0046     }
0047 
0048     lc = ev->data;
0049     ls = lc->listening;
0050     ev->ready = 0;
0051 
0052     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0053                    "accept on %V, ready: %d", &ls->addr_text, ev->available);
0054 
0055     do {
0056         socklen = sizeof(ngx_sockaddr_t);
0057 
0058 #if (NGX_HAVE_ACCEPT4)
0059         if (use_accept4) {
0060             s = accept4(lc->fd, &sa.sockaddr, &socklen, SOCK_NONBLOCK);
0061         } else {
0062             s = accept(lc->fd, &sa.sockaddr, &socklen);
0063         }
0064 #else
0065         s = accept(lc->fd, &sa.sockaddr, &socklen);
0066 #endif
0067 
0068         if (s == (ngx_socket_t) -1) {
0069             err = ngx_socket_errno;
0070 
0071             if (err == NGX_EAGAIN) {
0072                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, err,
0073                                "accept() not ready");
0074                 return;
0075             }
0076 
0077             level = NGX_LOG_ALERT;
0078 
0079             if (err == NGX_ECONNABORTED) {
0080                 level = NGX_LOG_ERR;
0081 
0082             } else if (err == NGX_EMFILE || err == NGX_ENFILE) {
0083                 level = NGX_LOG_CRIT;
0084             }
0085 
0086 #if (NGX_HAVE_ACCEPT4)
0087             ngx_log_error(level, ev->log, err,
0088                           use_accept4 ? "accept4() failed" : "accept() failed");
0089 
0090             if (use_accept4 && err == NGX_ENOSYS) {
0091                 use_accept4 = 0;
0092                 ngx_inherited_nonblocking = 0;
0093                 continue;
0094             }
0095 #else
0096             ngx_log_error(level, ev->log, err, "accept() failed");
0097 #endif
0098 
0099             if (err == NGX_ECONNABORTED) {
0100                 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
0101                     ev->available--;
0102                 }
0103 
0104                 if (ev->available) {
0105                     continue;
0106                 }
0107             }
0108 
0109             if (err == NGX_EMFILE || err == NGX_ENFILE) {
0110                 if (ngx_disable_accept_events((ngx_cycle_t *) ngx_cycle, 1)
0111                     != NGX_OK)
0112                 {
0113                     return;
0114                 }
0115 
0116                 if (ngx_use_accept_mutex) {
0117                     if (ngx_accept_mutex_held) {
0118                         ngx_shmtx_unlock(&ngx_accept_mutex);
0119                         ngx_accept_mutex_held = 0;
0120                     }
0121 
0122                     ngx_accept_disabled = 1;
0123 
0124                 } else {
0125                     ngx_add_timer(ev, ecf->accept_mutex_delay);
0126                 }
0127             }
0128 
0129             return;
0130         }
0131 
0132 #if (NGX_STAT_STUB)
0133         (void) ngx_atomic_fetch_add(ngx_stat_accepted, 1);
0134 #endif
0135 
0136         ngx_accept_disabled = ngx_cycle->connection_n / 8
0137                               - ngx_cycle->free_connection_n;
0138 
0139         c = ngx_get_connection(s, ev->log);
0140 
0141         if (c == NULL) {
0142             if (ngx_close_socket(s) == -1) {
0143                 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
0144                               ngx_close_socket_n " failed");
0145             }
0146 
0147             return;
0148         }
0149 
0150         c->type = SOCK_STREAM;
0151 
0152 #if (NGX_STAT_STUB)
0153         (void) ngx_atomic_fetch_add(ngx_stat_active, 1);
0154 #endif
0155 
0156         c->pool = ngx_create_pool(ls->pool_size, ev->log);
0157         if (c->pool == NULL) {
0158             ngx_close_accepted_connection(c);
0159             return;
0160         }
0161 
0162         if (socklen > (socklen_t) sizeof(ngx_sockaddr_t)) {
0163             socklen = sizeof(ngx_sockaddr_t);
0164         }
0165 
0166         c->sockaddr = ngx_palloc(c->pool, socklen);
0167         if (c->sockaddr == NULL) {
0168             ngx_close_accepted_connection(c);
0169             return;
0170         }
0171 
0172         ngx_memcpy(c->sockaddr, &sa, socklen);
0173 
0174         log = ngx_palloc(c->pool, sizeof(ngx_log_t));
0175         if (log == NULL) {
0176             ngx_close_accepted_connection(c);
0177             return;
0178         }
0179 
0180         /* set a blocking mode for iocp and non-blocking mode for others */
0181 
0182         if (ngx_inherited_nonblocking) {
0183             if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
0184                 if (ngx_blocking(s) == -1) {
0185                     ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
0186                                   ngx_blocking_n " failed");
0187                     ngx_close_accepted_connection(c);
0188                     return;
0189                 }
0190             }
0191 
0192         } else {
0193             if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
0194                 if (ngx_nonblocking(s) == -1) {
0195                     ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
0196                                   ngx_nonblocking_n " failed");
0197                     ngx_close_accepted_connection(c);
0198                     return;
0199                 }
0200             }
0201         }
0202 
0203         *log = ls->log;
0204 
0205         c->recv = ngx_recv;
0206         c->send = ngx_send;
0207         c->recv_chain = ngx_recv_chain;
0208         c->send_chain = ngx_send_chain;
0209 
0210         c->log = log;
0211         c->pool->log = log;
0212 
0213         c->socklen = socklen;
0214         c->listening = ls;
0215         c->local_sockaddr = ls->sockaddr;
0216         c->local_socklen = ls->socklen;
0217 
0218 #if (NGX_HAVE_UNIX_DOMAIN)
0219         if (c->sockaddr->sa_family == AF_UNIX) {
0220             c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
0221             c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
0222 #if (NGX_SOLARIS)
0223             /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */
0224             c->sendfile = 0;
0225 #endif
0226         }
0227 #endif
0228 
0229         rev = c->read;
0230         wev = c->write;
0231 
0232         wev->ready = 1;
0233 
0234         if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
0235             rev->ready = 1;
0236         }
0237 
0238         if (ev->deferred_accept) {
0239             rev->ready = 1;
0240 #if (NGX_HAVE_KQUEUE || NGX_HAVE_EPOLLRDHUP)
0241             rev->available = 1;
0242 #endif
0243         }
0244 
0245         rev->log = log;
0246         wev->log = log;
0247 
0248         /*
0249          * TODO: MT: - ngx_atomic_fetch_add()
0250          *             or protection by critical section or light mutex
0251          *
0252          * TODO: MP: - allocated in a shared memory
0253          *           - ngx_atomic_fetch_add()
0254          *             or protection by critical section or light mutex
0255          */
0256 
0257         c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
0258 
0259 #if (NGX_STAT_STUB)
0260         (void) ngx_atomic_fetch_add(ngx_stat_handled, 1);
0261 #endif
0262 
0263         if (ls->addr_ntop) {
0264             c->addr_text.data = ngx_pnalloc(c->pool, ls->addr_text_max_len);
0265             if (c->addr_text.data == NULL) {
0266                 ngx_close_accepted_connection(c);
0267                 return;
0268             }
0269 
0270             c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->socklen,
0271                                              c->addr_text.data,
0272                                              ls->addr_text_max_len, 0);
0273             if (c->addr_text.len == 0) {
0274                 ngx_close_accepted_connection(c);
0275                 return;
0276             }
0277         }
0278 
0279 #if (NGX_DEBUG)
0280         {
0281         ngx_str_t  addr;
0282         u_char     text[NGX_SOCKADDR_STRLEN];
0283 
0284         ngx_debug_accepted_connection(ecf, c);
0285 
0286         if (log->log_level & NGX_LOG_DEBUG_EVENT) {
0287             addr.data = text;
0288             addr.len = ngx_sock_ntop(c->sockaddr, c->socklen, text,
0289                                      NGX_SOCKADDR_STRLEN, 1);
0290 
0291             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
0292                            "*%uA accept: %V fd:%d", c->number, &addr, s);
0293         }
0294 
0295         }
0296 #endif
0297 
0298         if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
0299             if (ngx_add_conn(c) == NGX_ERROR) {
0300                 ngx_close_accepted_connection(c);
0301                 return;
0302             }
0303         }
0304 
0305         log->data = NULL;
0306         log->handler = NULL;
0307 
0308         ls->handler(c);
0309 
0310         if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
0311             ev->available--;
0312         }
0313 
0314     } while (ev->available);
0315 }
0316 
0317 
0318 ngx_int_t
0319 ngx_trylock_accept_mutex(ngx_cycle_t *cycle)
0320 {
0321     if (ngx_shmtx_trylock(&ngx_accept_mutex)) {
0322 
0323         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0324                        "accept mutex locked");
0325 
0326         if (ngx_accept_mutex_held && ngx_accept_events == 0) {
0327             return NGX_OK;
0328         }
0329 
0330         if (ngx_enable_accept_events(cycle) == NGX_ERROR) {
0331             ngx_shmtx_unlock(&ngx_accept_mutex);
0332             return NGX_ERROR;
0333         }
0334 
0335         ngx_accept_events = 0;
0336         ngx_accept_mutex_held = 1;
0337 
0338         return NGX_OK;
0339     }
0340 
0341     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0342                    "accept mutex lock failed: %ui", ngx_accept_mutex_held);
0343 
0344     if (ngx_accept_mutex_held) {
0345         if (ngx_disable_accept_events(cycle, 0) == NGX_ERROR) {
0346             return NGX_ERROR;
0347         }
0348 
0349         ngx_accept_mutex_held = 0;
0350     }
0351 
0352     return NGX_OK;
0353 }
0354 
0355 
0356 ngx_int_t
0357 ngx_enable_accept_events(ngx_cycle_t *cycle)
0358 {
0359     ngx_uint_t         i;
0360     ngx_listening_t   *ls;
0361     ngx_connection_t  *c;
0362 
0363     ls = cycle->listening.elts;
0364     for (i = 0; i < cycle->listening.nelts; i++) {
0365 
0366         c = ls[i].connection;
0367 
0368         if (c == NULL || c->read->active) {
0369             continue;
0370         }
0371 
0372         if (ngx_add_event(c->read, NGX_READ_EVENT, 0) == NGX_ERROR) {
0373             return NGX_ERROR;
0374         }
0375     }
0376 
0377     return NGX_OK;
0378 }
0379 
0380 
0381 static ngx_int_t
0382 ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all)
0383 {
0384     ngx_uint_t         i;
0385     ngx_listening_t   *ls;
0386     ngx_connection_t  *c;
0387 
0388     ls = cycle->listening.elts;
0389     for (i = 0; i < cycle->listening.nelts; i++) {
0390 
0391         c = ls[i].connection;
0392 
0393         if (c == NULL || !c->read->active) {
0394             continue;
0395         }
0396 
0397 #if (NGX_HAVE_REUSEPORT)
0398 
0399         /*
0400          * do not disable accept on worker's own sockets
0401          * when disabling accept events due to accept mutex
0402          */
0403 
0404         if (ls[i].reuseport && !all) {
0405             continue;
0406         }
0407 
0408 #endif
0409 
0410         if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT)
0411             == NGX_ERROR)
0412         {
0413             return NGX_ERROR;
0414         }
0415     }
0416 
0417     return NGX_OK;
0418 }
0419 
0420 
0421 static void
0422 ngx_close_accepted_connection(ngx_connection_t *c)
0423 {
0424     ngx_socket_t  fd;
0425 
0426     ngx_free_connection(c);
0427 
0428     fd = c->fd;
0429     c->fd = (ngx_socket_t) -1;
0430 
0431     if (ngx_close_socket(fd) == -1) {
0432         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
0433                       ngx_close_socket_n " failed");
0434     }
0435 
0436     if (c->pool) {
0437         ngx_destroy_pool(c->pool);
0438     }
0439 
0440 #if (NGX_STAT_STUB)
0441     (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
0442 #endif
0443 }
0444 
0445 
0446 u_char *
0447 ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len)
0448 {
0449     return ngx_snprintf(buf, len, " while accepting new connection on %V",
0450                         log->data);
0451 }
0452 
0453 
0454 #if (NGX_DEBUG)
0455 
0456 void
0457 ngx_debug_accepted_connection(ngx_event_conf_t *ecf, ngx_connection_t *c)
0458 {
0459     struct sockaddr_in   *sin;
0460     ngx_cidr_t           *cidr;
0461     ngx_uint_t            i;
0462 #if (NGX_HAVE_INET6)
0463     struct sockaddr_in6  *sin6;
0464     ngx_uint_t            n;
0465 #endif
0466 
0467     cidr = ecf->debug_connection.elts;
0468     for (i = 0; i < ecf->debug_connection.nelts; i++) {
0469         if (cidr[i].family != (ngx_uint_t) c->sockaddr->sa_family) {
0470             goto next;
0471         }
0472 
0473         switch (cidr[i].family) {
0474 
0475 #if (NGX_HAVE_INET6)
0476         case AF_INET6:
0477             sin6 = (struct sockaddr_in6 *) c->sockaddr;
0478             for (n = 0; n < 16; n++) {
0479                 if ((sin6->sin6_addr.s6_addr[n]
0480                     & cidr[i].u.in6.mask.s6_addr[n])
0481                     != cidr[i].u.in6.addr.s6_addr[n])
0482                 {
0483                     goto next;
0484                 }
0485             }
0486             break;
0487 #endif
0488 
0489 #if (NGX_HAVE_UNIX_DOMAIN)
0490         case AF_UNIX:
0491             break;
0492 #endif
0493 
0494         default: /* AF_INET */
0495             sin = (struct sockaddr_in *) c->sockaddr;
0496             if ((sin->sin_addr.s_addr & cidr[i].u.in.mask)
0497                 != cidr[i].u.in.addr)
0498             {
0499                 goto next;
0500             }
0501             break;
0502         }
0503 
0504         c->log->log_level = NGX_LOG_DEBUG_CONNECTION|NGX_LOG_DEBUG_ALL;
0505         break;
0506 
0507     next:
0508         continue;
0509     }
0510 }
0511 
0512 #endif