# HG changeset patch # User Igor Sysoev # Date 1188244800 -14400 # Node ID 5e3b425174f6aea903cfd1b7b5eb8d21bb780847 # Parent f2f8dc3e7933ed4eb9e958d1700c0a92315a5db0 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. diff --git a/CHANGES b/CHANGES --- 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", diff --git a/CHANGES.ru b/CHANGES.ru --- 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 пытается установить директивы diff --git a/conf/mime.types b/conf/mime.types --- 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; diff --git a/src/core/nginx.h b/src/core/nginx.h --- 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" diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c --- 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]; } diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- 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; diff --git a/src/http/modules/ngx_http_upstream_ip_hash_module.c b/src/http/modules/ngx_http_upstream_ip_hash_module.c --- 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; diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- 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); diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- 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; } diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c --- 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); diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c --- 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 */ diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c --- 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);