diff options
author | nginx <nginx@nginx.org> | 2015-04-07 15:42:39 +0000 |
---|---|---|
committer | Jon Kolb <kolbyjack@gmail.com> | 2015-04-07 15:42:39 +0000 |
commit | 6612579e5a1459b05960a31bbbcfe4cd5afc319a (patch) | |
tree | 6959ffbbb370e1aa938c169dec4e226c160c9d44 /src/http | |
parent | ae88e2338f6e27459ace8a23754afc5892c2c5be (diff) | |
download | nginx-1.7.tar.gz |
*) Feature: now the "tcp_nodelay" directive works with backend SSL
connections.
*) Feature: now thread pools can be used to read cache file headers.
*) Bugfix: in the "proxy_request_buffering" directive.
*) Bugfix: a segmentation fault might occur in a worker process when
using thread pools on Linux.
*) Bugfix: in error handling when using the "ssl_stapling" directive.
Thanks to Filipe da Silva.
*) Bugfix: in the ngx_http_spdy_module.
Diffstat (limited to 'src/http')
-rw-r--r-- | src/http/modules/ngx_http_headers_filter_module.c | 6 | ||||
-rw-r--r-- | src/http/modules/ngx_http_proxy_module.c | 7 | ||||
-rw-r--r-- | src/http/ngx_http_cache.h | 4 | ||||
-rw-r--r-- | src/http/ngx_http_file_cache.c | 124 | ||||
-rw-r--r-- | src/http/ngx_http_request_body.c | 2 | ||||
-rw-r--r-- | src/http/ngx_http_spdy.c | 111 | ||||
-rw-r--r-- | src/http/ngx_http_special_response.c | 4 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.c | 26 |
8 files changed, 197 insertions, 87 deletions
diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c index a10056903..a356814e4 100644 --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -378,7 +378,7 @@ ngx_http_parse_expires(ngx_str_t *value, ngx_http_expires_t *expires, } } - if (value->data[0] == '@') { + if (value->len && value->data[0] == '@') { value->data++; value->len--; minus = 0; @@ -390,12 +390,12 @@ ngx_http_parse_expires(ngx_str_t *value, ngx_http_expires_t *expires, *expires = NGX_HTTP_EXPIRES_DAILY; - } else if (value->data[0] == '+') { + } else if (value->len && value->data[0] == '+') { value->data++; value->len--; minus = 0; - } else if (value->data[0] == '-') { + } else if (value->len && value->data[0] == '-') { value->data++; value->len--; minus = 1; diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index d0b1c885d..00e8923a0 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -1503,7 +1503,7 @@ ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in) u_char *chunk; ngx_int_t rc; ngx_buf_t *b; - ngx_chain_t *out, *cl, *tl, **ll; + ngx_chain_t *out, *cl, *tl, **ll, **fl; ngx_http_proxy_ctx_t *ctx; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -1546,6 +1546,7 @@ ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in) size = 0; cl = in; + fl = ll; for ( ;; ) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -1602,8 +1603,8 @@ ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in) b->pos = chunk; b->last = ngx_sprintf(chunk, "%xO" CRLF, size); - tl->next = out; - out = tl; + tl->next = *fl; + *fl = tl; } if (cl->buf->last_buf) { diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h index a7d41c6f1..d36fa779c 100644 --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -91,6 +91,10 @@ struct ngx_http_cache_s { ngx_http_file_cache_t *file_cache; ngx_http_file_cache_node_t *node; +#if (NGX_THREADS) + ngx_thread_task_t *thread_task; +#endif + ngx_msec_t lock_timeout; ngx_msec_t lock_age; ngx_msec_t lock_time; diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index 52cbdda83..fc1476133 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -23,6 +23,11 @@ static ssize_t ngx_http_file_cache_aio_read(ngx_http_request_t *r, #if (NGX_HAVE_FILE_AIO) static void ngx_http_cache_aio_event_handler(ngx_event_t *ev); #endif +#if (NGX_THREADS) +static ngx_int_t ngx_http_cache_thread_handler(ngx_thread_task_t *task, + ngx_file_t *file); +static void ngx_http_cache_thread_event_handler(ngx_event_t *ev); +#endif static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c); static ngx_int_t ngx_http_file_cache_name(ngx_http_request_t *r, @@ -636,38 +641,49 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c) static ssize_t ngx_http_file_cache_aio_read(ngx_http_request_t *r, ngx_http_cache_t *c) { -#if (NGX_HAVE_FILE_AIO) +#if (NGX_HAVE_FILE_AIO || NGX_THREADS) ssize_t n; ngx_http_core_loc_conf_t *clcf; - if (!ngx_file_aio) { - goto noaio; - } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); +#endif - if (clcf->aio != NGX_HTTP_AIO_ON) { - goto noaio; - } +#if (NGX_HAVE_FILE_AIO) - n = ngx_file_aio_read(&c->file, c->buf->pos, c->body_start, 0, r->pool); + if (clcf->aio == NGX_HTTP_AIO_ON && ngx_file_aio) { + n = ngx_file_aio_read(&c->file, c->buf->pos, c->body_start, 0, r->pool); - if (n != NGX_AGAIN) { - c->reading = 0; - return n; + if (n != NGX_AGAIN) { + c->reading = 0; + return n; + } + + c->reading = 1; + + c->file.aio->data = r; + c->file.aio->handler = ngx_http_cache_aio_event_handler; + + r->main->blocked++; + r->aio = 1; + + return NGX_AGAIN; } - c->reading = 1; +#endif - c->file.aio->data = r; - c->file.aio->handler = ngx_http_cache_aio_event_handler; +#if (NGX_THREADS) - r->main->blocked++; - r->aio = 1; + if (clcf->aio == NGX_HTTP_AIO_THREADS) { + c->file.thread_handler = ngx_http_cache_thread_handler; + c->file.thread_ctx = r; - return NGX_AGAIN; + n = ngx_thread_read(&c->thread_task, &c->file, c->buf->pos, + c->body_start, 0, r->pool); -noaio: + c->reading = (n == NGX_AGAIN); + + return n; + } #endif @@ -704,6 +720,76 @@ ngx_http_cache_aio_event_handler(ngx_event_t *ev) #endif +#if (NGX_THREADS) + +static ngx_int_t +ngx_http_cache_thread_handler(ngx_thread_task_t *task, ngx_file_t *file) +{ + ngx_str_t name; + ngx_thread_pool_t *tp; + ngx_http_request_t *r; + ngx_http_core_loc_conf_t *clcf; + + r = file->thread_ctx; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + tp = clcf->thread_pool; + + if (tp == NULL) { + if (ngx_http_complex_value(r, clcf->thread_pool_value, &name) + != NGX_OK) + { + return NGX_ERROR; + } + + tp = ngx_thread_pool_get((ngx_cycle_t *) ngx_cycle, &name); + + if (tp == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "thread pool \"%V\" not found", &name); + return NGX_ERROR; + } + } + + task->event.data = r; + task->event.handler = ngx_http_cache_thread_event_handler; + + if (ngx_thread_task_post(tp, task) != NGX_OK) { + return NGX_ERROR; + } + + r->main->blocked++; + r->aio = 1; + + return NGX_OK; +} + + +static void +ngx_http_cache_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 file cache thread: \"%V?%V\"", &r->uri, &r->args); + + r->main->blocked--; + r->aio = 0; + + r->write_event_handler(r); + + ngx_http_run_posted_requests(c); +} + +#endif + + static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c) { diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index ac5b530ba..9c169845e 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -949,6 +949,7 @@ ngx_http_request_body_length_filter(ngx_http_request_t *r, ngx_chain_t *in) b->pos = cl->buf->pos; b->last = cl->buf->last; b->end = cl->buf->end; + b->flush = r->request_body_no_buffering; size = cl->buf->last - cl->buf->pos; @@ -1056,6 +1057,7 @@ ngx_http_request_body_chunked_filter(ngx_http_request_t *r, ngx_chain_t *in) b->pos = cl->buf->pos; b->last = cl->buf->last; b->end = cl->buf->end; + b->flush = r->request_body_no_buffering; *ll = tl; ll = &tl->next; diff --git a/src/http/ngx_http_spdy.c b/src/http/ngx_http_spdy.c index 13b81a63a..6bb79b88b 100644 --- a/src/http/ngx_http_spdy.c +++ b/src/http/ngx_http_spdy.c @@ -662,6 +662,7 @@ ngx_http_spdy_write_handler(ngx_event_t *wev) ngx_int_t ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc) { + int tcp_nodelay; ngx_chain_t *cl; ngx_event_t *wev; ngx_connection_t *c; @@ -700,20 +701,52 @@ ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc) cl = c->send_chain(c, cl, 0); if (cl == NGX_CHAIN_ERROR) { - c->error = 1; - - if (!sc->blocked) { - ngx_post_event(wev, &ngx_posted_events); - } - - return NGX_ERROR; + goto error; } clcf = ngx_http_get_module_loc_conf(sc->http_connection->conf_ctx, ngx_http_core_module); if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) { - return NGX_ERROR; /* FIXME */ + goto error; + } + + if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) { + if (ngx_tcp_push(c->fd) == -1) { + ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed"); + goto error; + } + + c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; + tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0; + + } else { + tcp_nodelay = 1; + } + + if (tcp_nodelay + && clcf->tcp_nodelay + && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) + { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) + == -1) + { +#if (NGX_SOLARIS) + /* Solaris returns EINVAL if a socket has been shut down */ + c->log_error = NGX_ERROR_IGNORE_EINVAL; +#endif + + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + + c->log_error = NGX_ERROR_INFO; + goto error; + } + + c->tcp_nodelay = NGX_TCP_NODELAY_SET; } if (cl) { @@ -751,6 +784,16 @@ ngx_http_spdy_send_output_queue(ngx_http_spdy_connection_t *sc) sc->last_out = frame; return NGX_OK; + +error: + + c->error = 1; + + if (!sc->blocked) { + ngx_post_event(wev, &ngx_posted_events); + } + + return NGX_ERROR; } @@ -3317,10 +3360,8 @@ ngx_http_spdy_close_stream_handler(ngx_event_t *ev) void ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc) { - int tcp_nodelay; ngx_event_t *ev; - ngx_connection_t *c, *fc; - ngx_http_core_loc_conf_t *clcf; + ngx_connection_t *fc; ngx_http_spdy_stream_t **index, *s; ngx_http_spdy_srv_conf_t *sscf; ngx_http_spdy_connection_t *sc; @@ -3346,54 +3387,6 @@ ngx_http_spdy_close_stream(ngx_http_spdy_stream_t *stream, ngx_int_t rc) { sc->connection->error = 1; } - - } else { - c = sc->connection; - - if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) { - if (ngx_tcp_push(c->fd) == -1) { - ngx_connection_error(c, ngx_socket_errno, - ngx_tcp_push_n " failed"); - c->error = 1; - tcp_nodelay = 0; - - } else { - c->tcp_nopush = NGX_TCP_NOPUSH_UNSET; - tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0; - } - - } else { - tcp_nodelay = 1; - } - - clcf = ngx_http_get_module_loc_conf(stream->request, - ngx_http_core_module); - - if (tcp_nodelay - && clcf->tcp_nodelay - && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) - { - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); - - if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, - (const void *) &tcp_nodelay, sizeof(int)) - == -1) - { -#if (NGX_SOLARIS) - /* Solaris returns EINVAL if a socket has been shut down */ - c->log_error = NGX_ERROR_IGNORE_EINVAL; -#endif - - ngx_connection_error(c, ngx_socket_errno, - "setsockopt(TCP_NODELAY) failed"); - - c->log_error = NGX_ERROR_INFO; - c->error = 1; - - } else { - c->tcp_nodelay = NGX_TCP_NODELAY_SET; - } - } } if (sc->stream == stream) { diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c index 546400539..a97791e8b 100644 --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -553,7 +553,7 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page) return NGX_ERROR; } - if (uri.data[0] == '/') { + if (uri.len && uri.data[0] == '/') { if (err_page->value.lengths) { ngx_http_split_args(r, &uri, &args); @@ -570,7 +570,7 @@ ngx_http_send_error_page(ngx_http_request_t *r, ngx_http_err_page_t *err_page) return ngx_http_internal_redirect(r, &uri, &args); } - if (uri.data[0] == '@') { + if (uri.len && uri.data[0] == '@') { return ngx_http_named_location(r, &uri); } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 0a04e611c..56091fa98 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1448,7 +1448,9 @@ static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_connection_t *c) { - ngx_int_t rc; + int tcp_nodelay; + ngx_int_t rc; + ngx_http_core_loc_conf_t *clcf; if (ngx_http_upstream_test_connect(c) != NGX_OK) { ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); @@ -1481,6 +1483,28 @@ ngx_http_upstream_ssl_init_connection(ngx_http_request_t *r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } + + /* abbreviated SSL handshake may interact badly with Nagle */ + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); + + tcp_nodelay = 1; + + if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, + (const void *) &tcp_nodelay, sizeof(int)) == -1) + { + ngx_connection_error(c, ngx_socket_errno, + "setsockopt(TCP_NODELAY) failed"); + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + c->tcp_nodelay = NGX_TCP_NODELAY_SET; + } } r->connection->log->action = "SSL handshaking to upstream"; |