diff src/core/ngx_connection.c @ 112:408f195b3482 NGINX_0_3_3

nginx 0.3.3 *) Change: the "bl" and "af" parameters of the "listen" directive was renamed to the "backlog" and "accept_filter". *) Feature: the "rcvbuf" and "sndbuf" parameters of the "listen" directive. *) Change: the "$msec" log parameter does not require now the additional the gettimeofday() system call. *) Feature: the -t switch now tests the "listen" directives. *) Bugfix: if the invalid address was specified in the "listen" directive, then after the -HUP signal nginx left an open socket in the CLOSED state. *) Bugfix: the mime type may be incorrectly set to default value for index file with variable in the name; bug appeared in 0.3.0. *) Feature: the "timer_resolution" directive. *) Feature: the millisecond "$upstream_response_time" log parameter. *) Bugfix: a temporary file with client request body now is removed just after the response header was transferred to a client. *) Bugfix: OpenSSL 0.9.6 compatibility. *) Bugfix: the SSL certificate and key file paths could not be relative. *) Bugfix: the "ssl_prefer_server_ciphers" directive did not work in the ngx_imap_ssl_module. *) Bugfix: the "ssl_protocols" directive allowed to specify the single protocol only.
author Igor Sysoev <http://sysoev.ru>
date Wed, 19 Oct 2005 00:00:00 +0400
parents dad2fe8ecf08
children ebca9c35e3a6
line wrap: on
line diff
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -66,13 +66,12 @@ ngx_set_inherited_sockets(ngx_cycle_t *c
     ngx_uint_t                 i;
     ngx_listening_t           *ls;
     struct sockaddr_in        *sin;
+    socklen_t                  olen;
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
     ngx_err_t                  err;
-    socklen_t                  aflen;
     struct accept_filter_arg   af;
 #endif
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
-    socklen_t                  tlen;
     int                        timeout;
 #endif
 
@@ -126,12 +125,38 @@ ngx_set_inherited_sockets(ngx_cycle_t *c
 
         ls[i].backlog = -1;
 
+        olen = sizeof(int);
+
+        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (void *) &ls[i].rcvbuf,
+                       &olen)
+            == -1)
+        {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                          "getsockopt(SO_RCVBUF) %V failed, ignored",
+                          &ls[i].addr_text);
+
+            ls[i].rcvbuf = -1;
+        }
+
+        olen = sizeof(int);
+
+        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, (void *) &ls[i].sndbuf,
+                       &olen)
+            == -1)
+        {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                          "getsockopt(SO_SNDBUF) %V failed, ignored",
+                          &ls[i].addr_text);
+
+            ls[i].sndbuf = -1;
+        }
+
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
 
         ngx_memzero(&af, sizeof(struct accept_filter_arg));
-        aflen = sizeof(struct accept_filter_arg);
+        olen = sizeof(struct accept_filter_arg);
 
-        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &aflen)
+        if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen)
             == -1)
         {
             err = ngx_errno;
@@ -146,7 +171,7 @@ ngx_set_inherited_sockets(ngx_cycle_t *c
             continue;
         }
 
-        if (aflen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') {
+        if (olen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') {
             continue;
         }
 
@@ -162,9 +187,9 @@ ngx_set_inherited_sockets(ngx_cycle_t *c
 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
 
         timeout = 0;
-        tlen = sizeof(int);
+        olen = sizeof(int);
 
-        if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &tlen)
+        if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen)
             == -1)
         {
             ngx_log_error(NGX_LOG_NOTICE, cycle->log, ngx_errno,
@@ -188,7 +213,8 @@ ngx_set_inherited_sockets(ngx_cycle_t *c
 ngx_int_t
 ngx_open_listening_sockets(ngx_cycle_t *cycle)
 {
-    ngx_uint_t        tries, failed, reuseaddr, i;
+    int               reuseaddr;
+    ngx_uint_t        i, tries, failed;
     ngx_err_t         err;
     ngx_log_t        *log;
     ngx_socket_t      s;
@@ -201,9 +227,9 @@ ngx_open_listening_sockets(ngx_cycle_t *
 
     log = cycle->log;
 
-    /* TODO: tries configurable */
+    /* TODO: configurable try number */
 
-    for (tries = /* STUB */ 5; tries; tries--) {
+    for (tries = 5 ; tries; tries--) {
         failed = 0;
 
         /* for each listening socket */
@@ -236,25 +262,19 @@ ngx_open_listening_sockets(ngx_cycle_t *
                 return NGX_ERROR;
             }
 
-#if (NGX_WIN32)
-
-            /*
-             * Winsock assignes a socket number divisible by 4
-             * so to find a connection we divide a socket number by 4.
-             */
-
-            if (s % 4) {
-                ngx_log_error(NGX_LOG_EMERG, log, 0,
-                              ngx_socket_n " created socket %d", s);
-                return NGX_ERROR;
-            }
-#endif
-
             if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
-                           (const void *) &reuseaddr, sizeof(int)) == -1) {
+                           (const void *) &reuseaddr, sizeof(int))
+                == -1)
+            {
                 ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
                               "setsockopt(SO_REUSEADDR) %V failed",
                               &ls[i].addr_text);
+
+                if (ngx_close_socket(s) == -1)
+                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+                                  ngx_close_socket_n " %V failed",
+                                  &ls[i].addr_text);
+
                 return NGX_ERROR;
             }
 
@@ -265,56 +285,54 @@ ngx_open_listening_sockets(ngx_cycle_t *
                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
                                   ngx_nonblocking_n " %V failed",
                                   &ls[i].addr_text);
+
+                    if (ngx_close_socket(s) == -1)
+                        ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
+                                      ngx_close_socket_n " %V failed",
+                                      &ls[i].addr_text);
+
                     return NGX_ERROR;
                 }
             }
 
-#if 0
-            if (ls[i].nonblocking) {
-                if (ngx_nonblocking(s) == -1) {
-                    ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
-                                  ngx_nonblocking_n " %V failed",
-                                  &ls[i].addr_text);
-                    return NGX_ERROR;
-                }
-            }
-#endif
-
             if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) {
                 err = ngx_socket_errno;
+
+                if (err == NGX_EADDRINUSE && ngx_test_config) {
+                    continue;
+                }
+
                 ngx_log_error(NGX_LOG_EMERG, log, err,
                               "bind() to %V failed", &ls[i].addr_text);
 
-                if (err != NGX_EADDRINUSE)
-                    return NGX_ERROR;
-
                 if (ngx_close_socket(s) == -1)
                     ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
                                   ngx_close_socket_n " %V failed",
                                   &ls[i].addr_text);
 
+                if (err != NGX_EADDRINUSE) {
+                    return NGX_ERROR;
+                }
+
                 failed = 1;
+
                 continue;
             }
 
-            if (listen(s, ls[i].backlog) == -1) {
-                ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno,
-                              "listen() to %V failed", &ls[i].addr_text);
-                return NGX_ERROR;
-            }
-
-            /* TODO: deferred accept */
+            ls[i].listen = 1;
 
             ls[i].fd = s;
         }
 
-        if (!failed)
+        if (!failed) {
             break;
+        }
 
         /* TODO: delay configurable */
 
         ngx_log_error(NGX_LOG_NOTICE, log, 0,
                       "try again to bind() after 500ms");
+
         ngx_msleep(500);
     }
 
@@ -328,6 +346,143 @@ ngx_open_listening_sockets(ngx_cycle_t *
 
 
 void
+ngx_configure_listening_socket(ngx_cycle_t *cycle)
+{
+    ngx_uint_t                 i;
+    ngx_listening_t           *ls;
+
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
+    struct accept_filter_arg   af;
+#endif
+#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
+    int                        timeout;
+#endif
+
+    ls = cycle->listening.elts;
+    for (i = 0; i < cycle->listening.nelts; i++) {
+
+        if (ls[i].rcvbuf != -1) {
+            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF,
+                           (const void *) &ls[i].rcvbuf, sizeof(int))
+                == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                              "setsockopt(SO_RCVBUF) %V failed, ignored",
+                              &ls[i].addr_text);
+                return;
+            }
+        }
+
+        if (ls[i].sndbuf != -1) {
+            if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF,
+                           (const void *) &ls[i].sndbuf, sizeof(int))
+                == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                              "setsockopt(SO_SNDBUF) %V failed, ignored",
+                              &ls[i].addr_text);
+                return;
+            }
+        }
+
+        if (ls[i].listen) {
+            if (listen(ls[i].fd, ls[i].backlog) == -1) {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
+                              "changing the listen() backlog to %d "
+                              "for %V failed, ignored",
+                              &ls[i].addr_text, ls[i].backlog);
+            }
+        }
+
+        /*
+         * setting deferred mode should be last operation on socket,
+         * because code may prematurely continue cycle on failure
+         */
+
+#if (NGX_HAVE_DEFERRED_ACCEPT)
+
+#ifdef SO_ACCEPTFILTER
+
+        if (ls->delete_deferred) {
+            if (setsockopt(ls->fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0) == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                              "setsockopt(SO_ACCEPTFILTER, NULL) "
+                              "for %V failed, ignored",
+                              &ls->addr_text);
+
+                if (ls->accept_filter) {
+                    ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+                                  "could not change the accept filter "
+                                  "to \"%s\" for %V, ignored",
+                                  ls->accept_filter, &ls->addr_text);
+                }
+
+                continue;
+            }
+
+            ls->deferred_accept = 0;
+        }
+
+        if (ls->add_deferred) {
+            ngx_memzero(&af, sizeof(struct accept_filter_arg));
+            (void) ngx_cpystrn((u_char *) af.af_name,
+                               (u_char *) ls->accept_filter, 16);
+
+            if (setsockopt(ls->fd, SOL_SOCKET, SO_ACCEPTFILTER,
+                           &af, sizeof(struct accept_filter_arg))
+                == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                              "setsockopt(SO_ACCEPTFILTER, \"%s\") "
+                              " for %V failed, ignored",
+                              ls->accept_filter, &ls->addr_text);
+                continue;
+            }
+
+            ls->deferred_accept = 1;
+        }
+
+#endif
+
+#ifdef TCP_DEFER_ACCEPT
+
+        if (ls->add_deferred || ls->delete_deferred) {
+
+            if (ls->add_deferred) {
+                timeout = (int) (ls->post_accept_timeout / 1000);
+
+            } else {
+                timeout = 0;
+            }
+
+            if (setsockopt(ls->fd, IPPROTO_TCP, TCP_DEFER_ACCEPT,
+                           &timeout, sizeof(int))
+                == -1)
+            {
+                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                              "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, "
+                              "ignored",
+                              timeout, &ls->addr_text);
+
+                continue;
+            }
+        }
+
+        if (ls->add_deferred) { 
+            ls->deferred_accept = 1;
+        }
+
+#endif
+
+#endif /* NGX_HAVE_DEFERRED_ACCEPT */
+    }
+
+    return;
+}
+
+
+void
 ngx_close_listening_sockets(ngx_cycle_t *cycle)
 {
     ngx_uint_t         i;
@@ -361,6 +516,9 @@ ngx_close_listening_sockets(ngx_cycle_t 
 
         c->fd = (ngx_socket_t) -1;
 
+        ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
+                       "close listening %V #%d ", &ls[i].addr_text, ls[i].fd);
+
         if (ngx_close_socket(ls[i].fd) == -1) {
             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno,
                           ngx_close_socket_n " %V failed", &ls[i].addr_text);
@@ -495,27 +653,26 @@ ngx_close_connection(ngx_connection_t *c
      * before we clean the connection
      */
 
-    if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_OK) {
+    ngx_mutex_lock(ngx_posted_events_mutex);
 
-        if (c->read->prev) {
-            ngx_delete_posted_event(c->read);
-        }
+    if (c->read->prev) {
+        ngx_delete_posted_event(c->read);
+    }
 
-        if (c->write->prev) {
-            ngx_delete_posted_event(c->write);
-        }
+    if (c->write->prev) {
+        ngx_delete_posted_event(c->write);
+    }
 
-        c->read->closed = 1;
-        c->write->closed = 1;
+    c->read->closed = 1;
+    c->write->closed = 1;
 
-        if (c->single_connection) {
-            ngx_unlock(&c->lock);
-            c->read->locked = 0;
-            c->write->locked = 0;
-        }
+    if (c->single_connection) {
+        ngx_unlock(&c->lock);
+        c->read->locked = 0;
+        c->write->locked = 0;
+    }
 
-        ngx_mutex_unlock(ngx_posted_events_mutex);
-    }
+    ngx_mutex_unlock(ngx_posted_events_mutex);
 
 #else