Merge branch 'nginx' (nginx-1.11.13).
Change-Id: I09f3e38baa909424d0c9ee898b8486cec97ea303
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
diff --git a/.hgtags b/.hgtags
index f56b37f..818243e 100644
--- a/.hgtags
+++ b/.hgtags
@@ -411,3 +411,4 @@
1ad0999a7ded3d4fb01c7acf8ff57c80b643da7e release-1.11.10
d8b321a876d6254e9e98795e3b194ef053290354 release-1.11.11
7f394e433f0003222aa6531931ecc0b24740d5e4 release-1.11.12
+3d0e8655f897959e48cc74e87670bb5492a58871 release-1.11.13
diff --git a/BUILD b/BUILD
index ae282e2..55656bf 100644
--- a/BUILD
+++ b/BUILD
@@ -1468,5 +1468,5 @@
preinst = "@nginx_pkgoss//:debian_preinst",
prerm = "@nginx_pkgoss//:debian_prerm",
section = "httpd",
- version = "1.11.12",
+ version = "1.11.13",
)
diff --git a/build.bzl b/build.bzl
index 38e8c35..42b6b32 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 = "6875999d1ccf62b0ecdc3cbad5f3b0a0c6f4069d", # nginx-1.11.12
+ commit = "5ca52610ad80ed63446d4b833ffc4a7f9130d230", # nginx-1.11.13
remote = "https://nginx.googlesource.com/nginx-pkgoss",
)
diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml
index 6106043..ea39ab2 100644
--- a/docs/xml/nginx/changes.xml
+++ b/docs/xml/nginx/changes.xml
@@ -5,6 +5,97 @@
<change_log title="nginx">
+<changes ver="1.11.13" date="2017-04-04">
+
+<change type="feature">
+<para lang="ru">
+параметр http_429 в директивах proxy_next_upstream, fastcgi_next_upstream,
+scgi_next_upstream и uwsgi_next_upstream.<br/>
+Спасибо Piotr Sikora.
+</para>
+<para lang="en">
+the "http_429" parameter of the "proxy_next_upstream", "fastcgi_next_upstream",
+"scgi_next_upstream", and "uwsgi_next_upstream" directives.<br/>
+Thanks to Piotr Sikora.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+в обработке ошибок выделения памяти.
+</para>
+<para lang="en">
+in memory allocation error handling.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+при использовании директив sendfile и timer_resolution на Linux
+запросы могли зависать.
+</para>
+<para lang="en">
+requests might hang
+when using the "sendfile" and "timer_resolution" directives on Linux.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+при использовании с подзапросами директив sendfile и aio_write
+запросы могли зависать.
+</para>
+<para lang="en">
+requests might hang
+when using the "sendfile" and "aio_write" directives with subrequests.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+в модуле ngx_http_v2_module.<br/>
+Спасибо Piotr Sikora.
+</para>
+<para lang="en">
+in the ngx_http_v2_module.<br/>
+Thanks to Piotr Sikora.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+при использовании HTTP/2 в рабочем процессе мог произойти segmentation fault.
+</para>
+<para lang="en">
+a segmentation fault might occur in a worker process when using HTTP/2.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+запросы могли зависать
+при использовании с подзапросами директив limit_rate, sendfile_max_chunk,
+limit_req или метода $r->sleep() встроенного перла.
+</para>
+<para lang="en">
+requests might hang
+when using the "limit_rate", "sendfile_max_chunk", "limit_req" directives,
+or the $r->sleep() embedded perl method with subrequests.
+</para>
+</change>
+
+<change type="bugfix">
+<para lang="ru">
+в модуле ngx_http_slice_module.
+</para>
+<para lang="en">
+in the ngx_http_slice_module.
+</para>
+</change>
+
+</changes>
+
+
<changes ver="1.11.12" date="2017-03-24">
<change type="bugfix">
diff --git a/src/core/nginx.h b/src/core/nginx.h
index eb5bf53..12d96ee 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -13,8 +13,8 @@
#define NGINX_NAME "nginx"
#endif
-#define nginx_version 1011012
-#define NGINX_VERSION "1.11.12"
+#define nginx_version 1011013
+#define NGINX_VERSION "1.11.13"
#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 3dfdf2e..aee7a58 100644
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -115,16 +115,14 @@
n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10;
- cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));
- if (cycle->paths.elts == NULL) {
+ if (ngx_array_init(&cycle->paths, pool, n, sizeof(ngx_path_t *))
+ != NGX_OK)
+ {
ngx_destroy_pool(pool);
return NULL;
}
- cycle->paths.nelts = 0;
- cycle->paths.size = sizeof(ngx_path_t *);
- cycle->paths.nalloc = n;
- cycle->paths.pool = pool;
+ ngx_memzero(cycle->paths.elts, n * sizeof(ngx_path_t *));
if (ngx_array_init(&cycle->config_dump, pool, 1, sizeof(ngx_conf_dump_t))
@@ -175,16 +173,14 @@
n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
- cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
- if (cycle->listening.elts == NULL) {
+ if (ngx_array_init(&cycle->listening, pool, n, sizeof(ngx_listening_t))
+ != NGX_OK)
+ {
ngx_destroy_pool(pool);
return NULL;
}
- cycle->listening.nelts = 0;
- cycle->listening.size = sizeof(ngx_listening_t);
- cycle->listening.nalloc = n;
- cycle->listening.pool = pool;
+ ngx_memzero(cycle->listening.elts, n * sizeof(ngx_listening_t));
ngx_queue_init(&cycle->reusable_connections_queue);
@@ -768,15 +764,15 @@
}
n = 10;
- ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool,
- n * sizeof(ngx_cycle_t *));
- if (ngx_old_cycles.elts == NULL) {
+
+ if (ngx_array_init(&ngx_old_cycles, ngx_temp_pool, n,
+ sizeof(ngx_cycle_t *))
+ != NGX_OK)
+ {
exit(1);
}
- ngx_old_cycles.nelts = 0;
- ngx_old_cycles.size = sizeof(ngx_cycle_t *);
- ngx_old_cycles.nalloc = n;
- ngx_old_cycles.pool = ngx_temp_pool;
+
+ ngx_memzero(ngx_old_cycles.elts, n * sizeof(ngx_cycle_t *));
ngx_cleaner_event.handler = ngx_clean_old_cycles;
ngx_cleaner_event.log = cycle->log;
diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c
index 71c4f17..8237fef 100644
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -500,8 +500,7 @@
#endif
shm.size = size;
- shm.name.len = sizeof("nginx_shared_zone") - 1;
- shm.name.data = (u_char *) "nginx_shared_zone";
+ ngx_str_set(&shm.name, "nginx_shared_zone");
shm.log = cycle->log;
if (ngx_shm_alloc(&shm) != NGX_OK) {
diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c
index d3544db..c144b31 100644
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -217,13 +217,13 @@
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
{
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, of.err,
- "%s \"%s\" failed", of.failed, path.data);
-
if (of.err == 0) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, of.err,
+ "%s \"%s\" failed", of.failed, path.data);
+
#if (NGX_HAVE_OPENAT)
if (of.err == NGX_EMLINK
|| of.err == NGX_ELOOP)
diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c
index ec3aadf..9e7def8 100644
--- a/src/http/modules/ngx_http_limit_req_module.c
+++ b/src/http/modules/ngx_http_limit_req_module.c
@@ -276,6 +276,8 @@
r->read_event_handler = ngx_http_test_reading;
r->write_event_handler = ngx_http_limit_req_delay;
+
+ r->connection->write->delayed = 1;
ngx_add_timer(r->connection->write, delay);
return NGX_AGAIN;
@@ -292,7 +294,7 @@
wev = r->connection->write;
- if (!wev->timedout) {
+ if (wev->delayed) {
if (ngx_handle_write_event(wev, 0) != NGX_OK) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -301,8 +303,6 @@
return;
}
- wev->timedout = 0;
-
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c
index 330dc7e..917ed55 100644
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -552,6 +552,11 @@
if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool)
!= NGX_OK)
{
+ if (of.err == 0) {
+ /* simulate successful logging */
+ return len;
+ }
+
ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
"%s \"%s\" failed", of.failed, log.data);
/* simulate successful logging */
diff --git a/src/http/modules/ngx_http_slice_filter_module.c b/src/http/modules/ngx_http_slice_filter_module.c
index 2005939..7758342 100644
--- a/src/http/modules/ngx_http_slice_filter_module.c
+++ b/src/http/modules/ngx_http_slice_filter_module.c
@@ -11,23 +11,25 @@
typedef struct {
- size_t size;
+ size_t size;
} ngx_http_slice_loc_conf_t;
typedef struct {
- off_t start;
- off_t end;
- ngx_str_t range;
- ngx_str_t etag;
- ngx_uint_t last; /* unsigned last:1; */
+ off_t start;
+ off_t end;
+ ngx_str_t range;
+ ngx_str_t etag;
+ unsigned last:1;
+ unsigned active:1;
+ ngx_http_request_t *sr;
} ngx_http_slice_ctx_t;
typedef struct {
- off_t start;
- off_t end;
- off_t complete_length;
+ off_t start;
+ off_t end;
+ off_t complete_length;
} ngx_http_slice_content_range_t;
@@ -169,6 +171,7 @@
}
ctx->start = end;
+ ctx->active = 1;
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.status_line.len = 0;
@@ -209,7 +212,6 @@
{
ngx_int_t rc;
ngx_chain_t *cl;
- ngx_http_request_t *sr;
ngx_http_slice_ctx_t *ctx;
ngx_http_slice_loc_conf_t *slcf;
@@ -234,6 +236,16 @@
return rc;
}
+ if (ctx->sr && !ctx->sr->done) {
+ return rc;
+ }
+
+ if (!ctx->active) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "missing slice response");
+ return NGX_ERROR;
+ }
+
if (ctx->start >= ctx->end) {
ngx_http_set_ctx(r, NULL, ngx_http_slice_filter_module);
ngx_http_send_special(r, NGX_HTTP_LAST);
@@ -244,14 +256,14 @@
return rc;
}
- if (ngx_http_subrequest(r, &r->uri, &r->args, &sr, NULL,
+ if (ngx_http_subrequest(r, &r->uri, &r->args, &ctx->sr, NULL,
NGX_HTTP_SUBREQUEST_CLONE)
!= NGX_OK)
{
return NGX_ERROR;
}
- ngx_http_set_ctx(sr, ctx, ngx_http_slice_filter_module);
+ ngx_http_set_ctx(ctx->sr, ctx, ngx_http_slice_filter_module);
slcf = ngx_http_get_module_loc_conf(r, ngx_http_slice_filter_module);
@@ -259,6 +271,8 @@
ctx->start + (off_t) slcf->size - 1)
- ctx->range.data;
+ ctx->active = 0;
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http slice subrequest: \"%V\"", &ctx->range);
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index 287d16e..865346a 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -1001,6 +1001,7 @@
ctx->next = SvRV(ST(2));
+ r->connection->write->delayed = 1;
ngx_add_timer(r->connection->write, sleep);
r->write_event_handler = ngx_http_perl_sleep_handler;
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index 2796319..6d3be91 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -278,15 +278,16 @@
wev = r->connection->write;
- if (wev->timedout) {
- wev->timedout = 0;
- ngx_http_perl_handle_request(r);
+ if (wev->delayed) {
+
+ if (ngx_handle_write_event(wev, 0) != NGX_OK) {
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ }
+
return;
}
- if (ngx_handle_write_event(wev, 0) != NGX_OK) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- }
+ ngx_http_perl_handle_request(r);
}
diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c
index c696fb6..c8ad5da 100644
--- a/src/http/ngx_http_copy_filter_module.c
+++ b/src/http/ngx_http_copy_filter_module.c
@@ -187,15 +187,24 @@
ngx_http_copy_aio_event_handler(ngx_event_t *ev)
{
ngx_event_aio_t *aio;
+ ngx_connection_t *c;
ngx_http_request_t *r;
aio = ev->data;
r = aio->data;
+ c = r->connection;
+
+ ngx_http_set_log_request(c->log, r);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http aio: \"%V?%V\"", &r->uri, &r->args);
r->main->blocked--;
r->aio = 0;
- r->connection->write->handler(r->connection->write);
+ r->write_event_handler(r);
+
+ ngx_http_run_posted_requests(c);
}
@@ -300,14 +309,33 @@
static void
ngx_http_copy_thread_event_handler(ngx_event_t *ev)
{
+ ngx_connection_t *c;
ngx_http_request_t *r;
r = ev->data;
+ c = r->connection;
+
+ ngx_http_set_log_request(c->log, r);
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
+ "http thread: \"%V?%V\"", &r->uri, &r->args);
r->main->blocked--;
r->aio = 0;
- r->connection->write->handler(r->connection->write);
+ if (r->done) {
+ /*
+ * trigger connection event handler if the subrequest was
+ * already finalized; this can happen if the handler is used
+ * for sendfile() in threads
+ */
+
+ c->write->handler(c->write);
+
+ } else {
+ r->write_event_handler(r);
+ ngx_http_run_posted_requests(c);
+ }
}
#endif
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 9ab2e1f..734e1d8 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1314,6 +1314,11 @@
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
{
+ if (of.err == 0) {
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_OK;
+ }
+
if (of.err != NGX_ENOENT
&& of.err != NGX_ENOTDIR
&& of.err != NGX_ENAMETOOLONG)
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index a9a9206..9ede5c6 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -2285,6 +2285,11 @@
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http run request: \"%V?%V\"", &r->uri, &r->args);
+ if (ev->delayed && ev->timedout) {
+ ev->delayed = 0;
+ ev->timedout = 0;
+ }
+
if (ev->write) {
r->write_event_handler(r);
@@ -2694,7 +2699,7 @@
static void
ngx_http_writer(ngx_http_request_t *r)
{
- int rc;
+ ngx_int_t rc;
ngx_event_t *wev;
ngx_connection_t *c;
ngx_http_core_loc_conf_t *clcf;
@@ -2708,34 +2713,22 @@
clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
if (wev->timedout) {
- if (!wev->delayed) {
- ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
- "client timed out");
- c->timedout = 1;
+ ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
+ "client timed out");
+ c->timedout = 1;
- ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
- return;
- }
-
- wev->timedout = 0;
- wev->delayed = 0;
-
- if (!wev->ready) {
- ngx_add_timer(wev, clcf->send_timeout);
-
- if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
- ngx_http_close_request(r, 0);
- }
-
- return;
- }
-
+ ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
+ return;
}
if (wev->delayed || r->aio) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
"http writer delayed");
+ if (!wev->delayed) {
+ ngx_add_timer(wev, clcf->send_timeout);
+ }
+
if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
ngx_http_close_request(r, 0);
}
@@ -2746,7 +2739,7 @@
rc = ngx_http_output_filter(r, NULL);
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "http writer output filter: %d, \"%V?%V\"",
+ "http writer output filter: %i, \"%V?%V\"",
rc, &r->uri, &r->args);
if (rc == NGX_ERROR) {
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index cc4d679..96f3ec6 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -1513,6 +1513,12 @@
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
{
+ if (of.err == 0) {
+ e->ip = ngx_http_script_exit;
+ e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ return;
+ }
+
if (of.err != NGX_ENOENT
&& of.err != NGX_ENOTDIR
&& of.err != NGX_ENAMETOOLONG)
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index d04dbbb..9e1f3b0 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -1247,6 +1247,11 @@
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
"http upstream request: \"%V?%V\"", &r->uri, &r->args);
+ if (ev->delayed && ev->timedout) {
+ ev->delayed = 0;
+ ev->timedout = 0;
+ }
+
if (ev->write) {
u->write_event_handler(r, u);
@@ -3805,9 +3810,19 @@
r->main->blocked--;
r->aio = 0;
- r->write_event_handler(r);
+ if (r->done) {
+ /*
+ * trigger connection event handler if the subrequest was
+ * already finalized; this can happen if the handler is used
+ * for sendfile() in threads
+ */
- ngx_http_run_posted_requests(c);
+ c->write->handler(c->write);
+
+ } else {
+ r->write_event_handler(r);
+ ngx_http_run_posted_requests(c);
+ }
}
#endif
@@ -3855,31 +3870,9 @@
if (wev->timedout) {
- if (wev->delayed) {
-
- wev->timedout = 0;
- wev->delayed = 0;
-
- if (!wev->ready) {
- ngx_add_timer(wev, p->send_timeout);
-
- if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
- ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
- }
-
- return;
- }
-
- if (ngx_event_pipe(p, wev->write) == NGX_ABORT) {
- ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
- return;
- }
-
- } else {
- p->downstream_error = 1;
- c->timedout = 1;
- ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
- }
+ p->downstream_error = 1;
+ c->timedout = 1;
+ ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
} else {
@@ -3924,30 +3917,8 @@
if (rev->timedout) {
- if (rev->delayed) {
-
- rev->timedout = 0;
- rev->delayed = 0;
-
- if (!rev->ready) {
- ngx_add_timer(rev, p->read_timeout);
-
- if (ngx_handle_read_event(rev, 0) != NGX_OK) {
- ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
- }
-
- return;
- }
-
- if (ngx_event_pipe(p, 0) == NGX_ABORT) {
- ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
- return;
- }
-
- } else {
- p->upstream_error = 1;
- ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
- }
+ p->upstream_error = 1;
+ ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
} else {
@@ -4184,8 +4155,7 @@
if (u->peer.sockaddr) {
if (ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_403
- || ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404
- || ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_429)
+ || ft_type == NGX_HTTP_UPSTREAM_FT_HTTP_404)
{
state = NGX_PEER_NEXT;
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c
index 34f0dac..4910ad8 100644
--- a/src/http/v2/ngx_http_v2.c
+++ b/src/http/v2/ngx_http_v2.c
@@ -817,7 +817,7 @@
NGX_HTTP_V2_PROTOCOL_ERROR);
}
- h2c->state.length -= h2c->state.padding + 1;
+ h2c->state.length -= 1 + h2c->state.padding;
}
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
@@ -942,7 +942,7 @@
if (size >= h2c->state.length) {
size = h2c->state.length;
- stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
+ stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG;
}
r = stream->request;
@@ -1910,7 +1910,7 @@
if (node == NULL || node->stream == NULL) {
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
- "unknown http2 stream");
+ "unknown http2 stream");
return ngx_http_v2_state_complete(h2c, pos, end);
}
@@ -2048,6 +2048,7 @@
break;
case NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING:
+
if (value > NGX_HTTP_V2_MAX_FRAME_SIZE
|| value < NGX_HTTP_V2_DEFAULT_FRAME_SIZE)
{
@@ -3133,7 +3134,7 @@
}
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "client sent unknown pseudo header \"%V\"",
+ "client sent unknown pseudo-header \":%V\"",
&header->name);
return NGX_DECLINED;
@@ -3280,14 +3281,14 @@
{
if (r->schema_start) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "client sent duplicate :schema header");
+ "client sent duplicate :scheme header");
return NGX_DECLINED;
}
if (header->value.len == 0) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "client sent empty :schema header");
+ "client sent empty :scheme header");
return NGX_DECLINED;
}
@@ -4194,6 +4195,14 @@
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
"http2 handle connection handler");
+ c = rev->data;
+ h2c = c->data;
+
+ if (c->error) {
+ ngx_http_v2_finalize_connection(h2c, 0);
+ return;
+ }
+
rev->handler = ngx_http_v2_read_handler;
if (rev->ready) {
@@ -4201,9 +4210,6 @@
return;
}
- c = rev->data;
- h2c = c->data;
-
if (h2c->last_out && ngx_http_v2_send_output_queue(h2c) == NGX_ERROR) {
ngx_http_v2_finalize_connection(h2c, 0);
return;
@@ -4326,7 +4332,10 @@
if (stream->queued) {
stream->queued = 0;
+
ev = fc->write;
+ ev->active = 0;
+ ev->ready = 1;
} else {
ev = fc->read;
diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h
index cddfccd..7d2a2ea 100644
--- a/src/http/v2/ngx_http_v2.h
+++ b/src/http/v2/ngx_http_v2.h
@@ -249,8 +249,8 @@
{
ngx_http_v2_out_frame_t **out;
- for (out = &h2c->last_out; *out; out = &(*out)->next)
- {
+ for (out = &h2c->last_out; *out; out = &(*out)->next) {
+
if ((*out)->blocked || (*out)->stream == NULL) {
break;
}
diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c
index 3c0696a..b44724c 100644
--- a/src/os/unix/ngx_linux_sendfile_chain.c
+++ b/src/os/unix/ngx_linux_sendfile_chain.c
@@ -20,8 +20,8 @@
#error sendfile64() is required!
#endif
-static ngx_int_t ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file,
- size_t size, size_t *sent);
+static ssize_t ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file,
+ size_t size);
static void ngx_linux_sendfile_thread_handler(void *data, ngx_log_t *log);
#endif
@@ -56,10 +56,6 @@
ngx_chain_t *cl;
ngx_iovec_t header;
struct iovec headers[NGX_IOVS_PREALLOCATE];
-#if (NGX_THREADS)
- ngx_int_t rc;
- ngx_uint_t thread_handled, thread_complete;
-#endif
wev = c->write;
@@ -82,10 +78,6 @@
for ( ;; ) {
prev_send = send;
-#if (NGX_THREADS)
- thread_handled = 0;
- thread_complete = 0;
-#endif
/* create the iovec and coalesce the neighbouring bufs */
@@ -179,38 +171,19 @@
}
#endif
-#if (NGX_THREADS)
- if (file->file->thread_handler) {
- rc = ngx_linux_sendfile_thread(c, file, file_size, &sent);
+ n = ngx_linux_sendfile(c, file, file_size);
- switch (rc) {
- case NGX_OK:
- thread_handled = 1;
- break;
-
- case NGX_DONE:
- thread_complete = 1;
- break;
-
- case NGX_AGAIN:
- break;
-
- default: /* NGX_ERROR */
- return NGX_CHAIN_ERROR;
- }
-
- } else
-#endif
- {
- n = ngx_linux_sendfile(c, file, file_size);
-
- if (n == NGX_ERROR) {
- return NGX_CHAIN_ERROR;
- }
-
- sent = (n == NGX_AGAIN) ? 0 : n;
+ if (n == NGX_ERROR) {
+ return NGX_CHAIN_ERROR;
}
+ if (n == NGX_DONE) {
+ /* thread task posted */
+ return in;
+ }
+
+ sent = (n == NGX_AGAIN) ? 0 : n;
+
} else {
n = ngx_writev(c, &header);
@@ -225,21 +198,27 @@
in = ngx_chain_update_sent(in, sent);
- if ((size_t) (send - prev_send) != sent) {
-#if (NGX_THREADS)
- if (thread_handled) {
- return in;
- }
-
- if (thread_complete) {
- send = prev_send + sent;
- continue;
- }
-#endif
+ if (n == NGX_AGAIN) {
wev->ready = 0;
return in;
}
+ if ((size_t) (send - prev_send) != sent) {
+
+ /*
+ * sendfile() on Linux 4.3+ might be interrupted at any time,
+ * and provides no indication if it was interrupted or not,
+ * so we have to retry till an explicit EAGAIN
+ *
+ * sendfile() in threads can also report less bytes written
+ * than we are prepared to send now, since it was started in
+ * some point in the past, so we again have to retry
+ */
+
+ send = prev_send + sent;
+ continue;
+ }
+
if (send >= limit || in == NULL) {
return in;
}
@@ -258,6 +237,14 @@
ssize_t n;
ngx_err_t err;
+#if (NGX_THREADS)
+
+ if (file->file->thread_handler) {
+ return ngx_linux_sendfile_thread(c, file, size);
+ }
+
+#endif
+
#if (NGX_HAVE_SENDFILE64)
offset = file->file_pos;
#else
@@ -324,9 +311,8 @@
} ngx_linux_sendfile_ctx_t;
-static ngx_int_t
-ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size,
- size_t *sent)
+static ssize_t
+ngx_linux_sendfile_thread(ngx_connection_t *c, ngx_buf_t *file, size_t size)
{
ngx_event_t *wev;
ngx_thread_task_t *task;
@@ -356,10 +342,14 @@
task->event.complete = 0;
if (ctx->err == NGX_EAGAIN) {
- *sent = 0;
+ /*
+ * if wev->complete is set, this means that a write event
+ * happened while we were waiting for the thread task, so
+ * we have to retry sending even on EAGAIN
+ */
if (wev->complete) {
- return NGX_DONE;
+ return 0;
}
return NGX_AGAIN;
@@ -384,13 +374,7 @@
return NGX_ERROR;
}
- *sent = ctx->sent;
-
- if (ctx->sent == ctx->size || wev->complete) {
- return NGX_DONE;
- }
-
- return NGX_AGAIN;
+ return ctx->sent;
}
if (task->event.active && ctx->file == file) {
@@ -399,9 +383,7 @@
* or multiple calls of the next body filter from a filter
*/
- *sent = 0;
-
- return NGX_OK;
+ return NGX_DONE;
}
ctx->file = file;
@@ -414,9 +396,7 @@
return NGX_ERROR;
}
- *sent = 0;
-
- return NGX_OK;
+ return NGX_DONE;
}
diff --git a/src/stream/ngx_stream_log_module.c b/src/stream/ngx_stream_log_module.c
index 6b29340..466bdda 100644
--- a/src/stream/ngx_stream_log_module.c
+++ b/src/stream/ngx_stream_log_module.c
@@ -443,6 +443,11 @@
s->connection->pool)
!= NGX_OK)
{
+ if (of.err == 0) {
+ /* simulate successful logging */
+ return len;
+ }
+
ngx_log_error(NGX_LOG_CRIT, s->connection->log, ngx_errno,
"%s \"%s\" failed", of.failed, log.data);
/* simulate successful logging */