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>