# HG changeset patch # User Igor Sysoev # Date 1202677200 -10800 # Node ID a39aab45a53f467d05443d25208b5d893de8f867 # Parent 6999caedb6658e8ad716eebe605fe07221be85d5 nginx 0.6.26 *) Bugfix: the "proxy_store" and "fastcgi_store" directives did not check a response length. *) Bugfix: a segmentation fault occurred in worker process, if big value was used in a "expires" directive. Thanks to Joaquin Cuenca Abela. *) Bugfix: nginx incorrectly detected cache line size on Pentium 4. Thanks to Gena Makhomed. *) Bugfix: in proxied or FastCGI subrequests a client original method was used instead of the GET method. *) Bugfix: socket leak in HTTPS mode if deferred accept was used. Thanks to Ben Maurer. *) Bugfix: nginx issued the bogus error message "SSL_shutdown() failed (SSL: )"; bug appeared in 0.6.23. *) Bugfix: in HTTPS mode requests might fail with the "bad write retry" error; bug appeared in 0.6.23. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,29 @@ +Changes with nginx 0.6.26 11 Feb 2008 + + *) Bugfix: the "proxy_store" and "fastcgi_store" directives did not + check a response length. + + *) Bugfix: a segmentation fault occurred in worker process, if big + value was used in a "expires" directive. + Thanks to Joaquin Cuenca Abela. + + *) Bugfix: nginx incorrectly detected cache line size on Pentium 4. + Thanks to Gena Makhomed. + + *) Bugfix: in proxied or FastCGI subrequests a client original method + was used instead of the GET method. + + *) Bugfix: socket leak in HTTPS mode if deferred accept was used. + Thanks to Ben Maurer. + + *) Bugfix: nginx issued the bogus error message "SSL_shutdown() failed + (SSL: )"; bug appeared in 0.6.23. + + *) Bugfix: in HTTPS mode requests might fail with the "bad write retry" + error; bug appeared in 0.6.23. + + Changes with nginx 0.6.25 08 Jan 2008 *) Change: now the "server_name_in_redirect" directive is used instead diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,32 @@ +Изменения в nginx 0.6.26 11.02.2008 + + *) Исправление: директивы proxy_store и fastcgi_store не проверяли + длину ответа. + + *) Исправление: при использовании большого значения в директиве expires + в рабочем процессе происходил segmentation fault. + Спасибо Joaquin Cuenca Abela. + + *) Исправление: nginx неверно определял длину строки кэша на + Pentium 4. + Спасибо Gena Makhomed. + + *) Исправление: в проксированных подзапросах и подзапросах к + FastCGI-серверу вместо метода GET использовался оригинальный метод + клиента. + + *) Исправление: утечки сокетов в режиме HTTPS при использовании + отложенного accept'а. + Спасибо Ben Maurer. + + *) Исправление: nginx выдавал ошибочное сообщение "SSL_shutdown() + failed (SSL: )"; ошибка появилась в 0.6.23. + + *) Исправление: при использовании HTTPS запросы могли завершаться с + ошибкой "bad write retry"; ошибка появилась в 0.6.23. + + Изменения в nginx 0.6.25 08.01.2008 *) Изменение: вместо специального параметра "*" в директиве server_name 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.25" +#define NGINX_VERSION "0.6.26" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -767,6 +767,9 @@ ngx_connection_error(ngx_connection_t *c || err == NGX_ENOTCONN || err == NGX_ETIMEDOUT || err == NGX_ECONNREFUSED + || err == NGX_ENETDOWN + || err == NGX_ENETUNREACH + || err == NGX_EHOSTDOWN || err == NGX_EHOSTUNREACH) { switch (c->log_error) { diff --git a/src/core/ngx_cpuinfo.c b/src/core/ngx_cpuinfo.c --- a/src/core/ngx_cpuinfo.c +++ b/src/core/ngx_cpuinfo.c @@ -92,13 +92,22 @@ ngx_cpuinfo(void) if (ngx_strcmp(vendor, "GenuineIntel") == 0) { - switch (cpu[0] & 0xf00) { + switch ((cpu[0] & 0xf00) >> 8) { /* Pentium */ case 5: + ngx_cacheline_size = 32; + break; + /* Pentium Pro, II, III */ case 6: ngx_cacheline_size = 32; + + if ((cpu[0] & 0xf0) >= 0xd0) { + /* Intel Core */ + ngx_cacheline_size = 64; + } + break; /* diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -212,7 +212,7 @@ ngx_sprint_uchar(u_char *text, u_char c, c2 = c % 10; - *text++ = (u_char) (c2 + '0'); + *text = (u_char) (c2 + '0'); n++; return n; diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -215,10 +215,9 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx if (ctx->event) { ngx_resolver_free_locked(r, ctx->event); + ctx->event = NULL; } - ngx_resolver_free_locked(r, ctx); - /* unlock alloc mutex */ return NGX_ERROR; @@ -787,9 +786,9 @@ ngx_resolver_resend(ngx_resolver_t *r, n rn->expire = now + r->resend_timeout; ngx_queue_insert_head(queue, &rn->queue); - - continue; } + + continue; } ngx_rbtree_delete(tree, &rn->node); diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -147,7 +147,7 @@ ngx_vsnprintf(u_char *buf, size_t max, c sign = 1; hexadecimal = 0; max_width = 0; - slen = 0; + slen = (size_t) -1; p = temp + NGX_INT64_LEN; @@ -182,7 +182,7 @@ ngx_vsnprintf(u_char *buf, size_t max, c continue; case '*': - slen = va_arg(args, u_int); + slen = va_arg(args, size_t); fmt++; continue; @@ -221,13 +221,15 @@ ngx_vsnprintf(u_char *buf, size_t max, c case 's': p = va_arg(args, u_char *); - if (slen == 0) { + if (slen == (size_t) -1) { while (*p && buf < last) { *buf++ = *p++; } } else { - buf = ngx_cpymem(buf, p, slen); + len = (buf + slen < last) ? slen : (size_t) (last - buf); + + buf = ngx_cpymem(buf, p, len); } fmt++; diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -203,18 +203,21 @@ ngx_http_cookie_time(u_char *buf, time_t void ngx_gmtime(time_t t, ngx_tm_t *tp) { - ngx_int_t sec, min, hour, mday, mon, year, wday, yday, days; + ngx_uint_t n, sec, min, hour, mday, mon, year, wday, yday, days; - days = (ngx_int_t) (t / 86400); + /* the calculation is valid for positive time_t only */ + n = (ngx_uint_t) t; + + days = n / 86400; /* Jaunary 1, 1970 was Thursday */ wday = (4 + days) % 7; - t %= 86400; - hour = (ngx_int_t) (t / 3600); - t %= 3600; - min = (ngx_int_t) (t / 60); - sec = (ngx_int_t) (t % 60); + n %= 86400; + hour = n / 3600; + n %= 3600; + min = n / 60; + sec = n % 60; /* the algorithm based on Gauss's formula */ diff --git a/src/event/modules/ngx_eventport_module.c b/src/event/modules/ngx_eventport_module.c --- a/src/event/modules/ngx_eventport_module.c +++ b/src/event/modules/ngx_eventport_module.c @@ -40,11 +40,6 @@ typedef struct port_notify { void *portnfy_user; /* user defined */ } port_notify_t; -typedef struct itimerspec { /* definition per POSIX.4 */ - struct timespec it_interval;/* timer period */ - struct timespec it_value; /* timer expiration */ -} itimerspec_t; - int port_create(void) { return -1; @@ -106,7 +101,7 @@ static char *ngx_eventport_init_conf(ngx static int ep = -1; static port_event_t *event_list; static ngx_uint_t nevents; -static timer_t event_timer = -1; +static timer_t event_timer = (timer_t) -1; static ngx_str_t eventport_name = ngx_string("eventport"); @@ -237,13 +232,13 @@ ngx_eventport_init(ngx_cycle_t *cycle, n static void ngx_eventport_done(ngx_cycle_t *cycle) { - if (event_timer != -1) { + if (event_timer != (timer_t) -1) { if (timer_delete(event_timer) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "timer_delete() failed"); } - event_timer = -1; + event_timer = (timer_t) -1; } if (close(ep) == -1) { diff --git a/src/event/modules/ngx_rtsig_module.c b/src/event/modules/ngx_rtsig_module.c --- a/src/event/modules/ngx_rtsig_module.c +++ b/src/event/modules/ngx_rtsig_module.c @@ -12,8 +12,7 @@ #if (NGX_TEST_BUILD_RTSIG) #define F_SETSIG 10 -#define SIGRTMIN 33 -#define si_fd __spare__[0] +#define si_fd _reason.__spare__.__spare2__[0] #define KERN_RTSIGNR 30 #define KERN_RTSIGMAX 31 diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -143,8 +143,14 @@ ngx_event_connect_peer(ngx_peer_connecti if (err != NGX_EINPROGRESS && err != NGX_EAGAIN) { - if (err == NGX_ECONNREFUSED || err == NGX_EHOSTUNREACH) { + if (err == NGX_ECONNREFUSED + || err == NGX_ENETDOWN + || err == NGX_ENETUNREACH + || err == NGX_EHOSTDOWN + || err == NGX_EHOSTUNREACH) + { level = NGX_LOG_ERR; + } else { level = NGX_LOG_CRIT; } 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 @@ -187,6 +187,13 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]); } + /* + * we need this option because in ngx_ssl_send_chain() + * we may switch to a buffered write and may copy leftover part of + * previously unbuffered data to our internal buffer + */ + SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); + SSL_CTX_set_read_ahead(ssl->ctx, 1); return NGX_OK; @@ -1035,19 +1042,16 @@ ngx_ssl_shutdown(ngx_connection_t *c) sslerr = 0; - /* SSL_shutdown() never return -1, on error it return 0 */ - - if (n != 1) { + /* SSL_shutdown() never returns -1, on error it returns 0 */ + + if (n != 1 && ERR_peek_error()) { sslerr = SSL_get_error(c->ssl->connection, n); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr); } - if (n == 1 - || sslerr == SSL_ERROR_ZERO_RETURN - || (sslerr == 0 && c->timedout)) - { + if (n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN) { SSL_free(c->ssl->connection); c->ssl = NULL; @@ -1111,6 +1115,7 @@ static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, char *text) { + int n; ngx_uint_t level; level = NGX_LOG_CRIT; @@ -1124,6 +1129,9 @@ ngx_ssl_connection_error(ngx_connection_ || err == NGX_ETIMEDOUT #endif || err == NGX_ECONNREFUSED + || err == NGX_ENETDOWN + || err == NGX_ENETUNREACH + || err == NGX_EHOSTDOWN || err == NGX_EHOSTUNREACH) { switch (c->log_error) { @@ -1141,6 +1149,35 @@ ngx_ssl_connection_error(ngx_connection_ break; } } + + } else if (sslerr == SSL_ERROR_SSL) { + + n = ERR_GET_REASON(ERR_peek_error()); + + /* handshake failures */ + if (n == SSL_R_NO_SHARED_CIPHER + || n == SSL_R_UNEXPECTED_MESSAGE + || n == SSL_R_WRONG_VERSION_NUMBER + || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */ + || n == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED + || n == SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER + || n == SSL_R_TLSV1_ALERT_UNKNOWN_CA) + { + switch (c->log_error) { + + case NGX_ERROR_IGNORE_ECONNRESET: + case NGX_ERROR_INFO: + level = NGX_LOG_INFO; + break; + + case NGX_ERROR_ERR: + level = NGX_LOG_ERR; + break; + + default: + break; + } + } } ngx_ssl_error(level, c->log, err, text); @@ -1150,18 +1187,21 @@ ngx_ssl_connection_error(ngx_connection_ static void ngx_ssl_clear_error(ngx_log_t *log) { - if (ERR_peek_error()) { + while (ERR_peek_error()) { ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error"); } + + ERR_clear_error(); } void ngx_cdecl ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) { - u_long n; - va_list args; - u_char errstr[NGX_MAX_CONF_ERRSTR], *p, *last; + u_long n; + va_list args; + u_char *p, *last; + u_char errstr[NGX_MAX_CONF_ERRSTR]; last = errstr + NGX_MAX_CONF_ERRSTR; @@ -1171,7 +1211,7 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_ p = ngx_cpystrn(p, (u_char *) " (SSL:", last - p); - while (p < last) { + for ( ;; ) { n = ERR_get_error(); @@ -1179,6 +1219,10 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_ break; } + if (p >= last) { + continue; + } + *p++ = ' '; ERR_error_string_n(n, (char *) p, last - p); diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -1140,7 +1140,7 @@ ngx_http_dav_create_loc_conf(ngx_conf_t * conf->methods = 0; */ - conf->min_delete_depth = NGX_CONF_UNSET; + conf->min_delete_depth = NGX_CONF_UNSET_UINT; conf->access = NGX_CONF_UNSET_UINT; conf->create_full_put_path = NGX_CONF_UNSET; diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -135,33 +135,6 @@ static char *ngx_http_fastcgi_upstream_f ngx_command_t *cmd, void *conf); -static ngx_http_fastcgi_request_start_t ngx_http_fastcgi_request_start = { - { 1, /* version */ - NGX_HTTP_FASTCGI_BEGIN_REQUEST, /* type */ - 0, /* request_id_hi */ - 1, /* request_id_lo */ - 0, /* content_length_hi */ - sizeof(ngx_http_fastcgi_begin_request_t), /* content_length_lo */ - 0, /* padding_length */ - 0 }, /* reserved */ - - { 0, /* role_hi */ - NGX_HTTP_FASTCGI_RESPONDER, /* role_lo */ - 0, /* NGX_HTTP_FASTCGI_KEEP_CONN */ /* flags */ - { 0, 0, 0, 0, 0 } }, /* reserved[5] */ - - { 1, /* version */ - NGX_HTTP_FASTCGI_PARAMS, /* type */ - 0, /* request_id_hi */ - 1 }, /* request_id_lo */ - -}; - - -static ngx_str_t ngx_http_fastcgi_script_name = - ngx_string("fastcgi_script_name"); - - static ngx_conf_post_t ngx_http_fastcgi_lowat_post = { ngx_http_fastcgi_lowat_check }; @@ -412,12 +385,40 @@ ngx_module_t ngx_http_fastcgi_module = }; +static ngx_http_fastcgi_request_start_t ngx_http_fastcgi_request_start = { + { 1, /* version */ + NGX_HTTP_FASTCGI_BEGIN_REQUEST, /* type */ + 0, /* request_id_hi */ + 1, /* request_id_lo */ + 0, /* content_length_hi */ + sizeof(ngx_http_fastcgi_begin_request_t), /* content_length_lo */ + 0, /* padding_length */ + 0 }, /* reserved */ + + { 0, /* role_hi */ + NGX_HTTP_FASTCGI_RESPONDER, /* role_lo */ + 0, /* NGX_HTTP_FASTCGI_KEEP_CONN */ /* flags */ + { 0, 0, 0, 0, 0 } }, /* reserved[5] */ + + { 1, /* version */ + NGX_HTTP_FASTCGI_PARAMS, /* type */ + 0, /* request_id_hi */ + 1 }, /* request_id_lo */ + +}; + + +static ngx_str_t ngx_http_fastcgi_script_name = + ngx_string("fastcgi_script_name"); + + static ngx_str_t ngx_http_fastcgi_hide_headers[] = { ngx_string("Status"), ngx_string("X-Accel-Expires"), ngx_string("X-Accel-Redirect"), ngx_string("X-Accel-Limit-Rate"), - ngx_string("X-Accel-Buffer"), + ngx_string("X-Accel-Buffering"), + ngx_string("X-Accel-Charset"), ngx_null_string }; diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -435,7 +435,8 @@ static ngx_str_t ngx_http_proxy_hide_he ngx_string("X-Accel-Expires"), ngx_string("X-Accel-Redirect"), ngx_string("X-Accel-Limit-Rate"), - ngx_string("X-Accel-Buffer"), + ngx_string("X-Accel-Buffering"), + ngx_string("X-Accel-Charset"), ngx_null_string }; 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.25'; +our $VERSION = '0.6.26'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -652,6 +652,9 @@ ngx_module_t ngx_http_core_module = { }; +static ngx_str_t ngx_http_core_get_method = { 3, (u_char *) "GET " }; + + void ngx_http_handler(ngx_http_request_t *r) { @@ -1760,7 +1763,7 @@ ngx_http_subrequest(ngx_http_request_t * sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0; sr->unparsed_uri = r->unparsed_uri; - sr->method_name = r->method_name; + sr->method_name = ngx_http_core_get_method; sr->http_protocol = r->http_protocol; if (ngx_http_set_exten(sr) != NGX_OK) { @@ -2909,7 +2912,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t if (conf->resolver == NULL) { conf->resolver = ngx_resolver_create(NULL, cf->cycle->new_log); if (conf->resolver == NULL) { - return NGX_OK; + return NGX_CONF_ERROR; } } } 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 @@ -479,6 +479,15 @@ ngx_http_ssl_handshake(ngx_event_t *rev) n = recv(c->fd, (char *) buf, 1, MSG_PEEK); if (n == -1 && ngx_socket_errno == NGX_EAGAIN) { + + if (!rev->timer_set) { + ngx_add_timer(rev, c->listening->post_accept_timeout); + } + + if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + } + return; } @@ -985,10 +994,9 @@ ngx_http_read_request_header(ngx_http_re } if (n == NGX_AGAIN) { - if (!r->header_timeout_set) { + if (!rev->timer_set) { cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); ngx_add_timer(rev, cscf->client_header_timeout); - r->header_timeout_set = 1; } if (ngx_handle_read_event(rev, 0) == NGX_ERROR) { diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -427,8 +427,6 @@ struct ngx_http_request_s { unsigned fast_subrequest:1; unsigned subrequest_in_memory:1; - unsigned header_timeout_set:1; - unsigned gzip:2; unsigned proxy:1; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1352,6 +1352,8 @@ ngx_http_upstream_process_header(ngx_eve r->headers_out.status = u->headers_in.status_n; r->headers_out.status_line = u->headers_in.status_line; + u->headers_in.content_length_n = r->headers_out.content_length_n; + if (r->headers_out.content_length_n != -1) { u->length = (size_t) r->headers_out.content_length_n; @@ -1955,6 +1957,7 @@ ngx_http_upstream_process_downstream(ngx static void ngx_http_upstream_process_body(ngx_event_t *ev) { + ngx_temp_file_t *tf; ngx_event_pipe_t *p; ngx_connection_t *c, *downstream; ngx_http_log_ctx_t *ctx; @@ -2049,18 +2052,22 @@ ngx_http_upstream_process_body(ngx_event if (u->store) { - if (p->upstream_eof && u->headers_in.status_n == NGX_HTTP_OK) { - + tf = u->pipe->temp_file; + + if (p->upstream_eof + && u->headers_in.status_n == NGX_HTTP_OK + && (u->headers_in.content_length_n == -1 + || (u->headers_in.content_length_n == tf->offset))) + { ngx_http_upstream_store(r, u); } else if ((p->upstream_error || (p->upstream_eof && u->headers_in.status_n != NGX_HTTP_OK)) - && u->pipe->temp_file->file.fd != NGX_INVALID_FILE) + && tf->file.fd != NGX_INVALID_FILE) { - if (ngx_delete_file(u->pipe->temp_file->file.name.data) - == NGX_FILE_ERROR) - { + if (ngx_delete_file(tf->file.name.data) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_delete_file_n " \"%s\" failed", u->pipe->temp_file->file.name.data); diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -192,6 +192,8 @@ typedef struct { ngx_table_elt_t *content_encoding; #endif + off_t content_length_n; + ngx_array_t cache_control; } ngx_http_upstream_headers_in_t; 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 @@ -605,7 +605,7 @@ ngx_http_upstream_get_peer(ngx_http_upst } for (i = 0; i < peers->number; i++) { - peer[i].current_weight += peer[i].weight; + peer[i].current_weight = peer[i].weight; } } } diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h --- a/src/os/unix/ngx_errno.h +++ b/src/os/unix/ngx_errno.h @@ -37,6 +37,9 @@ typedef int ngx_err_t; #define NGX_ETIMEDOUT ETIMEDOUT #define NGX_ECONNREFUSED ECONNREFUSED #define NGX_ENAMETOOLONG ENAMETOOLONG +#define NGX_ENETDOWN ENETDOWN +#define NGX_ENETUNREACH ENETUNREACH +#define NGX_EHOSTDOWN EHOSTDOWN #define NGX_EHOSTUNREACH EHOSTUNREACH #define NGX_ENOSYS ENOSYS #define NGX_ECANCELED ECANCELED diff --git a/src/os/unix/ngx_recv.c b/src/os/unix/ngx_recv.c --- a/src/os/unix/ngx_recv.c +++ b/src/os/unix/ngx_recv.c @@ -41,6 +41,7 @@ ngx_unix_recv(ngx_connection_t *c, u_cha return 0; } else { + rev->ready = 0; return NGX_AGAIN; } }