Merge branch 'nginx' (nginx-1.15.7). Change-Id: Ic090f74a5d7bbf5a44c0151eafd89656f61b9525 Signed-off-by: Piotr Sikora <piotrsikora@google.com>
diff --git a/.hgtags b/.hgtags index 04a512b..8e059a3 100644 --- a/.hgtags +++ b/.hgtags
@@ -432,3 +432,4 @@ 49d49835653857daa418e68d6cbfed4958c78fca release-1.15.4 f062e43d74fc2578bb100a9e82a953efa1eb9e4e release-1.15.5 2351853ce6867b6166823bdf94333c0a76633c0a release-1.15.6 +051a039ce1c7e09144de4a4846669ec7116cecea release-1.15.7
diff --git a/BUILD b/BUILD index a08d335..e572e13 100644 --- a/BUILD +++ b/BUILD
@@ -1535,5 +1535,5 @@ preinst = "@nginx_pkgoss//:debian_preinst", prerm = "@nginx_pkgoss//:debian_prerm", section = "httpd", - version = "1.15.6", + version = "1.15.7", )
diff --git a/build.bzl b/build.bzl index 78409de..bcf3238 100644 --- a/build.bzl +++ b/build.bzl
@@ -663,7 +663,7 @@ name = "nginx_pkgoss", build_file_content = _PKGOSS_BUILD_FILE.format(nginx = nginx) + _PKGOSS_BUILD_FILE_TAIL, - commit = "8cd9073e08734f32b52157e2495ad8804dbf8d51", # nginx-1.15.6 + commit = "a0a043cd5bc6ce17124507e4a6241be72c7eaeaa", # nginx-1.15.7 remote = "https://nginx.googlesource.com/nginx-pkgoss", )
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index 43a21e5..0738e6f 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml
@@ -5,6 +5,62 @@ <change_log title="nginx"> +<changes ver="1.15.7" date="2018-11-27"> + +<change type="feature"> +<para lang="ru"> +директива proxy_requests в модуле stream. +</para> +<para lang="en"> +the "proxy_requests" directive in the stream module. +</para> +</change> + +<change type="feature"> +<para lang="ru"> +параметр "delay" директивы "limit_req".<br/> +Спасибо Владиславу Шабанову и Петру Щучкину. +</para> +<para lang="en"> +the "delay" parameter of the "limit_req" directive.<br/> +Thanks to Vladislav Shabanov and Peter Shchuchkin. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +утечки памяти в случае ошибок при переконфигурации. +</para> +<para lang="en"> +memory leak on errors during reconfiguration. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +в переменных $upstream_response_time, $upstream_connect_time и +$upstream_header_time. +</para> +<para lang="en"> +in the $upstream_response_time, $upstream_connect_time, and +$upstream_header_time variables. +</para> +</change> + +<change type="bugfix"> +<para lang="ru"> +в рабочем процессе мог произойти segmentation fault, +если использовался модуль ngx_http_mp4_module на 32-битных платформах. +</para> +<para lang="en"> +a segmentation fault might occur in a worker process +if the ngx_http_mp4_module was used on 32-bit platforms. +</para> +</change> + +</changes> + + <changes ver="1.15.6" date="2018-11-06"> <change type="security">
diff --git a/misc/GNUmakefile b/misc/GNUmakefile index 73d8bd9..d68ceca 100644 --- a/misc/GNUmakefile +++ b/misc/GNUmakefile
@@ -6,7 +6,7 @@ CC = cl OBJS = objs.msvc8 -OPENSSL = openssl-1.0.2p +OPENSSL = openssl-1.0.2q ZLIB = zlib-1.2.11 PCRE = pcre-8.42
diff --git a/src/core/nginx.h b/src/core/nginx.h index 2ddd19d..14dc7c9 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h
@@ -13,8 +13,8 @@ #define NGINX_NAME "nginx" #endif -#define nginx_version 1015006 -#define NGINX_VERSION "1.15.6" +#define nginx_version 1015007 +#define NGINX_VERSION "1.15.7" #define NGINX_VER NGINX_NAME "/" NGINX_VERSION #ifdef NGX_BUILD
diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index 083c764..95f4bdf 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c
@@ -843,6 +843,69 @@ } } + /* free the newly created shared memory */ + + part = &cycle->shared_memory.part; + shm_zone = part->elts; + + for (i = 0; /* void */ ; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + part = part->next; + shm_zone = part->elts; + i = 0; + } + + if (shm_zone[i].shm.addr == NULL) { + continue; + } + + opart = &old_cycle->shared_memory.part; + oshm_zone = opart->elts; + + for (n = 0; /* void */ ; n++) { + + if (n >= opart->nelts) { + if (opart->next == NULL) { + break; + } + opart = opart->next; + oshm_zone = opart->elts; + n = 0; + } + + if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) { + continue; + } + + if (ngx_strncmp(shm_zone[i].shm.name.data, + oshm_zone[n].shm.name.data, + shm_zone[i].shm.name.len) + != 0) + { + continue; + } + + if (shm_zone[i].tag == oshm_zone[n].tag + && shm_zone[i].shm.size == oshm_zone[n].shm.size + && !shm_zone[i].noreuse) + { + goto old_shm_zone_found; + } + + break; + } + + ngx_shm_free(&shm_zone[i].shm); + + old_shm_zone_found: + + continue; + } + if (ngx_test_config) { ngx_destroy_cycle_pools(&conf); return NULL; @@ -1274,6 +1337,7 @@ shm_zone->data = NULL; shm_zone->shm.log = cf->cycle->log; + shm_zone->shm.addr = NULL; shm_zone->shm.size = size; shm_zone->shm.name = *name; shm_zone->shm.exists = 0;
diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c index 7f5dc78..5c3dbe8 100644 --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c
@@ -126,6 +126,26 @@ continue; } + if (bsize < 0) { + + ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, + "negative size buf in output " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + ctx->in->buf->temporary, + ctx->in->buf->recycled, + ctx->in->buf->in_file, + ctx->in->buf->start, + ctx->in->buf->pos, + ctx->in->buf->last, + ctx->in->buf->file, + ctx->in->buf->file_pos, + ctx->in->buf->file_last); + + ngx_debug_point(); + + return NGX_ERROR; + } + if (ngx_output_chain_as_is(ctx, ctx->in->buf)) { /* move the chain link to the output chain */ @@ -665,7 +685,6 @@ for (size = 0; in; in = in->next) { -#if 1 if (ngx_buf_size(in->buf) == 0 && !ngx_buf_special(in->buf)) { ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, @@ -685,7 +704,26 @@ continue; } -#endif + + if (ngx_buf_size(in->buf) < 0) { + + ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, + "negative size buf in chain writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + in->buf->temporary, + in->buf->recycled, + in->buf->in_file, + in->buf->start, + in->buf->pos, + in->buf->last, + in->buf->file, + in->buf->file_pos, + in->buf->file_last); + + ngx_debug_point(); + + return NGX_ERROR; + } size += ngx_buf_size(in->buf); @@ -709,7 +747,6 @@ for (cl = ctx->out; cl; cl = cl->next) { -#if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, @@ -729,7 +766,26 @@ continue; } -#endif + + if (ngx_buf_size(cl->buf) < 0) { + + ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0, + "negative size buf in chain writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + + return NGX_ERROR; + } size += ngx_buf_size(cl->buf); }
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index 2ee07bf..04980f8 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c
@@ -2013,6 +2013,14 @@ } +void +ngx_explicit_memzero(void *buf, size_t n) +{ + ngx_memzero(buf, n); + ngx_memory_barrier(); +} + + #if (NGX_MEMCPY_LIMIT) void *
diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h index 882ae7c..0fb9be7 100644 --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h
@@ -88,6 +88,8 @@ #define ngx_memzero(buf, n) (void) memset(buf, 0, n) #define ngx_memset(buf, c, n) (void) memset(buf, c, n) +void ngx_explicit_memzero(void *buf, size_t n); + #if (NGX_MEMCPY_LIMIT)
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index 0c03b56..f6eaf8c 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h
@@ -514,6 +514,7 @@ void ngx_udp_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); #endif +void ngx_delete_udp_connection(void *data); ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle); ngx_int_t ngx_enable_accept_events(ngx_cycle_t *cycle); u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len);
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 88571a9..d31f3b7 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c
@@ -1074,7 +1074,7 @@ ngx_close_file_n " \"%s\" failed", file->data); } - ngx_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE); + ngx_explicit_memzero(buf, NGX_SSL_PASSWORD_BUFFER_SIZE); return passwords; } @@ -1091,7 +1091,7 @@ pwd = passwords->elts; for (i = 0; i < passwords->nelts; i++) { - ngx_memzero(pwd[i].data, pwd[i].len); + ngx_explicit_memzero(pwd[i].data, pwd[i].len); } }
diff --git a/src/event/ngx_event_udp.c b/src/event/ngx_event_udp.c index 8b0ae55..65eb22f 100644 --- a/src/event/ngx_event_udp.c +++ b/src/event/ngx_event_udp.c
@@ -23,7 +23,6 @@ static ssize_t ngx_udp_shared_recv(ngx_connection_t *c, u_char *buf, size_t size); static ngx_int_t ngx_insert_udp_connection(ngx_connection_t *c); -static void ngx_delete_udp_connection(void *data); static ngx_connection_t *ngx_lookup_udp_connection(ngx_listening_t *ls, struct sockaddr *sockaddr, socklen_t socklen, struct sockaddr *local_sockaddr, socklen_t local_socklen); @@ -261,7 +260,10 @@ rev->handler(rev); - c->udp->buffer = NULL; + if (c->udp) { + c->udp->buffer = NULL; + } + rev->ready = 0; goto next; @@ -555,12 +557,18 @@ } -static void +void ngx_delete_udp_connection(void *data) { ngx_connection_t *c = data; + if (c->udp == NULL) { + return; + } + ngx_rbtree_delete(&c->listening->rbtree, &c->udp->node); + + c->udp = NULL; } @@ -638,4 +646,12 @@ return NULL; } +#else + +void +ngx_delete_udp_connection(void *data) +{ + return; +} + #endif
diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c index 63ec2de..e81d57f 100644 --- a/src/http/modules/ngx_http_limit_req_module.c +++ b/src/http/modules/ngx_http_limit_req_module.c
@@ -44,7 +44,7 @@ ngx_shm_zone_t *shm_zone; /* integer value, 1 corresponds to 0.001 r/s */ ngx_uint_t burst; - ngx_uint_t nodelay; /* unsigned nodelay:1 */ + ngx_uint_t delay; } ngx_http_limit_req_limit_t; @@ -499,12 +499,12 @@ excess = *ep; - if (excess == 0 || (*limit)->nodelay) { + if ((ngx_uint_t) excess <= (*limit)->delay) { max_delay = 0; } else { ctx = (*limit)->shm_zone->data; - max_delay = excess * 1000 / ctx->rate; + max_delay = (excess - (*limit)->delay) * 1000 / ctx->rate; } while (n--) { @@ -544,11 +544,11 @@ ctx->node = NULL; - if (limits[n].nodelay) { + if ((ngx_uint_t) excess <= limits[n].delay) { continue; } - delay = excess * 1000 / ctx->rate; + delay = (excess - limits[n].delay) * 1000 / ctx->rate; if (delay > max_delay) { max_delay = delay; @@ -875,9 +875,9 @@ { ngx_http_limit_req_conf_t *lrcf = conf; - ngx_int_t burst; + ngx_int_t burst, delay; ngx_str_t *value, s; - ngx_uint_t i, nodelay; + ngx_uint_t i; ngx_shm_zone_t *shm_zone; ngx_http_limit_req_limit_t *limit, *limits; @@ -885,7 +885,7 @@ shm_zone = NULL; burst = 0; - nodelay = 0; + delay = 0; for (i = 1; i < cf->args->nelts; i++) { @@ -908,7 +908,19 @@ burst = ngx_atoi(value[i].data + 6, value[i].len - 6); if (burst <= 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid burst rate \"%V\"", &value[i]); + "invalid burst value \"%V\"", &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + + if (ngx_strncmp(value[i].data, "delay=", 6) == 0) { + + delay = ngx_atoi(value[i].data + 6, value[i].len - 6); + if (delay <= 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid delay value \"%V\"", &value[i]); return NGX_CONF_ERROR; } @@ -916,7 +928,7 @@ } if (ngx_strcmp(value[i].data, "nodelay") == 0) { - nodelay = 1; + delay = NGX_MAX_INT_T_VALUE / 1000; continue; } @@ -956,7 +968,7 @@ limit->shm_zone = shm_zone; limit->burst = burst * 1000; - limit->nodelay = nodelay; + limit->delay = delay * 1000; return NGX_CONF_OK; }
diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c index 2a6fafa..618bf78 100644 --- a/src/http/modules/ngx_http_mp4_module.c +++ b/src/http/modules/ngx_http_mp4_module.c
@@ -169,7 +169,14 @@ #define ngx_mp4_atom_next(mp4, n) \ - mp4->buffer_pos += (size_t) n; \ + \ + if (n > (size_t) (mp4->buffer_end - mp4->buffer_pos)) { \ + mp4->buffer_pos = mp4->buffer_end; \ + \ + } else { \ + mp4->buffer_pos += (size_t) n; \ + } \ + \ mp4->offset += n
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 1127b71..fdfd3c6 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c
@@ -1509,8 +1509,8 @@ r->connection->log->action = "connecting to upstream"; - if (u->state && u->state->response_time) { - u->state->response_time = ngx_current_msec - u->state->response_time; + if (u->state && u->state->response_time == (ngx_msec_t) -1) { + u->state->response_time = ngx_current_msec - u->start_time; } u->state = ngx_array_push(r->upstream_states); @@ -1522,7 +1522,9 @@ ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t)); - u->state->response_time = ngx_current_msec; + u->start_time = ngx_current_msec; + + u->state->response_time = (ngx_msec_t) -1; u->state->connect_time = (ngx_msec_t) -1; u->state->header_time = (ngx_msec_t) -1; @@ -2006,7 +2008,7 @@ "http upstream send request"); if (u->state->connect_time == (ngx_msec_t) -1) { - u->state->connect_time = ngx_current_msec - u->state->response_time; + u->state->connect_time = ngx_current_msec - u->start_time; } if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) { @@ -2421,7 +2423,7 @@ /* rc == NGX_OK */ - u->state->header_time = ngx_current_msec - u->state->response_time; + u->state->header_time = ngx_current_msec - u->start_time; if (u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE) { @@ -4321,8 +4323,8 @@ u->resolved->ctx = NULL; } - if (u->state && u->state->response_time) { - u->state->response_time = ngx_current_msec - u->state->response_time; + if (u->state && u->state->response_time == (ngx_msec_t) -1) { + u->state->response_time = ngx_current_msec - u->start_time; if (u->pipe && u->pipe->read_length) { u->state->bytes_received += u->pipe->read_length @@ -5435,18 +5437,18 @@ state = r->upstream_states->elts; for ( ;; ) { - if (state[i].status) { - if (data == 1 && state[i].header_time != (ngx_msec_t) -1) { - ms = state[i].header_time; + if (data == 1) { + ms = state[i].header_time; - } else if (data == 2 && state[i].connect_time != (ngx_msec_t) -1) { - ms = state[i].connect_time; + } else if (data == 2) { + ms = state[i].connect_time; - } else { - ms = state[i].response_time; - } + } else { + ms = state[i].response_time; + } + if (ms != -1) { ms = ngx_max(ms, 0); p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000);
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 26a0cc5..6a3b302 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h
@@ -367,7 +367,7 @@ ngx_int_t (*rewrite_cookie)(ngx_http_request_t *r, ngx_table_elt_t *h); - ngx_msec_t timeout; + ngx_msec_t start_time; ngx_http_upstream_state_t *state;
diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c index 0036231..3f18d76 100644 --- a/src/http/ngx_http_write_filter_module.c +++ b/src/http/ngx_http_write_filter_module.c
@@ -80,7 +80,6 @@ cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); -#if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "zero size buf in writer " @@ -98,7 +97,24 @@ ngx_debug_point(); return NGX_ERROR; } -#endif + + if (ngx_buf_size(cl->buf) < 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "negative size buf in writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + return NGX_ERROR; + } size += ngx_buf_size(cl->buf); @@ -136,7 +152,6 @@ cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); -#if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "zero size buf in writer " @@ -154,7 +169,24 @@ ngx_debug_point(); return NGX_ERROR; } -#endif + + if (ngx_buf_size(cl->buf) < 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "negative size buf in writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + return NGX_ERROR; + } size += ngx_buf_size(cl->buf);
diff --git a/src/stream/ngx_stream_proxy_module.c b/src/stream/ngx_stream_proxy_module.c index c8465a7..0949313 100644 --- a/src/stream/ngx_stream_proxy_module.c +++ b/src/stream/ngx_stream_proxy_module.c
@@ -26,6 +26,7 @@ size_t buffer_size; size_t upload_rate; size_t download_rate; + ngx_uint_t requests; ngx_uint_t responses; ngx_uint_t next_upstream_tries; ngx_flag_t next_upstream; @@ -73,6 +74,8 @@ static ngx_int_t ngx_stream_proxy_test_connect(ngx_connection_t *c); static void ngx_stream_proxy_process(ngx_stream_session_t *s, ngx_uint_t from_upstream, ngx_uint_t do_write); +static ngx_int_t ngx_stream_proxy_test_finalize(ngx_stream_session_t *s, + ngx_uint_t from_upstream); static void ngx_stream_proxy_next_upstream(ngx_stream_session_t *s); static void ngx_stream_proxy_finalize(ngx_stream_session_t *s, ngx_uint_t rc); static u_char *ngx_stream_proxy_log_error(ngx_log_t *log, u_char *buf, @@ -193,6 +196,13 @@ offsetof(ngx_stream_proxy_srv_conf_t, download_rate), NULL }, + { ngx_string("proxy_requests"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_proxy_srv_conf_t, requests), + NULL }, + { ngx_string("proxy_responses"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -680,7 +690,7 @@ u->proxy_protocol = pscf->proxy_protocol; if (u->state) { - u->state->response_time = ngx_current_msec - u->state->response_time; + u->state->response_time = ngx_current_msec - u->start_time; } u->state = ngx_array_push(s->upstream_states); @@ -691,9 +701,11 @@ ngx_memzero(u->state, sizeof(ngx_stream_upstream_state_t)); + u->start_time = ngx_current_msec; + u->state->connect_time = (ngx_msec_t) -1; u->state->first_byte_time = (ngx_msec_t) -1; - u->state->response_time = ngx_current_msec; + u->state->response_time = (ngx_msec_t) -1; rc = ngx_event_connect_peer(&u->peer); @@ -807,7 +819,7 @@ } } - u->state->connect_time = ngx_current_msec - u->state->response_time; + u->state->connect_time = ngx_current_msec - u->start_time; if (u->peer.notify) { u->peer.notify(&u->peer, u->peer.data, @@ -1339,11 +1351,14 @@ } else { if (s->connection->type == SOCK_DGRAM) { - if (pscf->responses == NGX_MAX_INT32_VALUE) { + + if (pscf->responses == NGX_MAX_INT32_VALUE + || (u->responses >= pscf->responses * u->requests)) + { /* * successfully terminate timed out UDP session - * with unspecified number of responses + * if expected number of responses was received */ handler = c->log->handler; @@ -1609,7 +1624,7 @@ if (from_upstream) { if (u->state->first_byte_time == (ngx_msec_t) -1) { u->state->first_byte_time = ngx_current_msec - - u->state->response_time; + - u->start_time; } } @@ -1646,44 +1661,7 @@ c->log->action = "proxying connection"; - if (c->type == SOCK_DGRAM - && pscf->responses != NGX_MAX_INT32_VALUE - && u->responses >= pscf->responses * u->requests - && !src->buffered && dst && !dst->buffered) - { - handler = c->log->handler; - c->log->handler = NULL; - - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "udp done" - ", packets from/to client:%ui/%ui" - ", bytes from/to client:%O/%O" - ", bytes from/to upstream:%O/%O", - u->requests, u->responses, - s->received, c->sent, u->received, pc ? pc->sent : 0); - - c->log->handler = handler; - - ngx_stream_proxy_finalize(s, NGX_STREAM_OK); - return; - } - - if (c->type == SOCK_STREAM - && src->read->eof && dst && (dst->read->eof || !dst->buffered)) - { - handler = c->log->handler; - c->log->handler = NULL; - - ngx_log_error(NGX_LOG_INFO, c->log, 0, - "%s disconnected" - ", bytes from/to client:%O/%O" - ", bytes from/to upstream:%O/%O", - from_upstream ? "upstream" : "client", - s->received, c->sent, u->received, pc ? pc->sent : 0); - - c->log->handler = handler; - - ngx_stream_proxy_finalize(s, NGX_STREAM_OK); + if (ngx_stream_proxy_test_finalize(s, from_upstream) == NGX_OK) { return; } @@ -1710,6 +1688,87 @@ } +static ngx_int_t +ngx_stream_proxy_test_finalize(ngx_stream_session_t *s, + ngx_uint_t from_upstream) +{ + ngx_connection_t *c, *pc; + ngx_log_handler_pt handler; + ngx_stream_upstream_t *u; + ngx_stream_proxy_srv_conf_t *pscf; + + pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); + + c = s->connection; + u = s->upstream; + pc = u->connected ? u->peer.connection : NULL; + + if (c->type == SOCK_DGRAM) { + + if (pscf->requests && u->requests < pscf->requests) { + return NGX_DECLINED; + } + + if (pscf->requests) { + ngx_delete_udp_connection(c); + } + + if (pscf->responses == NGX_MAX_INT32_VALUE + || u->responses < pscf->responses * u->requests) + { + return NGX_DECLINED; + } + + if (pc == NULL || c->buffered || pc->buffered) { + return NGX_DECLINED; + } + + handler = c->log->handler; + c->log->handler = NULL; + + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "udp done" + ", packets from/to client:%ui/%ui" + ", bytes from/to client:%O/%O" + ", bytes from/to upstream:%O/%O", + u->requests, u->responses, + s->received, c->sent, u->received, pc ? pc->sent : 0); + + c->log->handler = handler; + + ngx_stream_proxy_finalize(s, NGX_STREAM_OK); + + return NGX_OK; + } + + /* c->type == SOCK_STREAM */ + + if (pc == NULL + || (!c->read->eof && !pc->read->eof) + || (!c->read->eof && c->buffered) + || (!pc->read->eof && pc->buffered)) + { + return NGX_DECLINED; + } + + handler = c->log->handler; + c->log->handler = NULL; + + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "%s disconnected" + ", bytes from/to client:%O/%O" + ", bytes from/to upstream:%O/%O", + from_upstream ? "upstream" : "client", + s->received, c->sent, u->received, pc ? pc->sent : 0); + + c->log->handler = handler; + + ngx_stream_proxy_finalize(s, NGX_STREAM_OK); + + return NGX_OK; +} + + static void ngx_stream_proxy_next_upstream(ngx_stream_session_t *s) { @@ -1800,7 +1859,9 @@ pc = u->peer.connection; if (u->state) { - u->state->response_time = ngx_current_msec - u->state->response_time; + if (u->state->response_time == (ngx_msec_t) -1) { + u->state->response_time = ngx_current_msec - u->start_time; + } if (pc) { u->state->bytes_received = u->received; @@ -1905,6 +1966,7 @@ conf->buffer_size = NGX_CONF_UNSET_SIZE; conf->upload_rate = NGX_CONF_UNSET_SIZE; conf->download_rate = NGX_CONF_UNSET_SIZE; + conf->requests = NGX_CONF_UNSET_UINT; conf->responses = NGX_CONF_UNSET_UINT; conf->next_upstream_tries = NGX_CONF_UNSET_UINT; conf->next_upstream = NGX_CONF_UNSET; @@ -1949,6 +2011,9 @@ ngx_conf_merge_size_value(conf->download_rate, prev->download_rate, 0); + ngx_conf_merge_uint_value(conf->requests, + prev->requests, 0); + ngx_conf_merge_uint_value(conf->responses, prev->responses, NGX_MAX_INT32_VALUE);
diff --git a/src/stream/ngx_stream_upstream.c b/src/stream/ngx_stream_upstream.c index 7feac43..eadcf9f 100644 --- a/src/stream/ngx_stream_upstream.c +++ b/src/stream/ngx_stream_upstream.c
@@ -267,24 +267,22 @@ for ( ;; ) { if (data == 1) { - if (state[i].first_byte_time == (ngx_msec_t) -1) { - *p++ = '-'; - goto next; - } - ms = state[i].first_byte_time; - } else if (data == 2 && state[i].connect_time != (ngx_msec_t) -1) { + } else if (data == 2) { ms = state[i].connect_time; } else { ms = state[i].response_time; } - ms = ngx_max(ms, 0); - p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000); + if (ms != -1) { + ms = ngx_max(ms, 0); + p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000); - next: + } else { + *p++ = '-'; + } if (++i == s->upstream_states->nelts) { break;
diff --git a/src/stream/ngx_stream_upstream.h b/src/stream/ngx_stream_upstream.h index 8931522..bf893f8 100644 --- a/src/stream/ngx_stream_upstream.h +++ b/src/stream/ngx_stream_upstream.h
@@ -130,6 +130,7 @@ time_t start_sec; ngx_uint_t requests; ngx_uint_t responses; + ngx_msec_t start_time; ngx_str_t ssl_name;
diff --git a/src/stream/ngx_stream_write_filter_module.c b/src/stream/ngx_stream_write_filter_module.c index 8fdcd37..24326c6 100644 --- a/src/stream/ngx_stream_write_filter_module.c +++ b/src/stream/ngx_stream_write_filter_module.c
@@ -104,7 +104,6 @@ cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); -#if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "zero size buf in writer " @@ -122,7 +121,24 @@ ngx_debug_point(); return NGX_ERROR; } -#endif + + if (ngx_buf_size(cl->buf) < 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "negative size buf in writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + return NGX_ERROR; + } size += ngx_buf_size(cl->buf); @@ -160,7 +176,6 @@ cl->buf->file_pos, cl->buf->file_last - cl->buf->file_pos); -#if 1 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "zero size buf in writer " @@ -178,7 +193,24 @@ ngx_debug_point(); return NGX_ERROR; } -#endif + + if (ngx_buf_size(cl->buf) < 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, + "negative size buf in writer " + "t:%d r:%d f:%d %p %p-%p %p %O-%O", + cl->buf->temporary, + cl->buf->recycled, + cl->buf->in_file, + cl->buf->start, + cl->buf->pos, + cl->buf->last, + cl->buf->file, + cl->buf->file_pos, + cl->buf->file_last); + + ngx_debug_point(); + return NGX_ERROR; + } size += ngx_buf_size(cl->buf);