changeset 330:5e3b425174f6 NGINX_0_6_9

nginx 0.6.9 *) Bugfix: a worker process may got caught in an endless loop, if the HTTPS protocol was used; bug appeared in 0.6.7. *) Bugfix: if server listened on two addresses or ports and trailing wildcard was used, then nginx did not run. *) Bugfix: the "ip_hash" directive might incorrectly mark servers as down. *) Bugfix: nginx could not be built on amd64; bug appeared in 0.6.8.
author Igor Sysoev <http://sysoev.ru>
date Tue, 28 Aug 2007 00:00:00 +0400
parents f2f8dc3e7933
children b69d5e83bf82
files CHANGES CHANGES.ru conf/mime.types src/core/nginx.h src/core/ngx_hash.c src/event/ngx_event_openssl.c src/http/modules/ngx_http_upstream_ip_hash_module.c src/http/modules/perl/nginx.pm src/http/ngx_http_request.c src/http/ngx_http_request_body.c src/http/ngx_http_upstream_round_robin.c src/http/ngx_http_write_filter_module.c
diffstat 12 files changed, 131 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,18 @@
 
+Changes with nginx 0.6.9                                         28 Aug 2007
+
+    *) Bugfix: a worker process may got caught in an endless loop, if the 
+       HTTPS protocol was used; bug appeared in 0.6.7.
+
+    *) Bugfix: if server listened on two addresses or ports and trailing 
+       wildcard was used, then nginx did not run.
+
+    *) Bugfix: the "ip_hash" directive might incorrectly mark servers as 
+       down.
+
+    *) Bugfix: nginx could not be built on amd64; bug appeared in 0.6.8.
+
+
 Changes with nginx 0.6.8                                         20 Aug 2007
 
     *) Change: now nginx tries to set the "worker_priority", 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,18 @@
 
+Изменения в nginx 0.6.9                                           28.08.2007
+
+    *) Исправление: рабочий процесс мог зациклиться при использовании 
+       протокола HTTPS; ошибка появилась в 0.6.7.
+
+    *) Исправление: если сервер слушал на двух адресах или портах, то nginx 
+       не запускался при использовании wildcard в конце имени сервера.
+
+    *) Исправление: директива ip_hash могла неверно помечать сервера как 
+       нерабочие.
+
+    *) Исправление: nginx не собирался на amd64; ошибка появилась в 0.6.8.
+
+
 Изменения в nginx 0.6.8                                           20.08.2007
 
     *) Изменение: теперь nginx пытается установить директивы 
--- a/conf/mime.types
+++ b/conf/mime.types
@@ -20,6 +20,7 @@ types {
     image/x-icon                          ico;
     image/x-jng                           jng;
     image/x-ms-bmp                        bmp;
+    image/svg+xml                         svg;
 
     application/java-archive              jar war ear;
     application/mac-binhex40              hqx;
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VERSION      "0.6.8"
+#define NGINX_VERSION      "0.6.9"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_hash.c
+++ b/src/core/ngx_hash.c
@@ -889,10 +889,15 @@ wildcard:
 
         /* convert "www.example.*" to "www.example\0" */
 
-        p = key->data;
-        key->data[last] = '\0';
         last++;
 
+        p = ngx_palloc(ha->temp_pool, last);
+        if (p == NULL) {
+            return NGX_ERROR;
+        }
+
+        ngx_cpystrn(p, key->data, last - 1);
+
         hwc = &ha->dns_wc_tail;
         keys = &ha->dns_wc_tail_hash[k];
     }
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -593,10 +593,13 @@ ngx_ssl_recv(ngx_connection_t *c, u_char
     int  n, bytes;
 
     if (c->ssl->last == NGX_ERROR) {
+        c->read->error = 1;
         return NGX_ERROR;
     }
 
     if (c->ssl->last == NGX_DONE) {
+        c->read->ready = 0;
+        c->read->eof = 1;
         return 0;
     }
 
@@ -619,26 +622,38 @@ ngx_ssl_recv(ngx_connection_t *c, u_char
 
         c->ssl->last = ngx_ssl_handle_recv(c, n);
 
-        if (c->ssl->last != NGX_OK) {
-
-            if (bytes) {
+        if (c->ssl->last == NGX_OK) {
+
+            size -= n;
+
+            if (size == 0) {
                 return bytes;
             }
 
-            if (c->ssl->last == NGX_DONE) {
-                return 0;
-            }
-
+            buf += n;
+
+            continue;
+        }
+
+        if (bytes) {
+            return bytes;
+        }
+
+        switch (c->ssl->last) {
+
+        case NGX_DONE:
+            c->read->ready = 0;
+            c->read->eof = 1;
+            return 0;
+
+        case NGX_ERROR:
+            c->read->error = 1;
+
+            /* fall thruogh */
+
+        case NGX_AGAIN:
             return c->ssl->last;
         }
-
-        size -= n;
-
-        if (size == 0) {
-            return bytes;
-        }
-
-        buf += n;
     }
 }
 
@@ -703,7 +718,6 @@ ngx_ssl_handle_recv(ngx_connection_t *c,
 
     c->ssl->no_wait_shutdown = 1;
     c->ssl->no_send_shutdown = 1;
-    c->read->eof = 1;
 
     if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
@@ -711,7 +725,6 @@ ngx_ssl_handle_recv(ngx_connection_t *c,
         return NGX_DONE;
     }
 
-    c->read->error = 1;
     ngx_ssl_connection_error(c, sslerr, err, "SSL_read() failed");
 
     return NGX_ERROR;
--- a/src/http/modules/ngx_http_upstream_ip_hash_module.c
+++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c
@@ -140,7 +140,7 @@ ngx_http_upstream_get_ip_hash_peer(ngx_p
 
     /* TODO: cached */
 
-    if (iphp->tries > 20 || iphp->rrp.peers->number == 1) {
+    if (iphp->tries > 20 || iphp->rrp.peers->single) {
         return iphp->get_rr_peer(pc, &iphp->rrp);
     }
 
@@ -160,7 +160,7 @@ ngx_http_upstream_get_ip_hash_peer(ngx_p
         p = hash % iphp->rrp.peers->number;
 
         n = p / (8 * sizeof(uintptr_t));
-        m = 1 << p % (8 * sizeof(uintptr_t));
+        m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
 
         if (!(iphp->rrp.tried[n] & m)) {
 
@@ -195,6 +195,8 @@ ngx_http_upstream_get_ip_hash_peer(ngx_p
         }
     }
 
+    iphp->rrp.current = p;
+
     pc->sockaddr = peer->sockaddr;
     pc->socklen = peer->socklen;
     pc->name = &peer->name;
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '0.6.8';
+our $VERSION = '0.6.9';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -836,7 +836,7 @@ ngx_http_process_request_headers(ngx_eve
                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
                                   "client sent too long header line: \"%V\"",
                                   &header);
-                    ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
+                    ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
                     return;
                 }
             }
@@ -948,7 +948,7 @@ ngx_http_process_request_headers(ngx_eve
         ngx_log_error(NGX_LOG_INFO, c->log, 0,
                       "client sent invalid header line: \"%V\\r...\"",
                       &header);
-        ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
+        ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
         return;
     }
 }
@@ -1556,6 +1556,7 @@ ngx_http_request_handler(ngx_event_t *ev
 void
 ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
 {
+    ngx_connection_t          *c;
     ngx_http_request_t        *pr;
     ngx_http_log_ctx_t        *ctx;
     ngx_http_core_loc_conf_t  *clcf;
@@ -1565,7 +1566,9 @@ ngx_http_finalize_request(ngx_http_reque
         return;
     }
 
-    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+    c = r->connection;
+
+    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
                    "http finalize request: %d, \"%V?%V\"",
                    rc, &r->uri, &r->args);
 
@@ -1580,10 +1583,7 @@ ngx_http_finalize_request(ngx_http_reque
         rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
     }
 
-    if (rc == NGX_ERROR
-        || rc == NGX_HTTP_REQUEST_TIME_OUT
-        || r->connection->error)
-    {
+    if (rc == NGX_ERROR || rc == NGX_HTTP_REQUEST_TIME_OUT || c->error) {
         if (rc > 0 && r->headers_out.status == 0) {
             r->headers_out.status = rc;
         }
@@ -1606,12 +1606,12 @@ ngx_http_finalize_request(ngx_http_reque
         }
 
         if (r == r->main) {
-            if (r->connection->read->timer_set) {
-                ngx_del_timer(r->connection->read);
+            if (c->read->timer_set) {
+                ngx_del_timer(c->read);
             }
 
-            if (r->connection->write->timer_set) {
-                ngx_del_timer(r->connection->write);
+            if (c->write->timer_set) {
+                ngx_del_timer(c->write);
             }
         }
 
@@ -1627,8 +1627,8 @@ ngx_http_finalize_request(ngx_http_reque
 
     r->done = 1;
 
-    if (r != r->connection->data) {
-        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+    if (r != c->data) {
+        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                        "http finalize non-active request: \"%V?%V\"",
                        &r->uri, &r->args);
         return;
@@ -1638,19 +1638,19 @@ ngx_http_finalize_request(ngx_http_reque
 
         pr = r->parent;
 
-        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                        "http parent request: \"%V?%V\"", &pr->uri, &pr->args);
 
         if (rc != NGX_AGAIN) {
-            r->connection->data = pr;
+            c->data = pr;
         }
 
-        ctx = r->connection->log->data;
+        ctx = c->log->data;
         ctx->current_request = pr;
 
         if (pr->postponed) {
 
-            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                            "http request: \"%V?%V\" has postponed",
                            &pr->uri, &pr->args);
 
@@ -1664,14 +1664,14 @@ ngx_http_finalize_request(ngx_http_reque
                     r->fast_subrequest = 0;
                 }
 
-                ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                            "http fast subrequest: \"%V?%V\" done",
                            &r->uri, &r->args);
                 return;
             }
 
             if (rc != NGX_AGAIN) {
-                ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                                "http wake parent request: \"%V?%V\"",
                                &pr->uri, &pr->args);
 
@@ -1686,7 +1686,7 @@ ngx_http_finalize_request(ngx_http_reque
         return;
     }
 
-    if (r->connection->buffered) {
+    if (c->buffered) {
         (void) ngx_http_set_write_handler(r);
         return;
     }
@@ -1699,16 +1699,21 @@ ngx_http_finalize_request(ngx_http_reque
         return;
     }
 
-    if (r->connection->read->timer_set) {
-        ngx_del_timer(r->connection->read);
+    if (c->read->timer_set) {
+        ngx_del_timer(c->read);
+    }
+
+    if (c->write->timer_set) {
+        c->write->delayed = 0;
+        ngx_del_timer(c->write);
     }
 
-    if (r->connection->write->timer_set) {
-        r->connection->write->delayed = 0;
-        ngx_del_timer(r->connection->write);
+    if (c->destroyed) {
+        return;
     }
 
-    if (r->connection->destroyed) {
+    if (c->read->eof) {
+        ngx_http_close_request(r, 0);
         return;
     }
 
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -571,6 +571,10 @@ ngx_http_read_discarded_request_body(ngx
             return NGX_AGAIN;
         }
 
+        if (n == 0) {
+            return NGX_OK;
+        }
+
         r->headers_in.content_length_n -= n;
 
     } while (r->connection->read->ready);
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -303,6 +303,8 @@ ngx_http_upstream_get_round_robin_peer(n
 
             /* it's a first try - get a current peer */
 
+            i = pc->tries;
+
             for ( ;; ) {
                 rrp->current = ngx_http_upstream_get_peer(rrp->peers);
 
@@ -339,16 +341,24 @@ ngx_http_upstream_get_round_robin_peer(n
                     pc->tries--;
                 }
 
-                if (pc->tries) {
-                    continue;
+                if (pc->tries == 0) {
+                    goto failed;
                 }
 
-                goto failed;
+                if (--i == 0) {
+                    ngx_log_error(NGX_LOG_ALERT, pc->log, 0,
+                                  "round robin upstream stuck on %ui tries",
+                                  pc->tries);
+                    goto failed;
+                }
             }
 
             peer->current_weight--;
 
         } else {
+
+            i = pc->tries;
+
             for ( ;; ) {
                 n = rrp->current / (8 * sizeof(uintptr_t));
                 m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t));
@@ -385,11 +395,16 @@ ngx_http_upstream_get_round_robin_peer(n
                     rrp->current = 0;
                 }
 
-                if (pc->tries) {
-                    continue;
+                if (pc->tries == 0) {
+                    goto failed;
                 }
 
-                goto failed;
+                if (--i == 0) {
+                    ngx_log_error(NGX_LOG_ALERT, pc->log, 0,
+                                  "round robin upstream stuck on %ui tries",
+                                  pc->tries);
+                    goto failed;
+                }
             }
 
             peer->current_weight--;
@@ -500,7 +515,7 @@ ngx_http_upstream_get_peer(ngx_http_upst
 
         for (i = 0; i < peers->number; i++) {
             if (peer[i].fails == 0) {
-                peer[i].current_weight += peer[i].weight;
+                peer[i].current_weight = peer[i].weight;
 
             } else {
                 /* 1 allows to go to quick recovery when all peers failed */
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -251,7 +251,8 @@ ngx_http_write_filter(ngx_http_request_t
 
     } else if (c->write->ready
                && clcf->sendfile_max_chunk
-               && c->sent - sent >= clcf->sendfile_max_chunk - 2 * ngx_pagesize)
+               && (size_t) (c->sent - sent)
+                                >= clcf->sendfile_max_chunk - 2 * ngx_pagesize)
     {
         c->write->delayed = 1;
         ngx_add_timer(c->write, 1);