# HG changeset patch # User Igor Sysoev # Date 1287345600 -14400 # Node ID c5122335e41d714c25792bcd57a6c42396d04c35 # Parent b2afd36d87f46247bdbe924e232a8fd7b95a6529 nginx 0.8.53 *) Feature: now the "error_page" directive allows to change a status code in a redirect. *) Feature: the "gzip_disable" directive supports special "degradation" mask. *) Bugfix: a socket leak might occurred if file AIO was used. Thanks to Maxim Dounin. *) Bugfix: if the first server had no "listen" directive and there was no explicit default server, then a next server with a "listen" directive became the default server; the bug had appeared in 0.8.21. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,20 @@ +Changes with nginx 0.8.53 18 Oct 2010 + + *) Feature: now the "error_page" directive allows to change a status + code in a redirect. + + *) Feature: the "gzip_disable" directive supports special "degradation" + mask. + + *) Bugfix: a socket leak might occurred if file AIO was used. + Thanks to Maxim Dounin. + + *) Bugfix: if the first server had no "listen" directive and there was + no explicit default server, then a next server with a "listen" + directive became the default server; the bug had appeared in 0.8.21. + + Changes with nginx 0.8.52 28 Sep 2010 *) Bugfix: nginx used SSL mode for a listen socket if any listen option @@ -131,7 +147,7 @@ Changes with nginx 0.8.44 *) Bugfix: compatibility with HP/UX. - *) Bugfix: compatibility with AIX xcl_r compiler. + *) Bugfix: compatibility with AIX xlC_r compiler. *) Bugfix: nginx treated large SSLv2 packets as plain requests. Thanks to Miroslaw Jaworski. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,22 @@ +Изменения в nginx 0.8.53 18.10.2010 + + *) Добавление: теперь директива error_page позволяет менять код статуса + у редиректа. + + *) Добавление: директива gzip_disable поддерживает специальную маску + degradation. + + *) Исправление: при использовании файлового AIO, могла происходить + утечка сокетов. + Спасибо Максиму Дунину. + + *) Исправление: если в первом сервере не была описана директива listen + и нигде явно не описан сервер по умолчанию, то сервером по умолчанию + становился следующий сервер с директивой listen; ошибка появилась в + 0.8.21. + + Изменения в nginx 0.8.52 28.09.2010 *) Исправление: nginx использовал режим SSL для listen сокета, если для @@ -129,7 +147,7 @@ *) Исправление: совместимость с HP/UX. - *) Исправление: совместимость с компилятором AIX xcl_r. + *) Исправление: совместимость с компилятором AIX xlC_r. *) Исправление: nginx считал большие пакеты SSLv2 как обычные текстовые запросы. diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -322,6 +322,7 @@ if [ $HTTP_SECURE_LINK = YES ]; then fi if [ $HTTP_DEGRADATION = YES ]; then + have=NGX_HTTP_DEGRADATION . auto/have HTTP_MODULES="$HTTP_MODULES $HTTP_DEGRADATION_MODULE" HTTP_SRCS="$HTTP_SRCS $HTTP_DEGRADATION_SRCS" fi diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,8 +8,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 8052 -#define NGINX_VERSION "0.8.52" +#define nginx_version 8053 +#define NGINX_VERSION "0.8.53" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -74,18 +74,18 @@ ngx_output_chain(ngx_output_chain_ctx_t } } -#if (NGX_HAVE_FILE_AIO) - if (ctx->aio) { - return NGX_AGAIN; - } -#endif - out = NULL; last_out = &out; last = NGX_NONE; for ( ;; ) { +#if (NGX_HAVE_FILE_AIO) + if (ctx->aio) { + return NGX_AGAIN; + } +#endif + while (ctx->in) { /* diff --git a/src/http/modules/ngx_http_degradation_module.c b/src/http/modules/ngx_http_degradation_module.c --- a/src/http/modules/ngx_http_degradation_module.c +++ b/src/http/modules/ngx_http_degradation_module.c @@ -86,25 +86,38 @@ ngx_module_t ngx_http_degradation_modul }; +static ngx_uint_t ngx_degraded; + + static ngx_int_t ngx_http_degradation_handler(ngx_http_request_t *r) { - time_t now; - static size_t sbrk_size; - static time_t sbrk_time; - ngx_http_degradation_loc_conf_t *dlcf; - ngx_http_degradation_main_conf_t *dmcf; + ngx_http_degradation_loc_conf_t *dlcf; dlcf = ngx_http_get_module_loc_conf(r, ngx_http_degradation_module); - if (dlcf->degrade == 0) { - return NGX_DECLINED; + if (dlcf->degrade && ngx_http_degraded(r)) { + return dlcf->degrade; } + return NGX_DECLINED; +} + + +ngx_uint_t +ngx_http_degraded(ngx_http_request_t *r) +{ + time_t now; + ngx_uint_t log; + static size_t sbrk_size; + static time_t sbrk_time; + ngx_http_degradation_main_conf_t *dmcf; + dmcf = ngx_http_get_module_main_conf(r, ngx_http_degradation_module); if (dmcf->sbrk_size) { + log = 0; now = ngx_time(); /* lock mutex */ @@ -120,19 +133,27 @@ ngx_http_degradation_handler(ngx_http_re sbrk_size = (size_t) sbrk(0) - ((uintptr_t) ngx_palloc & ~0x3FFFFF); sbrk_time = now; + log = 1; } /* unlock mutex */ if (sbrk_size >= dmcf->sbrk_size) { - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "degradation sbrk: %uz", sbrk_size); + ngx_degraded = 1; - return dlcf->degrade; + if (log) { + ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, + "degradation sbrk:%uzM", + sbrk_size / (1024 * 1024)); + } + + return 1; } } - return NGX_DECLINED; + ngx_degraded = 0; + + return 0; } diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -258,6 +258,18 @@ ngx_http_gzip_header_filter(ngx_http_req r->gzip_vary = 1; +#if (NGX_HTTP_DEGRADATION) + { + ngx_http_core_loc_conf_t *clcf; + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->gzip_disable_degradation && ngx_http_degraded(r)) { + return ngx_http_next_header_filter(r); + } + } +#endif + if (!r->gzip_tested) { if (ngx_http_gzip_ok(r) != NGX_OK) { return ngx_http_next_header_filter(r); diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c --- a/src/http/modules/ngx_http_limit_req_module.c +++ b/src/http/modules/ngx_http_limit_req_module.c @@ -51,7 +51,7 @@ typedef struct { static void ngx_http_limit_req_delay(ngx_http_request_t *r); static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, - ngx_uint_t hash, u_char *data, size_t len, ngx_http_limit_req_node_t **lrp); + ngx_uint_t hash, u_char *data, size_t len, ngx_uint_t *ep); static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n); @@ -186,25 +186,56 @@ ngx_http_limit_req_handler(ngx_http_requ ngx_http_limit_req_expire(ctx, 1); - rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &lr); - - if (lr) { - ngx_queue_remove(&lr->queue); - - ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); - - excess = lr->excess; - - } else { - excess = 0; - } + rc = ngx_http_limit_req_lookup(lrcf, hash, vv->data, len, &excess); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "limit_req: %i %ui.%03ui", rc, excess / 1000, excess % 1000); - if (rc == NGX_BUSY) { + if (rc == NGX_DECLINED) { + + n = offsetof(ngx_rbtree_node_t, color) + + offsetof(ngx_http_limit_req_node_t, data) + + len; + + node = ngx_slab_alloc_locked(ctx->shpool, n); + if (node == NULL) { + + ngx_http_limit_req_expire(ctx, 0); + + node = ngx_slab_alloc_locked(ctx->shpool, n); + if (node == NULL) { + ngx_shmtx_unlock(&ctx->shpool->mutex); + return NGX_HTTP_SERVICE_UNAVAILABLE; + } + } + + lr = (ngx_http_limit_req_node_t *) &node->color; + + node->key = hash; + lr->len = (u_char) len; + + tp = ngx_timeofday(); + lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); + + lr->excess = 0; + ngx_memcpy(lr->data, vv->data, len); + + ngx_rbtree_insert(&ctx->sh->rbtree, node); + + ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); + ngx_shmtx_unlock(&ctx->shpool->mutex); + return NGX_DECLINED; + } + + ngx_shmtx_unlock(&ctx->shpool->mutex); + + if (rc == NGX_OK) { + return NGX_DECLINED; + } + + if (rc == NGX_BUSY) { ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, "limiting requests, excess: %ui.%03ui by zone \"%V\"", excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name); @@ -212,71 +243,26 @@ ngx_http_limit_req_handler(ngx_http_requ return NGX_HTTP_SERVICE_UNAVAILABLE; } - if (rc == NGX_AGAIN) { - ngx_shmtx_unlock(&ctx->shpool->mutex); - - if (lrcf->nodelay) { - return NGX_DECLINED; - } - - ngx_log_error(lrcf->delay_log_level, r->connection->log, 0, - "delaying request, excess: %ui.%03ui, by zone \"%V\"", - excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name); + /* rc == NGX_AGAIN */ - if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - r->read_event_handler = ngx_http_test_reading; - r->write_event_handler = ngx_http_limit_req_delay; - ngx_add_timer(r->connection->write, - (ngx_msec_t) excess * 1000 / ctx->rate); - - return NGX_AGAIN; - } - - if (rc == NGX_OK) { - goto done; + if (lrcf->nodelay) { + return NGX_DECLINED; } - /* rc == NGX_DECLINED */ - - n = offsetof(ngx_rbtree_node_t, color) - + offsetof(ngx_http_limit_req_node_t, data) - + len; + ngx_log_error(lrcf->delay_log_level, r->connection->log, 0, + "delaying request, excess: %ui.%03ui, by zone \"%V\"", + excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name); - node = ngx_slab_alloc_locked(ctx->shpool, n); - if (node == NULL) { - - ngx_http_limit_req_expire(ctx, 0); - - node = ngx_slab_alloc_locked(ctx->shpool, n); - if (node == NULL) { - ngx_shmtx_unlock(&ctx->shpool->mutex); - return NGX_HTTP_SERVICE_UNAVAILABLE; - } + if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; } - lr = (ngx_http_limit_req_node_t *) &node->color; - - node->key = hash; - lr->len = (u_char) len; - - tp = ngx_timeofday(); - lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); + r->read_event_handler = ngx_http_test_reading; + r->write_event_handler = ngx_http_limit_req_delay; + ngx_add_timer(r->connection->write, + (ngx_msec_t) excess * 1000 / ctx->rate); - lr->excess = 0; - ngx_memcpy(lr->data, vv->data, len); - - ngx_rbtree_insert(&ctx->sh->rbtree, node); - - ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); - -done: - - ngx_shmtx_unlock(&ctx->shpool->mutex); - - return NGX_DECLINED; + return NGX_AGAIN; } @@ -356,7 +342,7 @@ ngx_http_limit_req_rbtree_insert_value(n static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_conf_t *lrcf, ngx_uint_t hash, - u_char *data, size_t len, ngx_http_limit_req_node_t **lrp) + u_char *data, size_t len, ngx_uint_t *ep) { ngx_int_t rc, excess; ngx_time_t *tp; @@ -391,6 +377,8 @@ ngx_http_limit_req_lookup(ngx_http_limit rc = ngx_memn2cmp(data, lr->data, len, (size_t) lr->len); if (rc == 0) { + ngx_queue_remove(&lr->queue); + ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); tp = ngx_timeofday(); @@ -403,16 +391,15 @@ ngx_http_limit_req_lookup(ngx_http_limit excess = 0; } + *ep = excess; + if ((ngx_uint_t) excess > lrcf->burst) { - *lrp = lr; return NGX_BUSY; } lr->excess = excess; lr->last = now; - *lrp = lr; - if (excess) { return NGX_AGAIN; } @@ -427,7 +414,7 @@ ngx_http_limit_req_lookup(ngx_http_limit break; } - *lrp = NULL; + *ep = 0; return NGX_DECLINED; } diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -48,7 +48,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.8.52'; +our $VERSION = '0.8.53'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -142,6 +142,10 @@ char *ngx_http_merge_types(ngx_conf_t *c ngx_int_t ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types, ngx_str_t *default_type); +#if (NGX_HTTP_DEGRADATION) +ngx_uint_t ngx_http_degraded(ngx_http_request_t *); +#endif + extern ngx_module_t ngx_http_module; diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -118,8 +118,10 @@ ngx_http_copy_filter(ngx_http_request_t ctx->filter_ctx = r; #if (NGX_HAVE_FILE_AIO) - if (ngx_file_aio && clcf->aio) { - ctx->aio_handler = ngx_http_copy_aio_handler; + if (ngx_file_aio) { + if (clcf->aio) { + ctx->aio_handler = ngx_http_copy_aio_handler; + } #if (NGX_HAVE_AIO_SENDFILE) c->aio_sendfile = (clcf->aio == NGX_HTTP_AIO_SENDFILE); #endif @@ -211,6 +213,7 @@ ngx_http_copy_aio_handler(ngx_output_cha r->main->blocked++; r->aio = 1; + ctx->aio = 1; } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2427,7 +2427,9 @@ ngx_http_core_server(ngx_conf_t *cf, ngx ngx_uint_t i; ngx_conf_t pcf; ngx_http_module_t *module; + struct sockaddr_in *sin; ngx_http_conf_ctx_t *ctx, *http_ctx; + ngx_http_listen_opt_t lsopt; ngx_http_core_srv_conf_t *cscf, **cscfp; ngx_http_core_main_conf_t *cmcf; @@ -2506,6 +2508,37 @@ ngx_http_core_server(ngx_conf_t *cf, ngx *cf = pcf; + if (rv == NGX_CONF_OK && !cscf->listen) { + ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); + + sin = &lsopt.u.sockaddr_in; + + sin->sin_family = AF_INET; +#if (NGX_WIN32) + sin->sin_port = htons(80); +#else + sin->sin_port = htons((getuid() == 0) ? 80 : 8000); +#endif + sin->sin_addr.s_addr = INADDR_ANY; + + lsopt.socklen = sizeof(struct sockaddr_in); + + lsopt.backlog = NGX_LISTEN_BACKLOG; + lsopt.rcvbuf = -1; + lsopt.sndbuf = -1; +#if (NGX_HAVE_SETFIB) + lsopt.setfib = -1; +#endif + lsopt.wildcard = 1; + + (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.addr, + NGX_SOCKADDR_STRLEN, 1); + + if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + return rv; } @@ -2946,8 +2979,6 @@ ngx_http_core_merge_srv_conf(ngx_conf_t ngx_http_core_srv_conf_t *prev = parent; ngx_http_core_srv_conf_t *conf = child; - struct sockaddr_in *sin; - ngx_http_listen_opt_t lsopt; ngx_http_server_name_t *sn; /* TODO: it does not merge, it inits only */ @@ -2979,37 +3010,6 @@ ngx_http_core_merge_srv_conf(ngx_conf_t ngx_conf_merge_value(conf->underscores_in_headers, prev->underscores_in_headers, 0); - if (!conf->listen) { - ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t)); - - sin = &lsopt.u.sockaddr_in; - - sin->sin_family = AF_INET; -#if (NGX_WIN32) - sin->sin_port = htons(80); -#else - sin->sin_port = htons((getuid() == 0) ? 80 : 8000); -#endif - sin->sin_addr.s_addr = INADDR_ANY; - - lsopt.socklen = sizeof(struct sockaddr_in); - - lsopt.backlog = NGX_LISTEN_BACKLOG; - lsopt.rcvbuf = -1; - lsopt.sndbuf = -1; -#if (NGX_HAVE_SETFIB) - lsopt.setfib = -1; -#endif - lsopt.wildcard = 1; - - (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.addr, - NGX_SOCKADDR_STRLEN, 1); - - if (ngx_http_add_listen(cf, conf, &lsopt) == NGX_OK) { - return NGX_CONF_OK; - } - } - if (conf->server_name.data == NULL) { ngx_str_set(&conf->server_name, ""); @@ -3113,6 +3113,9 @@ ngx_http_core_create_loc_conf(ngx_conf_t clcf->gzip_disable = NGX_CONF_UNSET_PTR; #endif clcf->gzip_disable_msie6 = 3; +#if (NGX_HTTP_DEGRADATION) + clcf->gzip_disable_degradation = 3; +#endif #endif return clcf; @@ -3373,6 +3376,15 @@ ngx_http_core_merge_loc_conf(ngx_conf_t (prev->gzip_disable_msie6 == 3) ? 0 : prev->gzip_disable_msie6; } +#if (NGX_HTTP_DEGRADATION) + + if (conf->gzip_disable_degradation == 3) { + conf->gzip_disable_degradation = + (prev->gzip_disable_degradation == 3) ? + 0 : prev->gzip_disable_degradation; + } + +#endif #endif return NGX_CONF_OK; @@ -4057,19 +4069,15 @@ ngx_http_core_error_page(ngx_conf_t *cf, return NGX_CONF_ERROR; } - if (overwrite >= 0) { - err->overwrite = overwrite; - - } else { + err->overwrite = overwrite; + + if (overwrite == -1) { switch (err->status) { case NGX_HTTP_TO_HTTPS: case NGX_HTTPS_CERT_ERROR: case NGX_HTTPS_NO_CERT: err->overwrite = NGX_HTTP_BAD_REQUEST; - break; - default: - err->overwrite = err->status; break; } } @@ -4394,6 +4402,15 @@ ngx_http_gzip_disable(ngx_conf_t *cf, ng continue; } +#if (NGX_HTTP_DEGRADATION) + + if (ngx_strcmp(value[i].data, "degradation") == 0) { + clcf->gzip_disable_degradation = 1; + continue; + } + +#endif + re = ngx_array_push(clcf->gzip_disable); if (re == NULL) { return NGX_CONF_ERROR; @@ -4414,20 +4431,35 @@ ngx_http_gzip_disable(ngx_conf_t *cf, ng return NGX_CONF_OK; #else - ngx_str_t *value; + ngx_str_t *value; + ngx_uint_t i; value = cf->args->elts; - if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "msie6") == 0) { - clcf->gzip_disable_msie6 = 1; - return NGX_CONF_OK; + for (i = 1; i < cf->args->nelts; i++) { + if (ngx_strcmp(value[i].data, "msie6") == 0) { + clcf->gzip_disable_msie6 = 1; + continue; + } + +#if (NGX_HTTP_DEGRADATION) + + if (ngx_strcmp(value[i].data, "degradation") == 0) { + clcf->gzip_disable_degradation = 1; + continue; + } + +#endif + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "without PCRE library \"gzip_disable\" supports " + "builtin \"msie6\" and \"degradation\" mask only"); + + return NGX_CONF_ERROR; } - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "without PCRE library \"gzip_disable\" supports " - "builtin \"msie6\" mask only"); - - return NGX_CONF_ERROR; + return NGX_CONF_OK; + #endif } diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -295,6 +295,9 @@ struct ngx_http_core_loc_conf_s { unsigned auto_redirect:1; #if (NGX_HTTP_GZIP) unsigned gzip_disable_msie6:2; +#if (NGX_HTTP_DEGRADATION) + unsigned gzip_disable_degradation:2; +#endif #endif ngx_http_location_tree_node_t *static_locations; diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -523,7 +523,9 @@ ngx_http_send_error_page(ngx_http_reques r->expect_tested = 1; } - r->err_status = overwrite; + if (overwrite >= 0) { + r->err_status = overwrite; + } if (ngx_http_complex_value(r, &err_page->value, &uri) != NGX_OK) { return NGX_ERROR; @@ -556,7 +558,7 @@ ngx_http_send_error_page(ngx_http_reques return NGX_ERROR; } - r->err_status = NGX_HTTP_MOVED_TEMPORARILY; + r->err_status = overwrite > 0 ? overwrite : NGX_HTTP_MOVED_TEMPORARILY; location->hash = 1; ngx_str_set(&location->key, "Location"); @@ -570,7 +572,7 @@ ngx_http_send_error_page(ngx_http_reques return ngx_http_send_refresh(r); } - return ngx_http_send_special_response(r, clcf, NGX_HTTP_MOVED_TEMPORARILY + return ngx_http_send_special_response(r, clcf, r->err_status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_LEVEL_200); } diff --git a/src/os/unix/ngx_linux_aio_read.c b/src/os/unix/ngx_linux_aio_read.c --- a/src/os/unix/ngx_linux_aio_read.c +++ b/src/os/unix/ngx_linux_aio_read.c @@ -95,6 +95,10 @@ ngx_file_aio_read(ngx_file_t *file, u_ch n = io_submit(ngx_aio_ctx, 1, piocb); if (n == 1) { + ev->active = 1; + ev->ready = 0; + ev->complete = 0; + return NGX_AGAIN; }