# HG changeset patch # User Igor Sysoev # Date 1146686400 -14400 # Node ID 003bd800ec2a2410917d44d67793e40d7edcf68f # Parent 2a1394604ae977ab9a890851d1a208ebf7adb47d nginx 0.3.44 *) Feature: the "wait" parameter in the "include" SSI command. *) Feature: the Ukrainian and Byelorussian characters were added to koi-win conversion table. *) Bugfix: in the SSI. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,14 @@ +Changes with nginx 0.3.44 04 May 2006 + + *) Feature: the "wait" parameter in the SSI "include" command. + + *) Feature: the Ukrainian and Byelorussian characters were added to + koi-win conversion table. + + *) Bugfix: in the SSI. + + Changes with nginx 0.3.43 26 Apr 2006 *) Bugfix: in the SSI. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,14 @@ +Изменения в nginx 0.3.44 04.05.2006 + + *) Добавление: параметр wait в команде SSI inlcude. + + *) Добавление: в таблицу перекодировки koi-win добавлены украинские и + белорусские символы. + + *) Исправление: в SSI. + + Изменения в nginx 0.3.43 26.04.2006 *) Исправление: в SSI. diff --git a/auto/feature b/auto/feature --- a/auto/feature +++ b/auto/feature @@ -14,7 +14,8 @@ END ngx_found=no if test -n "$ngx_feature_name"; then - ngx_have_feature=`echo $ngx_feature_name | tr '[a-z]' '[A-Z]'` + ngx_have_feature=`echo $ngx_feature_name \ + | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ` fi cat << END > $NGX_AUTOTEST.c diff --git a/auto/include b/auto/include --- a/auto/include +++ b/auto/include @@ -35,8 +35,8 @@ if [ -x $NGX_AUTOTEST ]; then echo " found" - ngx_name=`echo $ngx_include | sed -e 's/\./_/' -e 's/\//_/' \ - | tr '[a-z]' '[A-Z]'` + ngx_name=`echo $ngx_include \ + | tr abcdefghijklmnopqrstuvwxyz/. ABCDEFGHIJKLMNOPQRSTUVWXYZ__` have=NGX_HAVE_$ngx_name . auto/have_headers diff --git a/conf/koi-win b/conf/koi-win --- a/conf/koi-win +++ b/conf/koi-win @@ -10,8 +10,22 @@ charset_map koi8-r windows-1251 { 9E B7 ; # · A3 B8 ; # small yo + A4 BA ; # small Ukrainian ye + + A6 B3 ; # small Ukrainian i + A7 BF ; # small Ukrainian j + + AD B4 ; # small Ukrainian soft g + AE A2 ; # small Byelorussian short u B3 A8 ; # capital YO + B4 AA ; # capital Ukrainian YE + + B6 B2 ; # capital Ukrainian I + B7 AF ; # capital Ukrainian J + + BD A5 ; # capital Ukrainian soft G + BE A1 ; # capital Byelorussian short U BF A9 ; # (C) diff --git a/conf/nginx.conf b/conf/nginx.conf --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -26,9 +26,10 @@ http { sendfile on; #tcp_nopush on; - #tcp_nodelay on; #keepalive_timeout 0; + keepalive_timeout 65; + tcp_nodelay on; #gzip on; @@ -60,7 +61,8 @@ http { # include conf/fastcgi_params; #} - # deny access to .htaccess files + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one # #location ~ /\.ht { # deny all; diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.3.43" +#define NGINX_VER "nginx/0.3.44" #define NGINX_VAR "NGINX" #define NGX_OLDPID_EXT ".oldbin" diff --git a/src/core/ngx_buf.c b/src/core/ngx_buf.c --- a/src/core/ngx_buf.c +++ b/src/core/ngx_buf.c @@ -134,12 +134,6 @@ ngx_chain_add_copy(ngx_pool_t *pool, ngx } while (in) { - - if (ngx_buf_sync_only(in->buf)) { - in = in->next; - continue; - } - cl = ngx_alloc_chain_link(pool); if (cl == NULL) { return NGX_ERROR; diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -221,12 +221,14 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int { char *rv; void *conf, **confp; - ngx_uint_t i, valid; + ngx_uint_t i, multi; ngx_str_t *name; ngx_command_t *cmd; name = cf->args->elts; + multi = 0; + for (i = 0; ngx_modules[i]; i++) { /* look up the directive in the appropriate modules */ @@ -242,132 +244,138 @@ ngx_conf_handler(ngx_conf_t *cf, ngx_int continue; } - while (cmd->name.len) { + for ( /* void */ ; cmd->name.len; cmd++) { - if (name->len == cmd->name.len - && ngx_strcmp(name->data, cmd->name.data) == 0) - { - /* is the directive's location right ? */ + if (name->len != cmd->name.len) { + continue; + } - if (!(cmd->type & cf->cmd_type)) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "directive \"%s\" in %s:%ui " - "is not allowed here", - name->data, cf->conf_file->file.name.data, - cf->conf_file->line); - return NGX_ERROR; + if (ngx_strcmp(name->data, cmd->name.data) != 0) { + continue; + } + + + /* is the directive's location right ? */ + + if (!(cmd->type & cf->cmd_type)) { + if (cmd->type & NGX_CONF_MULTI) { + multi = 1; + continue; } - if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "directive \"%s\" in %s:%ui " - "is not terminated by \";\"", - name->data, cf->conf_file->file.name.data, - cf->conf_file->line); - return NGX_ERROR; - } + goto not_allowed; + } + + if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "directive \"%s\" in %s:%ui " + "is not terminated by \";\"", + name->data, cf->conf_file->file.name.data, + cf->conf_file->line); + return NGX_ERROR; + } - if ((cmd->type & NGX_CONF_BLOCK) - && last != NGX_CONF_BLOCK_START) - { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "directive \"%s\" in %s:%ui " - "has not the opening \"{\"", - name->data, cf->conf_file->file.name.data, - cf->conf_file->line); - return NGX_ERROR; - } + if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "directive \"%s\" in %s:%ui " + "has not the opening \"{\"", + name->data, cf->conf_file->file.name.data, + cf->conf_file->line); + return NGX_ERROR; + } - /* is the directive's argument count right ? */ + /* is the directive's argument count right ? */ - if (cmd->type & NGX_CONF_ANY) { - valid = 1; + if (!(cmd->type & NGX_CONF_ANY)) { - } else if (cmd->type & NGX_CONF_FLAG) { + if (cmd->type & NGX_CONF_FLAG) { - if (cf->args->nelts == 2) { - valid = 1; - } else { - valid = 0; + if (cf->args->nelts != 2) { + goto invalid; } } else if (cmd->type & NGX_CONF_1MORE) { - if (cf->args->nelts > 1) { - valid = 1; - } else { - valid = 0; + if (cf->args->nelts < 2) { + goto invalid; } } else if (cmd->type & NGX_CONF_2MORE) { - if (cf->args->nelts > 2) { - valid = 1; - } else { - valid = 0; + if (cf->args->nelts < 3) { + goto invalid; } - } else if (cf->args->nelts <= NGX_CONF_MAX_ARGS - && (cmd->type - & argument_number[cf->args->nelts - 1])) - { - valid = 1; + } else if (cf->args->nelts > NGX_CONF_MAX_ARGS) { - } else { - valid = 0; - } + goto invalid; - if (!valid) { - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "invalid number arguments in " - "directive \"%s\" in %s:%ui", - name->data, cf->conf_file->file.name.data, - cf->conf_file->line); - return NGX_ERROR; + } else if (!(cmd->type & argument_number[cf->args->nelts - 1])) + { + goto invalid; } + } - /* set up the directive's configuration context */ + /* set up the directive's configuration context */ - conf = NULL; + conf = NULL; - if (cmd->type & NGX_DIRECT_CONF) { - conf = ((void **) cf->ctx)[ngx_modules[i]->index]; + if (cmd->type & NGX_DIRECT_CONF) { + conf = ((void **) cf->ctx)[ngx_modules[i]->index]; - } else if (cmd->type & NGX_MAIN_CONF) { - conf = &(((void **) cf->ctx)[ngx_modules[i]->index]); - - } else if (cf->ctx) { - confp = *(void **) ((char *) cf->ctx + cmd->conf); + } else if (cmd->type & NGX_MAIN_CONF) { + conf = &(((void **) cf->ctx)[ngx_modules[i]->index]); - if (confp) { - conf = confp[ngx_modules[i]->ctx_index]; - } - } - - rv = cmd->set(cf, cmd, conf); + } else if (cf->ctx) { + confp = *(void **) ((char *) cf->ctx + cmd->conf); - if (rv == NGX_CONF_OK) { - return NGX_OK; - } - - if (rv == NGX_CONF_ERROR) { - return NGX_ERROR; + if (confp) { + conf = confp[ngx_modules[i]->ctx_index]; } + } - ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "the \"%s\" directive %s in %s:%ui", - name->data, rv, cf->conf_file->file.name.data, - cf->conf_file->line); + rv = cmd->set(cf, cmd, conf); + if (rv == NGX_CONF_OK) { + return NGX_OK; + } + + if (rv == NGX_CONF_ERROR) { return NGX_ERROR; } - cmd++; + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "the \"%s\" directive %s in %s:%ui", + name->data, rv, cf->conf_file->file.name.data, + cf->conf_file->line); + + return NGX_ERROR; } } + if (multi == 0) { + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "unknown directive \"%s\" in %s:%ui", + name->data, cf->conf_file->file.name.data, + cf->conf_file->line); + + return NGX_ERROR; + } + +not_allowed: + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - "unknown directive \"%s\" in %s:%ui", + "directive \"%s\" in %s:%ui " + "is not allowed here", + name->data, cf->conf_file->file.name.data, + cf->conf_file->line); + return NGX_ERROR; + +invalid: + + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, + "invalid number arguments in " + "directive \"%s\" in %s:%ui", name->data, cf->conf_file->file.name.data, cf->conf_file->line); diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -44,6 +44,7 @@ #define NGX_CONF_ANY 0x00000400 #define NGX_CONF_1MORE 0x00000800 #define NGX_CONF_2MORE 0x00001000 +#define NGX_CONF_MULTI 0x00002000 #define NGX_DIRECT_CONF 0x00010000 diff --git a/src/core/ngx_log.h b/src/core/ngx_log.h --- a/src/core/ngx_log.h +++ b/src/core/ngx_log.h @@ -28,6 +28,7 @@ #define NGX_LOG_DEBUG_EVENT 0x080 #define NGX_LOG_DEBUG_HTTP 0x100 #define NGX_LOG_DEBUG_IMAP 0x200 +#define NGX_LOG_DEBUG_MYSQL 0x400 /* * do not forget to update debug_levels[] in src/core/ngx_log.c diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c --- a/src/http/modules/ngx_http_addition_filter_module.c +++ b/src/http/modules/ngx_http_addition_filter_module.c @@ -143,7 +143,9 @@ ngx_http_addition_body_filter(ngx_http_r ctx->before_body_sent = 1; if (conf->before_body.len) { - if (ngx_http_subrequest(r, &conf->before_body, NULL, 0) != NGX_OK) { + if (ngx_http_subrequest(r, &conf->before_body, NULL, 0) + == NGX_ERROR) + { return NGX_ERROR; } } @@ -165,7 +167,7 @@ ngx_http_addition_body_filter(ngx_http_r return rc; } - if (ngx_http_subrequest(r, &conf->after_body, NULL, 0) != NGX_OK) { + if (ngx_http_subrequest(r, &conf->after_body, NULL, 0) == NGX_ERROR) { return NGX_ERROR; } diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c --- a/src/http/modules/ngx_http_autoindex_module.c +++ b/src/http/modules/ngx_http_autoindex_module.c @@ -162,7 +162,7 @@ ngx_http_autoindex_handler(ngx_http_requ return NGX_DECLINED; } - if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { + if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_DECLINED; } diff --git a/src/http/modules/ngx_http_empty_gif_module.c b/src/http/modules/ngx_http_empty_gif_module.c --- a/src/http/modules/ngx_http_empty_gif_module.c +++ b/src/http/modules/ngx_http_empty_gif_module.c @@ -112,7 +112,7 @@ ngx_http_empty_gif_handler(ngx_http_requ ngx_buf_t *b; ngx_chain_t out; - if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { + if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c --- a/src/http/modules/ngx_http_index_module.c +++ b/src/http/modules/ngx_http_index_module.c @@ -143,7 +143,7 @@ ngx_http_index_handler(ngx_http_request_ return NGX_DECLINED; } - if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { + if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_DECLINED; } diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -128,7 +128,8 @@ static ngx_command_t ngx_http_log_comma NULL }, { ngx_string("access_log"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_TAKE123, ngx_http_log_set_log, NGX_HTTP_LOC_CONF_OFFSET, 0, diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c --- a/src/http/modules/ngx_http_memcached_module.c +++ b/src/http/modules/ngx_http_memcached_module.c @@ -154,7 +154,7 @@ ngx_http_memcached_handler(ngx_http_requ ngx_http_memcached_ctx_t *ctx; ngx_http_memcached_loc_conf_t *mlcf; - if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { + if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -188,6 +188,7 @@ static ngx_str_t ngx_http_ssi_none = ngx #define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0 #define NGX_HTTP_SSI_INCLUDE_FILE 1 +#define NGX_HTTP_SSI_INCLUDE_WAIT 2 #define NGX_HTTP_SSI_ECHO_VAR 0 #define NGX_HTTP_SSI_ECHO_DEFAULT 1 @@ -204,6 +205,7 @@ static ngx_str_t ngx_http_ssi_none = ngx static ngx_http_ssi_param_t ngx_http_ssi_include_params[] = { { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0, 0 }, { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0, 0 }, + { ngx_string("wait"), NGX_HTTP_SSI_INCLUDE_WAIT, 0, 0 }, { ngx_null_string, 0, 0, 0 } }; @@ -361,7 +363,12 @@ ngx_http_ssi_body_filter(ngx_http_reques ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module); - if (ctx == NULL || (in == NULL && ctx->in == NULL && ctx->busy == NULL)) { + if (ctx == NULL + || (in == NULL + && ctx->buf == NULL + && ctx->in == NULL + && ctx->busy == NULL)) + { return ngx_http_next_body_filter(r, in); } @@ -373,6 +380,19 @@ ngx_http_ssi_body_filter(ngx_http_reques } } + if (ctx->wait) { + if (r->connection->data != r) { + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http ssi filter \"%V\" wait", &r->uri); + return NGX_AGAIN; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http ssi filter \"%V\" continue", &r->uri); + + ctx->wait = 0; + } + slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -632,6 +652,10 @@ ngx_http_ssi_body_filter(ngx_http_reques continue; } + if (rc == NGX_AGAIN) { + return NGX_AGAIN; + } + if (rc == NGX_ERROR) { return NGX_ERROR; } @@ -782,8 +806,13 @@ ngx_http_ssi_output(ngx_http_request_t * cl = ctx->busy; ctx->busy = cl->next; - cl->next = ctx->free; - ctx->free = cl; + + if (ngx_buf_in_memory(b) || b->in_file) { + /* add data bufs only to the free buf chain */ + + cl->next = ctx->free; + ctx->free = cl; + } } return rc; @@ -1626,11 +1655,13 @@ static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { - ngx_str_t *uri, *file, args; + ngx_int_t rc; + ngx_str_t *uri, *file, *wait, args; ngx_uint_t flags; uri = params[NGX_HTTP_SSI_INCLUDE_VIRTUAL]; file = params[NGX_HTTP_SSI_INCLUDE_FILE]; + wait = params[NGX_HTTP_SSI_INCLUDE_WAIT]; if (uri && file) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, @@ -1645,6 +1676,26 @@ ngx_http_ssi_include(ngx_http_request_t return NGX_HTTP_SSI_ERROR; } + if (wait) { + if (uri == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "\"wait\" may not be used with file=\"%V\"", + uri, file); + return NGX_HTTP_SSI_ERROR; + } + + if (wait->len == 2 && ngx_strncasecmp(wait->data, "no", 2) == 0) { + wait = NULL; + + } else if (wait->len != 3 || ngx_strncasecmp(wait->data, "yes", 3) != 0) + { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "invalid value \"%V\" in the \"wait\" parameter", + &wait); + return NGX_HTTP_SSI_ERROR; + } + } + if (uri == NULL) { uri = file; } @@ -1666,11 +1717,21 @@ ngx_http_ssi_include(ngx_http_request_t return NGX_HTTP_SSI_ERROR; } - if (ngx_http_subrequest(r, uri, &args, flags) != NGX_OK) { + rc = ngx_http_subrequest(r, uri, &args, flags); + + if (rc == NGX_ERROR) { return NGX_HTTP_SSI_ERROR; } - return NGX_OK; + if (wait == NULL) { + return NGX_OK; + } + + if (rc == NGX_AGAIN) { + ctx->wait = 1; + } + + return rc; } diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h --- a/src/http/modules/ngx_http_ssi_filter_module.h +++ b/src/http/modules/ngx_http_ssi_filter_module.h @@ -61,6 +61,7 @@ typedef struct { unsigned conditional:2; unsigned output:1; unsigned output_chosen:1; + unsigned wait:1; void *value_buf; ngx_str_t timefmt; diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c --- a/src/http/modules/ngx_http_static_module.c +++ b/src/http/modules/ngx_http_static_module.c @@ -86,7 +86,7 @@ ngx_http_static_handler(ngx_http_request ngx_pool_cleanup_file_t *clnf; ngx_http_core_loc_conf_t *clcf; - if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { + if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } 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 @@ -17,7 +17,7 @@ our @EXPORT = qw( HTTP_SERVER_ERROR ); -our $VERSION = '0.3.23'; +our $VERSION = '0.3.43'; require XSLoader; XSLoader::load('nginx', $VERSION); 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 @@ -1168,7 +1168,7 @@ ngx_http_subrequest(ngx_http_request_t * sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t)); if (sr == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return NGX_ERROR; } sr->signature = NGX_HTTP_MODULE; @@ -1178,14 +1178,14 @@ ngx_http_subrequest(ngx_http_request_t * sr->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module); if (sr->ctx == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return NGX_ERROR; } if (ngx_list_init(&sr->headers_out.headers, r->pool, 20, sizeof(ngx_table_elt_t)) == NGX_ERROR) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return NGX_ERROR; } cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); @@ -1228,7 +1228,7 @@ ngx_http_subrequest(ngx_http_request_t * sr->http_protocol = r->http_protocol; if (ngx_http_set_exten(sr) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return NGX_ERROR; } sr->main = r->main; @@ -1251,7 +1251,7 @@ ngx_http_subrequest(ngx_http_request_t * pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t)); if (pr == NULL) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; + return NGX_ERROR; } pr->request = sr; @@ -1275,10 +1275,18 @@ ngx_http_subrequest(ngx_http_request_t * ngx_http_handler(sr); if (!c->destroyed) { - sr->fast_subrequest = 0; - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http subrequest done \"%V?%V\"", uri, &sr->args); + + if (sr->fast_subrequest) { + sr->fast_subrequest = 0; + + if (sr->done) { + return NGX_OK; + } + } + + return NGX_AGAIN; } return NGX_OK; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -958,7 +958,7 @@ ngx_http_read_request_header(ngx_http_re } if (n == 0 || n == NGX_ERROR) { - ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_ERROR; } @@ -1480,17 +1480,24 @@ ngx_http_finalize_request(ngx_http_reque } if (r->fast_subrequest) { + + if (rc == NGX_AGAIN) { + r->fast_subrequest = 0; + } + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http fast subrequest: \"%V?%V\" done", &r->uri, &r->args); return; } - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http wake parent request: \"%V?%V\"", - &pr->uri, &pr->args); - - pr->write_event_handler(pr); + if (rc != NGX_AGAIN) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http wake parent request: \"%V?%V\"", + &pr->uri, &pr->args); + + pr->write_event_handler(pr); + } } return; diff --git a/src/os/unix/ngx_socket.c b/src/os/unix/ngx_socket.c --- a/src/os/unix/ngx_socket.c +++ b/src/os/unix/ngx_socket.c @@ -10,7 +10,7 @@ /* * ioctl(FIONBIO) sets a blocking mode with the single syscall - * while fcntl(F_SETFL, ~O_NONBLOCK) needs to learn before + * while fcntl(F_SETFL, !O_NONBLOCK) needs to learn before * the previous state using fcntl(F_GETFL). * * ioctl() and fcntl() are syscalls at least in FreeBSD 2.x, Linux 2.2 diff --git a/src/os/unix/ngx_socket.h b/src/os/unix/ngx_socket.h --- a/src/os/unix/ngx_socket.h +++ b/src/os/unix/ngx_socket.h @@ -29,9 +29,12 @@ int ngx_blocking(ngx_socket_t s); #else -#define ngx_nonblocking(s) fcntl(s, F_SETFL, O_NONBLOCK) +#define ngx_nonblocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK) #define ngx_nonblocking_n "fcntl(O_NONBLOCK)" +#define ngx_blocking(s) fcntl(s, F_SETFL, fcntl(s, F_GETFL) & ~O_NONBLOCK) +#define ngx_blocking_n "fcntl(!O_NONBLOCK)" + #endif int ngx_tcp_nopush(ngx_socket_t s);