Skip to content

Commit

Permalink
nginx 1.19.2
Browse files Browse the repository at this point in the history
  • Loading branch information
chronolaw committed Aug 14, 2020
2 parents 600d2b9 + 3765736 commit c90665e
Show file tree
Hide file tree
Showing 15 changed files with 376 additions and 139 deletions.
29 changes: 29 additions & 0 deletions nginx/CHANGES
Original file line number Diff line number Diff line change
@@ -1,4 +1,33 @@

Changes with nginx 1.19.2 11 Aug 2020

*) Change: now nginx starts closing keepalive connections before all
free worker connections are exhausted, and logs a warning about this
to the error log.

*) Change: optimization of client request body reading when using
chunked transfer encoding.

*) Bugfix: memory leak if the "ssl_ocsp" directive was used.

*) Bugfix: "zero size buf in output" alerts might appear in logs if a
FastCGI server returned an incorrect response; the bug had appeared
in 1.19.1.

*) Bugfix: a segmentation fault might occur in a worker process if
different large_client_header_buffers sizes were used in different
virtual servers.

*) Bugfix: SSL shutdown might not work.

*) Bugfix: "SSL_shutdown() failed (SSL: ... bad write retry)" messages
might appear in logs.

*) Bugfix: in the ngx_http_slice_module.

*) Bugfix: in the ngx_http_xslt_filter_module.


Changes with nginx 1.19.1 07 Jul 2020

*) Change: the "lingering_close", "lingering_time", and
Expand Down
29 changes: 29 additions & 0 deletions nginx/CHANGES.ru
Original file line number Diff line number Diff line change
@@ -1,4 +1,33 @@

Изменения в nginx 1.19.2 11.08.2020

*) Изменение: теперь nginx начинает закрывать keepalive-соединения, не
дожидаясь исчерпания всех свободных соединений, а также пишет об этом
предупреждение в лог ошибок.

*) Изменение: оптимизация чтения тела запроса при использовании chunked
transfer encoding.

*) Исправление: утечки памяти при использовании директивы ssl_ocsp.

*) Исправление: в логах могли появляться сообщения "zero size buf in
output", если FastCGI-сервер возвращал некорректный ответ; ошибка
появилась в 1.19.1.

*) Исправление: в рабочем процессе мог произойти segmentation fault,
если размеры large_client_header_buffers отличались в разных
виртуальных серверах.

*) Исправление: SSL shutdown мог не работать.

*) Исправление: в логах могли появляться сообщения "SSL_shutdown()
failed (SSL: ... bad write retry)".

*) Исправление: в модуле ngx_http_slice_module.

*) Исправление: в модуле ngx_http_xslt_filter_module.


Изменения в nginx 1.19.1 07.07.2020

*) Изменение: директивы lingering_close, lingering_time и
Expand Down
4 changes: 2 additions & 2 deletions nginx/src/core/nginx.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
// 1'015'005


#define nginx_version 1019001
#define NGINX_VERSION "1.19.1"
#define nginx_version 1019002
#define NGINX_VERSION "1.19.2"
#define NGINX_VER "nginx/" NGINX_VERSION

// nginx 1.7之后添加--build=Name选项
Expand Down
20 changes: 10 additions & 10 deletions nginx/src/core/ngx_buf.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,22 +144,22 @@ typedef struct {


// 检查多个标志位,确定缓冲区是否在内存里
#define ngx_buf_in_memory(b) (b->temporary || b->memory || b->mmap)
#define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !b->in_file)
#define ngx_buf_in_memory(b) ((b)->temporary || (b)->memory || (b)->mmap)
#define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !(b)->in_file)

// 起控制作用的特殊缓冲区
#define ngx_buf_special(b) \
((b->flush || b->last_buf || b->sync) \
&& !ngx_buf_in_memory(b) && !b->in_file)
(((b)->flush || (b)->last_buf || (b)->sync) \
&& !ngx_buf_in_memory(b) && !(b)->in_file)

#define ngx_buf_sync_only(b) \
(b->sync \
&& !ngx_buf_in_memory(b) && !b->in_file && !b->flush && !b->last_buf)
((b)->sync && !ngx_buf_in_memory(b) \
&& !(b)->in_file && !(b)->flush && !(b)->last_buf)

// 计算缓冲区的大小,会根据是否在内存里使用恰当的指针
#define ngx_buf_size(b) \
(ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos): \
(b->file_last - b->file_pos))
(ngx_buf_in_memory(b) ? (off_t) ((b)->last - (b)->pos): \
((b)->file_last - (b)->file_pos))

// 从内存池里分配一块size大小的缓冲区
// 并使用buf管理,注意temporary是1,可以修改
Expand All @@ -181,8 +181,8 @@ ngx_chain_t *ngx_alloc_chain_link(ngx_pool_t *pool);

// 释放链表节点,挂在空闲链表里
#define ngx_free_chain(pool, cl) \
cl->next = pool->chain; \
pool->chain = cl
(cl)->next = (pool)->chain; \
(pool)->chain = (cl)



Expand Down
39 changes: 27 additions & 12 deletions nginx/src/core/ngx_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -1246,20 +1246,17 @@ ngx_get_connection(ngx_socket_t s, ngx_log_t *log)

// 从全局变量ngx_cycle里获取空闲链接,即free_connections链表
// free_connections是空闲链表头指针
c = ngx_cycle->free_connections;

if (c == NULL) {
// 检查最多32个在可复用连接队列里的元素
// 设置为连接关闭c->close = 1;
// 调用事件的处理函数,里面会检查c->close
// 这样就会调用ngx_http_close_connection
// 释放连接,加入空闲链表,可以再次使用
ngx_drain_connections((ngx_cycle_t *) ngx_cycle);
// 检查最多32个在可复用连接队列里的元素
// 设置为连接关闭c->close = 1;
// 调用事件的处理函数,里面会检查c->close
// 这样就会调用ngx_http_close_connection
// 释放连接,加入空闲链表,可以再次使用
ngx_drain_connections((ngx_cycle_t *) ngx_cycle);

// 此时应该有了一些空闲连接
// 再次获取
c = ngx_cycle->free_connections;
}
// 此时应该有了一些空闲连接
// 再次获取
c = ngx_cycle->free_connections;

// 如果还没有获取到连接,那么就报错
if (c == NULL) {
Expand Down Expand Up @@ -1493,8 +1490,26 @@ ngx_drain_connections(ngx_cycle_t *cycle)
ngx_queue_t *q;
ngx_connection_t *c;

// 从全局变量ngx_cycle里获取空闲链接,即free_connections链表
// free_connections是空闲链表头指针

// 早期的nginx只检查32次,避免过多消耗时间
// 1.12改变了这个固定值
if (cycle->free_connection_n > cycle->connection_n / 16
|| cycle->reusable_connections_n == 0)
{
return;
}

if (cycle->connections_reuse_time != ngx_time()) {
cycle->connections_reuse_time = ngx_time();

ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
"%ui worker_connections are not enough, "
"reusing connections",
cycle->connection_n);
}

n = ngx_max(ngx_min(32, cycle->reusable_connections_n / 8), 1);

for (i = 0; i < n; i++) {
Expand Down
7 changes: 5 additions & 2 deletions nginx/src/core/ngx_cycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,7 @@ ngx_int_t
ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
{
size_t len;
ngx_int_t rc;
ngx_uint_t create;
ngx_file_t file;
u_char pid[NGX_INT64_LEN + 2];
Expand All @@ -1218,11 +1219,13 @@ ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
return NGX_ERROR;
}

rc = NGX_OK;

if (!ngx_test_config) {
len = ngx_snprintf(pid, NGX_INT64_LEN + 2, "%P%N", ngx_pid) - pid;

if (ngx_write_file(&file, pid, len, 0) == NGX_ERROR) {
return NGX_ERROR;
rc = NGX_ERROR;
}
}

Expand All @@ -1231,7 +1234,7 @@ ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
ngx_close_file_n " \"%s\" failed", file.name.data);
}

return NGX_OK;
return rc;
}


Expand Down
1 change: 1 addition & 0 deletions nginx/src/core/ngx_cycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ struct ngx_cycle_s {
// 复用连接对象队列
ngx_queue_t reusable_connections_queue;
ngx_uint_t reusable_connections_n;
time_t connections_reuse_time;

// 监听的端口数组, in ngx_connection.h
// 主要成员: fd,backlog,rcvbuf,sndbuf
Expand Down
79 changes: 48 additions & 31 deletions nginx/src/event/ngx_event_openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2795,8 +2795,9 @@ ngx_ssl_free_buffer(ngx_connection_t *c)
ngx_int_t
ngx_ssl_shutdown(ngx_connection_t *c)
{
int n, sslerr, mode;
ngx_err_t err;
int n, sslerr, mode;
ngx_err_t err;
ngx_uint_t tries;

ngx_ssl_ocsp_cleanup(c);

Expand Down Expand Up @@ -2837,55 +2838,71 @@ ngx_ssl_shutdown(ngx_connection_t *c)

ngx_ssl_clear_error(c->log);

n = SSL_shutdown(c->ssl->connection);
tries = 2;

for ( ;; ) {

/*
* For bidirectional shutdown, SSL_shutdown() needs to be called
* twice: first call sends the "close notify" alert and returns 0,
* second call waits for the peer's "close notify" alert.
*/

ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);
n = SSL_shutdown(c->ssl->connection);

sslerr = 0;
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n);

/* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */
if (n == 1) {
SSL_free(c->ssl->connection);
c->ssl = NULL;

return NGX_OK;
}

if (n == 0 && tries-- > 1) {
continue;
}

/* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */

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 == 0 || sslerr == SSL_ERROR_ZERO_RETURN) {
SSL_free(c->ssl->connection);
c->ssl = NULL;
if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
c->read->handler = ngx_ssl_shutdown_handler;
c->write->handler = ngx_ssl_shutdown_handler;

return NGX_OK;
}
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
}

if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) {
c->read->handler = ngx_ssl_shutdown_handler;
c->write->handler = ngx_ssl_shutdown_handler;
if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
}

if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
return NGX_ERROR;
}
ngx_add_timer(c->read, 3000);

if (ngx_handle_write_event(c->write, 0) != NGX_OK) {
return NGX_ERROR;
return NGX_AGAIN;
}

if (sslerr == SSL_ERROR_WANT_READ) {
ngx_add_timer(c->read, 30000);
}
if (sslerr == SSL_ERROR_ZERO_RETURN || ERR_peek_error() == 0) {
SSL_free(c->ssl->connection);
c->ssl = NULL;

return NGX_AGAIN;
}
return NGX_OK;
}

err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;
err = (sslerr == SSL_ERROR_SYSCALL) ? ngx_errno : 0;

ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");
ngx_ssl_connection_error(c, sslerr, err, "SSL_shutdown() failed");

SSL_free(c->ssl->connection);
c->ssl = NULL;
SSL_free(c->ssl->connection);
c->ssl = NULL;

return NGX_ERROR;
return NGX_ERROR;
}
}


Expand Down
9 changes: 9 additions & 0 deletions nginx/src/event/ngx_event_openssl_stapling.c
Original file line number Diff line number Diff line change
Expand Up @@ -883,6 +883,7 @@ ngx_ssl_ocsp_validate(ngx_connection_t *c)

ocsp = ngx_pcalloc(c->pool, sizeof(ngx_ssl_ocsp_t));
if (ocsp == NULL) {
X509_free(cert);
return NGX_ERROR;
}

Expand All @@ -899,6 +900,7 @@ ngx_ssl_ocsp_validate(ngx_connection_t *c)
if (ocsp->certs) {
ocsp->certs = X509_chain_up_ref(ocsp->certs);
if (ocsp->certs == NULL) {
X509_free(cert);
return NGX_ERROR;
}
}
Expand All @@ -910,13 +912,15 @@ ngx_ssl_ocsp_validate(ngx_connection_t *c)
if (store == NULL) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"SSL_CTX_get_cert_store() failed");
X509_free(cert);
return NGX_ERROR;
}

store_ctx = X509_STORE_CTX_new();
if (store_ctx == NULL) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"X509_STORE_CTX_new() failed");
X509_free(cert);
return NGX_ERROR;
}

Expand All @@ -926,13 +930,15 @@ ngx_ssl_ocsp_validate(ngx_connection_t *c)
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"X509_STORE_CTX_init() failed");
X509_STORE_CTX_free(store_ctx);
X509_free(cert);
return NGX_ERROR;
}

rc = X509_verify_cert(store_ctx);
if (rc <= 0) {
ngx_ssl_error(NGX_LOG_ERR, c->log, 0, "X509_verify_cert() failed");
X509_STORE_CTX_free(store_ctx);
X509_free(cert);
return NGX_ERROR;
}

Expand All @@ -941,12 +947,15 @@ ngx_ssl_ocsp_validate(ngx_connection_t *c)
ngx_ssl_error(NGX_LOG_ERR, c->log, 0,
"X509_STORE_CTX_get1_chain() failed");
X509_STORE_CTX_free(store_ctx);
X509_free(cert);
return NGX_ERROR;
}

X509_STORE_CTX_free(store_ctx);
}

X509_free(cert);

ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
"ssl ocsp validate, certs:%d", sk_X509_num(ocsp->certs));

Expand Down
Loading

0 comments on commit c90665e

Please sign in to comment.