Mercurial > hg > nginx-mail
diff src/core/ngx_connection.c @ 665:0b460e61bdcd default tip
Merge with nginx 1.0.0.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Apr 2011 04:22:17 +0400 |
parents | b9763778e212 |
children |
line wrap: on
line diff
--- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -12,9 +12,13 @@ ngx_os_io_t ngx_io; +static void ngx_drain_connections(void); + + ngx_listening_t * ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen) { + size_t len; ngx_listening_t *ls; struct sockaddr *sa; u_char text[NGX_SOCKADDR_STRLEN]; @@ -36,17 +40,8 @@ ngx_create_listening(ngx_conf_t *cf, voi ls->sockaddr = sa; ls->socklen = socklen; - ls->addr_text.len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1); - - ls->addr_text.data = ngx_pnalloc(cf->pool, ls->addr_text.len); - if (ls->addr_text.data == NULL) { - return NULL; - } - - ngx_memcpy(ls->addr_text.data, text, ls->addr_text.len); - - ls->fd = (ngx_socket_t) -1; - ls->type = SOCK_STREAM; + len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1); + ls->addr_text.len = len; switch (ls->sockaddr->sa_family) { #if (NGX_HAVE_INET6) @@ -54,6 +49,12 @@ ngx_create_listening(ngx_conf_t *cf, voi ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN; break; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN; + len++; + break; +#endif case AF_INET: ls->addr_text_max_len = NGX_INET_ADDRSTRLEN; break; @@ -62,10 +63,24 @@ ngx_create_listening(ngx_conf_t *cf, voi break; } + ls->addr_text.data = ngx_pnalloc(cf->pool, len); + if (ls->addr_text.data == NULL) { + return NULL; + } + + ngx_memcpy(ls->addr_text.data, text, len); + + ls->fd = (ngx_socket_t) -1; + ls->type = SOCK_STREAM; + ls->backlog = NGX_LISTEN_BACKLOG; ls->rcvbuf = -1; ls->sndbuf = -1; +#if (NGX_HAVE_SETFIB) + ls->setfib = -1; +#endif + return ls; } @@ -88,14 +103,12 @@ ngx_set_inherited_sockets(ngx_cycle_t *c ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { - /* AF_INET only */ - - ls[i].sockaddr = ngx_palloc(cycle->pool, sizeof(struct sockaddr_in)); + ls[i].sockaddr = ngx_palloc(cycle->pool, NGX_SOCKADDRLEN); if (ls[i].sockaddr == NULL) { return NGX_ERROR; } - ls[i].socklen = sizeof(struct sockaddr_in); + ls[i].socklen = NGX_SOCKADDRLEN; if (getsockname(ls[i].fd, ls[i].sockaddr, &ls[i].socklen) == -1) { ngx_log_error(NGX_LOG_CRIT, cycle->log, ngx_socket_errno, "getsockname() of the inherited " @@ -109,11 +122,20 @@ ngx_set_inherited_sockets(ngx_cycle_t *c #if (NGX_HAVE_INET6) case AF_INET6: ls[i].addr_text_max_len = NGX_INET6_ADDRSTRLEN; + len = NGX_INET6_ADDRSTRLEN + sizeof(":65535") - 1; + break; +#endif + +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + ls[i].addr_text_max_len = NGX_UNIX_ADDRSTRLEN; + len = NGX_UNIX_ADDRSTRLEN; break; #endif case AF_INET: ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN; + len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1; break; default: @@ -124,8 +146,6 @@ ngx_set_inherited_sockets(ngx_cycle_t *c continue; } - len = ls[i].addr_text_max_len + sizeof(":65535") - 1; - ls[i].addr_text.data = ngx_pnalloc(cycle->pool, len); if (ls[i].addr_text.data == NULL) { return NGX_ERROR; @@ -166,6 +186,25 @@ ngx_set_inherited_sockets(ngx_cycle_t *c ls[i].sndbuf = -1; } +#if 0 + /* SO_SETFIB is currently a set only option */ + +#if (NGX_HAVE_SETFIB) + + if (getsockopt(ls[i].setfib, SOL_SOCKET, SO_SETFIB, + (void *) &ls[i].setfib, &olen) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "getsockopt(SO_SETFIB) %V failed, ignored", + &ls[i].addr_text); + + ls[i].setfib = -1; + } + +#endif +#endif + #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) ngx_memzero(&af, sizeof(struct accept_filter_arg)); @@ -357,6 +396,29 @@ ngx_open_listening_sockets(ngx_cycle_t * continue; } +#if (NGX_HAVE_UNIX_DOMAIN) + + if (ls[i].sockaddr->sa_family == AF_UNIX) { + mode_t mode; + u_char *name; + + name = ls[i].addr_text.data + sizeof("unix:") - 1; + mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); + + if (chmod((char *) name, mode) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "chmod() \"%s\" failed", name); + } + + if (ngx_test_config) { + if (ngx_delete_file(name) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + ngx_delete_file_n " %s failed", name); + } + } + } +#endif + if (listen(s, ls[i].backlog) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, "listen() to %V, backlog %d failed", @@ -437,6 +499,19 @@ ngx_configure_listening_sockets(ngx_cycl } } +#if (NGX_HAVE_SETFIB) + if (ls[i].setfib != -1) { + if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SETFIB, + (const void *) &ls[i].setfib, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(SO_SETFIB, %d) %V failed, ignored", + ls[i].setfib, &ls[i].addr_text); + } + } +#endif + #if 0 if (1) { int tcp_nodelay = 1; @@ -604,6 +679,22 @@ ngx_close_listening_sockets(ngx_cycle_t ngx_close_socket_n " %V failed", &ls[i].addr_text); } +#if (NGX_HAVE_UNIX_DOMAIN) + + if (ls[i].sockaddr->sa_family == AF_UNIX + && ngx_process <= NGX_PROCESS_MASTER + && ngx_new_binary == 0) + { + u_char *name = ls[i].addr_text.data + sizeof("unix:") - 1; + + if (ngx_delete_file(name) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, + ngx_delete_file_n " %s failed", name); + } + } + +#endif + ls[i].fd = (ngx_socket_t) -1; } } @@ -631,6 +722,11 @@ ngx_get_connection(ngx_socket_t s, ngx_l c = ngx_cycle->free_connections; if (c == NULL) { + ngx_drain_connections(); + c = ngx_cycle->free_connections; + } + + if (c == NULL) { ngx_log_error(NGX_LOG_ALERT, log, 0, "%ui worker_connections are not enough", ngx_cycle->connection_n); @@ -773,6 +869,8 @@ ngx_close_connection(ngx_connection_t *c #endif + ngx_reusable_connection(c, 0); + log_error = c->log_error; ngx_free_connection(c); @@ -812,6 +910,51 @@ ngx_close_connection(ngx_connection_t *c } +void +ngx_reusable_connection(ngx_connection_t *c, ngx_uint_t reusable) +{ + ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0, + "reusable connection: %ui", reusable); + + if (c->reusable) { + ngx_queue_remove(&c->queue); + } + + c->reusable = reusable; + + if (reusable) { + /* need cast as ngx_cycle is volatile */ + + ngx_queue_insert_head( + (ngx_queue_t *) &ngx_cycle->reusable_connections_queue, &c->queue); + } +} + + +static void +ngx_drain_connections(void) +{ + ngx_int_t i; + ngx_queue_t *q; + ngx_connection_t *c; + + for (i = 0; i < 32; i++) { + if (ngx_queue_empty(&ngx_cycle->reusable_connections_queue)) { + break; + } + + q = ngx_queue_last(&ngx_cycle->reusable_connections_queue); + c = ngx_queue_data(q, ngx_connection_t, queue); + + ngx_log_debug0(NGX_LOG_DEBUG_CORE, c->log, 0, + "reusing connection"); + + c->close = 1; + c->read->handler(c->read); + } +} + + ngx_int_t ngx_connection_local_sockaddr(ngx_connection_t *c, ngx_str_t *s, ngx_uint_t port) @@ -858,7 +1001,6 @@ ngx_connection_local_sockaddr(ngx_connec return NGX_ERROR; } - c->local_socklen = len; ngx_memcpy(c->local_sockaddr, &sa, len); } @@ -917,12 +1059,8 @@ ngx_connection_error(ngx_connection_t *c level = NGX_LOG_INFO; break; - case NGX_ERROR_ERR: + default: level = NGX_LOG_ERR; - break; - - default: - level = NGX_LOG_ALERT; } } else {