Annotation of embedaddon/nginx/src/event/ngx_event_accept.c, revision 1.1.1.1

1.1       misho       1: 
                      2: /*
                      3:  * Copyright (C) Igor Sysoev
                      4:  * Copyright (C) Nginx, Inc.
                      5:  */
                      6: 
                      7: 
                      8: #include <ngx_config.h>
                      9: #include <ngx_core.h>
                     10: #include <ngx_event.h>
                     11: 
                     12: 
                     13: static ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle);
                     14: static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle);
                     15: static void ngx_close_accepted_connection(ngx_connection_t *c);
                     16: 
                     17: 
                     18: void
                     19: ngx_event_accept(ngx_event_t *ev)
                     20: {
                     21:     socklen_t          socklen;
                     22:     ngx_err_t          err;
                     23:     ngx_log_t         *log;
                     24:     ngx_uint_t         level;
                     25:     ngx_socket_t       s;
                     26:     ngx_event_t       *rev, *wev;
                     27:     ngx_listening_t   *ls;
                     28:     ngx_connection_t  *c, *lc;
                     29:     ngx_event_conf_t  *ecf;
                     30:     u_char             sa[NGX_SOCKADDRLEN];
                     31: #if (NGX_HAVE_ACCEPT4)
                     32:     static ngx_uint_t  use_accept4 = 1;
                     33: #endif
                     34: 
                     35:     if (ev->timedout) {
                     36:         if (ngx_enable_accept_events((ngx_cycle_t *) ngx_cycle) != NGX_OK) {
                     37:             return;
                     38:         }
                     39: 
                     40:         ev->timedout = 0;
                     41:     }
                     42: 
                     43:     ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
                     44: 
                     45:     if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
                     46:         ev->available = 1;
                     47: 
                     48:     } else if (!(ngx_event_flags & NGX_USE_KQUEUE_EVENT)) {
                     49:         ev->available = ecf->multi_accept;
                     50:     }
                     51: 
                     52:     lc = ev->data;
                     53:     ls = lc->listening;
                     54:     ev->ready = 0;
                     55: 
                     56:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                     57:                    "accept on %V, ready: %d", &ls->addr_text, ev->available);
                     58: 
                     59:     do {
                     60:         socklen = NGX_SOCKADDRLEN;
                     61: 
                     62: #if (NGX_HAVE_ACCEPT4)
                     63:         if (use_accept4) {
                     64:             s = accept4(lc->fd, (struct sockaddr *) sa, &socklen,
                     65:                         SOCK_NONBLOCK);
                     66:         } else {
                     67:             s = accept(lc->fd, (struct sockaddr *) sa, &socklen);
                     68:         }
                     69: #else
                     70:         s = accept(lc->fd, (struct sockaddr *) sa, &socklen);
                     71: #endif
                     72: 
                     73:         if (s == -1) {
                     74:             err = ngx_socket_errno;
                     75: 
                     76:             if (err == NGX_EAGAIN) {
                     77:                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, err,
                     78:                                "accept() not ready");
                     79:                 return;
                     80:             }
                     81: 
                     82:             level = NGX_LOG_ALERT;
                     83: 
                     84:             if (err == NGX_ECONNABORTED) {
                     85:                 level = NGX_LOG_ERR;
                     86: 
                     87:             } else if (err == NGX_EMFILE || err == NGX_ENFILE) {
                     88:                 level = NGX_LOG_CRIT;
                     89:             }
                     90: 
                     91: #if (NGX_HAVE_ACCEPT4)
                     92:             ngx_log_error(level, ev->log, err,
                     93:                           use_accept4 ? "accept4() failed" : "accept() failed");
                     94: 
                     95:             if (use_accept4 && err == NGX_ENOSYS) {
                     96:                 use_accept4 = 0;
                     97:                 ngx_inherited_nonblocking = 0;
                     98:                 continue;
                     99:             }
                    100: #else
                    101:             ngx_log_error(level, ev->log, err, "accept() failed");
                    102: #endif
                    103: 
                    104:             if (err == NGX_ECONNABORTED) {
                    105:                 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
                    106:                     ev->available--;
                    107:                 }
                    108: 
                    109:                 if (ev->available) {
                    110:                     continue;
                    111:                 }
                    112:             }
                    113: 
                    114:             if (err == NGX_EMFILE || err == NGX_ENFILE) {
                    115:                 if (ngx_disable_accept_events((ngx_cycle_t *) ngx_cycle)
                    116:                     != NGX_OK)
                    117:                 {
                    118:                     return;
                    119:                 }
                    120: 
                    121:                 if (ngx_use_accept_mutex) {
                    122:                     if (ngx_accept_mutex_held) {
                    123:                         ngx_shmtx_unlock(&ngx_accept_mutex);
                    124:                         ngx_accept_mutex_held = 0;
                    125:                     }
                    126: 
                    127:                     ngx_accept_disabled = 1;
                    128: 
                    129:                 } else {
                    130:                     ngx_add_timer(ev, ecf->accept_mutex_delay);
                    131:                 }
                    132:             }
                    133: 
                    134:             return;
                    135:         }
                    136: 
                    137: #if (NGX_STAT_STUB)
                    138:         (void) ngx_atomic_fetch_add(ngx_stat_accepted, 1);
                    139: #endif
                    140: 
                    141:         ngx_accept_disabled = ngx_cycle->connection_n / 8
                    142:                               - ngx_cycle->free_connection_n;
                    143: 
                    144:         c = ngx_get_connection(s, ev->log);
                    145: 
                    146:         if (c == NULL) {
                    147:             if (ngx_close_socket(s) == -1) {
                    148:                 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
                    149:                               ngx_close_socket_n " failed");
                    150:             }
                    151: 
                    152:             return;
                    153:         }
                    154: 
                    155: #if (NGX_STAT_STUB)
                    156:         (void) ngx_atomic_fetch_add(ngx_stat_active, 1);
                    157: #endif
                    158: 
                    159:         c->pool = ngx_create_pool(ls->pool_size, ev->log);
                    160:         if (c->pool == NULL) {
                    161:             ngx_close_accepted_connection(c);
                    162:             return;
                    163:         }
                    164: 
                    165:         c->sockaddr = ngx_palloc(c->pool, socklen);
                    166:         if (c->sockaddr == NULL) {
                    167:             ngx_close_accepted_connection(c);
                    168:             return;
                    169:         }
                    170: 
                    171:         ngx_memcpy(c->sockaddr, sa, socklen);
                    172: 
                    173:         log = ngx_palloc(c->pool, sizeof(ngx_log_t));
                    174:         if (log == NULL) {
                    175:             ngx_close_accepted_connection(c);
                    176:             return;
                    177:         }
                    178: 
                    179:         /* set a blocking mode for aio and non-blocking mode for others */
                    180: 
                    181:         if (ngx_inherited_nonblocking) {
                    182:             if (ngx_event_flags & NGX_USE_AIO_EVENT) {
                    183:                 if (ngx_blocking(s) == -1) {
                    184:                     ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
                    185:                                   ngx_blocking_n " failed");
                    186:                     ngx_close_accepted_connection(c);
                    187:                     return;
                    188:                 }
                    189:             }
                    190: 
                    191:         } else {
                    192:             if (!(ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT))) {
                    193:                 if (ngx_nonblocking(s) == -1) {
                    194:                     ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
                    195:                                   ngx_nonblocking_n " failed");
                    196:                     ngx_close_accepted_connection(c);
                    197:                     return;
                    198:                 }
                    199:             }
                    200:         }
                    201: 
                    202:         *log = ls->log;
                    203: 
                    204:         c->recv = ngx_recv;
                    205:         c->send = ngx_send;
                    206:         c->recv_chain = ngx_recv_chain;
                    207:         c->send_chain = ngx_send_chain;
                    208: 
                    209:         c->log = log;
                    210:         c->pool->log = log;
                    211: 
                    212:         c->socklen = socklen;
                    213:         c->listening = ls;
                    214:         c->local_sockaddr = ls->sockaddr;
                    215: 
                    216:         c->unexpected_eof = 1;
                    217: 
                    218: #if (NGX_HAVE_UNIX_DOMAIN)
                    219:         if (c->sockaddr->sa_family == AF_UNIX) {
                    220:             c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
                    221:             c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
                    222: #if (NGX_SOLARIS)
                    223:             /* Solaris's sendfilev() supports AF_NCA, AF_INET, and AF_INET6 */
                    224:             c->sendfile = 0;
                    225: #endif
                    226:         }
                    227: #endif
                    228: 
                    229:         rev = c->read;
                    230:         wev = c->write;
                    231: 
                    232:         wev->ready = 1;
                    233: 
                    234:         if (ngx_event_flags & (NGX_USE_AIO_EVENT|NGX_USE_RTSIG_EVENT)) {
                    235:             /* rtsig, aio, iocp */
                    236:             rev->ready = 1;
                    237:         }
                    238: 
                    239:         if (ev->deferred_accept) {
                    240:             rev->ready = 1;
                    241: #if (NGX_HAVE_KQUEUE)
                    242:             rev->available = 1;
                    243: #endif
                    244:         }
                    245: 
                    246:         rev->log = log;
                    247:         wev->log = log;
                    248: 
                    249:         /*
                    250:          * TODO: MT: - ngx_atomic_fetch_add()
                    251:          *             or protection by critical section or light mutex
                    252:          *
                    253:          * TODO: MP: - allocated in a shared memory
                    254:          *           - ngx_atomic_fetch_add()
                    255:          *             or protection by critical section or light mutex
                    256:          */
                    257: 
                    258:         c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1);
                    259: 
                    260: #if (NGX_STAT_STUB)
                    261:         (void) ngx_atomic_fetch_add(ngx_stat_handled, 1);
                    262: #endif
                    263: 
                    264: #if (NGX_THREADS)
                    265:         rev->lock = &c->lock;
                    266:         wev->lock = &c->lock;
                    267:         rev->own_lock = &c->lock;
                    268:         wev->own_lock = &c->lock;
                    269: #endif
                    270: 
                    271:         if (ls->addr_ntop) {
                    272:             c->addr_text.data = ngx_pnalloc(c->pool, ls->addr_text_max_len);
                    273:             if (c->addr_text.data == NULL) {
                    274:                 ngx_close_accepted_connection(c);
                    275:                 return;
                    276:             }
                    277: 
                    278:             c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->addr_text.data,
                    279:                                              ls->addr_text_max_len, 0);
                    280:             if (c->addr_text.len == 0) {
                    281:                 ngx_close_accepted_connection(c);
                    282:                 return;
                    283:             }
                    284:         }
                    285: 
                    286: #if (NGX_DEBUG)
                    287:         {
                    288: 
                    289:         struct sockaddr_in   *sin;
                    290:         ngx_cidr_t           *cidr;
                    291:         ngx_uint_t            i;
                    292: #if (NGX_HAVE_INET6)
                    293:         struct sockaddr_in6  *sin6;
                    294:         ngx_uint_t            n;
                    295: #endif
                    296: 
                    297:         cidr = ecf->debug_connection.elts;
                    298:         for (i = 0; i < ecf->debug_connection.nelts; i++) {
                    299:             if (cidr[i].family != c->sockaddr->sa_family) {
                    300:                 goto next;
                    301:             }
                    302: 
                    303:             switch (cidr[i].family) {
                    304: 
                    305: #if (NGX_HAVE_INET6)
                    306:             case AF_INET6:
                    307:                 sin6 = (struct sockaddr_in6 *) c->sockaddr;
                    308:                 for (n = 0; n < 16; n++) {
                    309:                     if ((sin6->sin6_addr.s6_addr[n]
                    310:                         & cidr[i].u.in6.mask.s6_addr[n])
                    311:                         != cidr[i].u.in6.addr.s6_addr[n])
                    312:                     {
                    313:                         goto next;
                    314:                     }
                    315:                 }
                    316:                 break;
                    317: #endif
                    318: 
                    319: #if (NGX_HAVE_UNIX_DOMAIN)
                    320:             case AF_UNIX:
                    321:                 break;
                    322: #endif
                    323: 
                    324:             default: /* AF_INET */
                    325:                 sin = (struct sockaddr_in *) c->sockaddr;
                    326:                 if ((sin->sin_addr.s_addr & cidr[i].u.in.mask)
                    327:                     != cidr[i].u.in.addr)
                    328:                 {
                    329:                     goto next;
                    330:                 }
                    331:                 break;
                    332:             }
                    333: 
                    334:             log->log_level = NGX_LOG_DEBUG_CONNECTION|NGX_LOG_DEBUG_ALL;
                    335:             break;
                    336: 
                    337:         next:
                    338:             continue;
                    339:         }
                    340: 
                    341:         }
                    342: #endif
                    343: 
                    344:         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
                    345:                        "*%d accept: %V fd:%d", c->number, &c->addr_text, s);
                    346: 
                    347:         if (ngx_add_conn && (ngx_event_flags & NGX_USE_EPOLL_EVENT) == 0) {
                    348:             if (ngx_add_conn(c) == NGX_ERROR) {
                    349:                 ngx_close_accepted_connection(c);
                    350:                 return;
                    351:             }
                    352:         }
                    353: 
                    354:         log->data = NULL;
                    355:         log->handler = NULL;
                    356: 
                    357:         ls->handler(c);
                    358: 
                    359:         if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
                    360:             ev->available--;
                    361:         }
                    362: 
                    363:     } while (ev->available);
                    364: }
                    365: 
                    366: 
                    367: ngx_int_t
                    368: ngx_trylock_accept_mutex(ngx_cycle_t *cycle)
                    369: {
                    370:     if (ngx_shmtx_trylock(&ngx_accept_mutex)) {
                    371: 
                    372:         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    373:                        "accept mutex locked");
                    374: 
                    375:         if (ngx_accept_mutex_held
                    376:             && ngx_accept_events == 0
                    377:             && !(ngx_event_flags & NGX_USE_RTSIG_EVENT))
                    378:         {
                    379:             return NGX_OK;
                    380:         }
                    381: 
                    382:         if (ngx_enable_accept_events(cycle) == NGX_ERROR) {
                    383:             ngx_shmtx_unlock(&ngx_accept_mutex);
                    384:             return NGX_ERROR;
                    385:         }
                    386: 
                    387:         ngx_accept_events = 0;
                    388:         ngx_accept_mutex_held = 1;
                    389: 
                    390:         return NGX_OK;
                    391:     }
                    392: 
                    393:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    394:                    "accept mutex lock failed: %ui", ngx_accept_mutex_held);
                    395: 
                    396:     if (ngx_accept_mutex_held) {
                    397:         if (ngx_disable_accept_events(cycle) == NGX_ERROR) {
                    398:             return NGX_ERROR;
                    399:         }
                    400: 
                    401:         ngx_accept_mutex_held = 0;
                    402:     }
                    403: 
                    404:     return NGX_OK;
                    405: }
                    406: 
                    407: 
                    408: static ngx_int_t
                    409: ngx_enable_accept_events(ngx_cycle_t *cycle)
                    410: {
                    411:     ngx_uint_t         i;
                    412:     ngx_listening_t   *ls;
                    413:     ngx_connection_t  *c;
                    414: 
                    415:     ls = cycle->listening.elts;
                    416:     for (i = 0; i < cycle->listening.nelts; i++) {
                    417: 
                    418:         c = ls[i].connection;
                    419: 
                    420:         if (c->read->active) {
                    421:             continue;
                    422:         }
                    423: 
                    424:         if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
                    425: 
                    426:             if (ngx_add_conn(c) == NGX_ERROR) {
                    427:                 return NGX_ERROR;
                    428:             }
                    429: 
                    430:         } else {
                    431:             if (ngx_add_event(c->read, NGX_READ_EVENT, 0) == NGX_ERROR) {
                    432:                 return NGX_ERROR;
                    433:             }
                    434:         }
                    435:     }
                    436: 
                    437:     return NGX_OK;
                    438: }
                    439: 
                    440: 
                    441: static ngx_int_t
                    442: ngx_disable_accept_events(ngx_cycle_t *cycle)
                    443: {
                    444:     ngx_uint_t         i;
                    445:     ngx_listening_t   *ls;
                    446:     ngx_connection_t  *c;
                    447: 
                    448:     ls = cycle->listening.elts;
                    449:     for (i = 0; i < cycle->listening.nelts; i++) {
                    450: 
                    451:         c = ls[i].connection;
                    452: 
                    453:         if (!c->read->active) {
                    454:             continue;
                    455:         }
                    456: 
                    457:         if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
                    458:             if (ngx_del_conn(c, NGX_DISABLE_EVENT) == NGX_ERROR) {
                    459:                 return NGX_ERROR;
                    460:             }
                    461: 
                    462:         } else {
                    463:             if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT)
                    464:                 == NGX_ERROR)
                    465:             {
                    466:                 return NGX_ERROR;
                    467:             }
                    468:         }
                    469:     }
                    470: 
                    471:     return NGX_OK;
                    472: }
                    473: 
                    474: 
                    475: static void
                    476: ngx_close_accepted_connection(ngx_connection_t *c)
                    477: {
                    478:     ngx_socket_t  fd;
                    479: 
                    480:     ngx_free_connection(c);
                    481: 
                    482:     fd = c->fd;
                    483:     c->fd = (ngx_socket_t) -1;
                    484: 
                    485:     if (ngx_close_socket(fd) == -1) {
                    486:         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_socket_errno,
                    487:                       ngx_close_socket_n " failed");
                    488:     }
                    489: 
                    490:     if (c->pool) {
                    491:         ngx_destroy_pool(c->pool);
                    492:     }
                    493: 
                    494: #if (NGX_STAT_STUB)
                    495:     (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
                    496: #endif
                    497: }
                    498: 
                    499: 
                    500: u_char *
                    501: ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len)
                    502: {
                    503:     return ngx_snprintf(buf, len, " while accepting new connection on %V",
                    504:                         log->data);
                    505: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>