Annotation of embedaddon/nginx/src/event/ngx_event_accept.c, revision 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>