diff --git a/.hgtags b/.hgtags index a1e630018..40a72593c 100644 --- a/.hgtags +++ b/.hgtags @@ -466,3 +466,4 @@ bfbc52374adcbf2f9060afd62de940f6fab3bba5 release-1.21.2 2217a9c1d0b86026f22700b3c089545db1964f55 release-1.21.3 39be8a682c58308d9399cddd57e37f9fdb7bdf3e release-1.21.4 d986378168fd4d70e0121cabac274c560cca9bdf release-1.21.5 +714eb4b2c09e712fb2572a2164ce2bf67638ccac release-1.21.6 diff --git a/contrib/vim/syntax/nginx.vim b/contrib/vim/syntax/nginx.vim index 1b52d4869..6828cd3e5 100644 --- a/contrib/vim/syntax/nginx.vim +++ b/contrib/vim/syntax/nginx.vim @@ -5,6 +5,9 @@ if exists("b:current_syntax") finish end +let s:save_cpo = &cpo +set cpo&vim + " general syntax if has("patch-7.4.1142") @@ -2485,4 +2488,7 @@ hi def link ngxDirectiveThirdPartyDeprecated Error hi def link ngxListenOptions Keyword hi def link ngxListenOptionsDeprecated Error +let &cpo = s:save_cpo +unlet s:save_cpo + let b:current_syntax = "nginx" diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml index fd6da38ba..2f9c350e1 100644 --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,44 @@ + + + + +при использование EPOLLEXCLUSIVE на Linux +распределение клиентских соединений между рабочими процессами +было неравномерным. + + +when using EPOLLEXCLUSIVE on Linux +client connections were unevenly distributed +among worker processes. + + + + + +во время плавного завершения старых рабочих процессов +nginx возвращал в ответах строку заголовка "Connection: keep-alive". + + +nginx returned the "Connection: keep-alive" header line in responses +during graceful shutdown of old worker processes. + + + + + +в директиве ssl_session_ticket_key при использовании TLSv1.3. + + +in the "ssl_session_ticket_key" when using TLSv1.3. + + + + + + diff --git a/src/core/nginx.h b/src/core/nginx.h index 5ad6aff45..daac21e2c 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1021005 -#define NGINX_VERSION "1.21.5" +#define nginx_version 1021006 +#define NGINX_VERSION "1.21.6" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_rwlock.c b/src/core/ngx_rwlock.c index ed2b0f810..e7da8a8ec 100644 --- a/src/core/ngx_rwlock.c +++ b/src/core/ngx_rwlock.c @@ -89,22 +89,10 @@ ngx_rwlock_rlock(ngx_atomic_t *lock) void ngx_rwlock_unlock(ngx_atomic_t *lock) { - ngx_atomic_uint_t readers; - - readers = *lock; - - if (readers == NGX_RWLOCK_WLOCK) { + if (*lock == NGX_RWLOCK_WLOCK) { (void) ngx_atomic_cmp_set(lock, NGX_RWLOCK_WLOCK, 0); - return; - } - - for ( ;; ) { - - if (ngx_atomic_cmp_set(lock, readers, readers - 1)) { - return; - } - - readers = *lock; + } else { + (void) ngx_atomic_fetch_add(lock, -1); } } diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c index 5b246c015..aebc4541d 100644 --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -55,6 +55,7 @@ ngx_uint_t ngx_accept_events; ngx_uint_t ngx_accept_mutex_held; ngx_msec_t ngx_accept_mutex_delay; ngx_int_t ngx_accept_disabled; +ngx_uint_t ngx_use_exclusive_accept; #if (NGX_STAT_STUB) @@ -662,6 +663,8 @@ ngx_event_process_init(ngx_cycle_t *cycle) #endif + ngx_use_exclusive_accept = 0; + ngx_queue_init(&ngx_posted_accept_events); ngx_queue_init(&ngx_posted_next_events); ngx_queue_init(&ngx_posted_events); @@ -907,6 +910,8 @@ ngx_event_process_init(ngx_cycle_t *cycle) if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ccf->worker_processes > 1) { + ngx_use_exclusive_accept = 1; + if (ngx_add_event(rev, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT) == NGX_ERROR) { diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index 1d04ff56d..deac04e7b 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -462,6 +462,7 @@ extern ngx_uint_t ngx_accept_events; extern ngx_uint_t ngx_accept_mutex_held; extern ngx_msec_t ngx_accept_mutex_delay; extern ngx_int_t ngx_accept_disabled; +extern ngx_uint_t ngx_use_exclusive_accept; #if (NGX_STAT_STUB) diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index b05666c76..27038799d 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -11,6 +11,9 @@ static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all); +#if (NGX_HAVE_EPOLLEXCLUSIVE) +static void ngx_reorder_accept_events(ngx_listening_t *ls); +#endif static void ngx_close_accepted_connection(ngx_connection_t *c); @@ -314,6 +317,10 @@ ngx_event_accept(ngx_event_t *ev) } } while (ev->available); + +#if (NGX_HAVE_EPOLLEXCLUSIVE) + ngx_reorder_accept_events(ls); +#endif } @@ -420,6 +427,57 @@ ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all) } +#if (NGX_HAVE_EPOLLEXCLUSIVE) + +static void +ngx_reorder_accept_events(ngx_listening_t *ls) +{ + ngx_connection_t *c; + + /* + * Linux with EPOLLEXCLUSIVE usually notifies only the process which + * was first to add the listening socket to the epoll instance. As + * a result most of the connections are handled by the first worker + * process. To fix this, we re-add the socket periodically, so other + * workers will get a chance to accept connections. + */ + + if (!ngx_use_exclusive_accept) { + return; + } + +#if (NGX_HAVE_REUSEPORT) + + if (ls->reuseport) { + return; + } + +#endif + + c = ls->connection; + + if (c->requests++ % 16 != 0 + && ngx_accept_disabled <= 0) + { + return; + } + + if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT) + == NGX_ERROR) + { + return; + } + + if (ngx_add_event(c->read, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT) + == NGX_ERROR) + { + return; + } +} + +#endif + + static void ngx_close_accepted_connection(ngx_connection_t *c) { diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index ef9eec7be..60efdbfa7 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1383,6 +1383,9 @@ ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file) if (SSL_CTX_set0_tmp_dh_pkey(ssl->ctx, dh) != 1) { ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, "SSL_CTX_set0_tmp_dh_pkey(\%s\") failed", file->data); +#if (OPENSSL_VERSION_NUMBER >= 0x3000001fL) + EVP_PKEY_free(dh); +#endif BIO_free(bio); return NGX_ERROR; } @@ -4455,7 +4458,21 @@ ngx_ssl_session_ticket_key_callback(ngx_ssl_conn_t *ssl_conn, return -1; } - return (i == 0) ? 1 : 2 /* renew */; + /* renew if TLSv1.3 */ + +#ifdef TLS1_3_VERSION + if (SSL_version(ssl_conn) == TLS1_3_VERSION) { + return 2; + } +#endif + + /* renew if non-default key */ + + if (i != 0) { + return 2; + } + + return 1; } } diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c index 9b8940590..76f6e9629 100644 --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -197,6 +197,10 @@ ngx_http_header_filter(ngx_http_request_t *r) } } + if (r->keepalive && (ngx_terminate || ngx_exiting)) { + r->keepalive = 0; + } + len = sizeof("HTTP/1.x ") - 1 + sizeof(CRLF) - 1 /* the end of the header */ + sizeof(CRLF) - 1;