# HG changeset patch # User Maxim Dounin # Date 1233698583 -10800 # Node ID a28a95b7a86d3dcd5c44e2dde8b4ab4231066faf # Parent 96428109ec3bbbc2836762ce49dca5bfc238d7da# Parent 28335b73075091c0e231e7660b1c1fca1dc23ef8 Merge with nginx 0.7.33. diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -225,3 +225,5 @@ dc98ed169c03366ef89869d49da3b21b4b6663fe 2580fe1c5a9a300134ea707c5e27d871bc0237f0 PATCH_NGINX_MAIL_0_6 2c989ee54dbd4bfa12b53f3b0ff59e5def929818 PATCH_NGINX_MAIL_0_7 ce4f9ff90bfa58834c5b0db35395fd980c8c4aa0 NGINX_0_7_31 +6281966854a55e092674b01b6861bd025fe158ee NGINX_0_7_32 +670af56a1158749e82d7b1fce1ce348f8e10472a NGINX_0_7_33 diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,32 @@ +Changes with nginx 0.7.33 02 Feb 2009 + + *) Bugfix: a double response might be returned if the epoll or rtsig + methods are used and a redirect was returned to a request with + body. + Thanks to Eden Li. + + *) Bugfix: the $sent_http_location variable was empty for some + redirects types. + + *) Bugfix: a segmentation fault might occur in worker process if + "resolver" directive was used in SMTP proxy. + + +Changes with nginx 0.7.32 26 Jan 2009 + + *) Feature: now a directory existence testing can be set explicitly in + the "try_files" directive. + + *) Bugfix: fastcgi_store stored files not always. + + *) Bugfix: in geo ranges. + + *) Bugfix: in shared memory allocations if nginx was built without + debugging. + Thanks to Andrey Kvasov. + + Changes with nginx 0.7.31 19 Jan 2009 *) Change: now the "try_files" directive tests files only and ignores diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,31 @@ +Изменения в nginx 0.7.33 02.02.2009 + + *) Исправление: если на запрос с телом возвращался редирект, то ответ + мог быть двойным при использовании методов epoll или rtsig. + Спасибо Eden Li. + + *) Исправление: для некоторых типов редиректов в переменной + $sent_http_location было пустое значение. + + *) Исправление: при использовании директивы resolver в SMTP + прокси-сервере в рабочем процессе мог произойти segmentation fault. + + +Изменения в nginx 0.7.32 26.01.2009 + + *) Добавление: теперь в директиве try_files можно явно указать проверку + каталога. + + *) Исправление: fastcgi_store не всегда сохранял файлы. + + *) Исправление: в гео-диапазонах. + + *) Исправление: ошибки выделения больших блоков в разделяемой памяти, + если nginx был собран без отладки. + Спасибо Андрею Квасову. + + Изменения в nginx 0.7.31 19.01.2009 *) Изменение: теперь директива try_files проверяет только файлы, 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_VERSION "0.7.31" +#define NGINX_VERSION "0.7.33" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -394,6 +394,10 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) cycle->log = cycle->new_log; pool->log = cycle->new_log; + if (cycle->log->log_level == 0) { + cycle->log->log_level = NGX_LOG_ERR; + } + /* create shared memory */ diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c --- a/src/core/ngx_open_file_cache.c +++ b/src/core/ngx_open_file_cache.c @@ -457,7 +457,7 @@ ngx_open_and_stat_file(u_char *name, ngx goto failed; } - if (of->is_dir) { + if (ngx_is_dir(&fi)) { goto done; } } diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -578,6 +578,7 @@ failed: ngx_int_t ngx_resolve_addr(ngx_resolver_ctx_t *ctx) { + u_char *name; ngx_resolver_t *r; ngx_resolver_node_t *rn; @@ -601,19 +602,21 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue); - ctx->name.len = rn->nlen; - ctx->name.data = ngx_resolver_dup(r, rn->name, rn->nlen); - if (ctx->name.data == NULL) { + name = ngx_resolver_dup(r, rn->name, rn->nlen); + if (name == NULL) { goto failed; } + ctx->name.len = rn->nlen; + ctx->name.data = name; + /* unlock addr mutex */ ctx->state = NGX_OK; ctx->handler(ctx); - ngx_resolver_free(r, ctx->name.data); + ngx_resolver_free(r, name); return NGX_OK; } @@ -623,7 +626,9 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx ctx->next = rn->waiting; rn->waiting = ctx; - return NGX_AGAIN; + /* unlock addr mutex */ + + return NGX_OK; } ngx_queue_remove(&rn->queue); @@ -1336,7 +1341,7 @@ ngx_resolver_process_a(ngx_resolver_t *r ctx->handler(ctx); } - if (naddrs) { + if (naddrs > 1) { ngx_resolver_free(r, addrs); } @@ -1513,20 +1518,23 @@ ngx_resolver_process_ptr(ngx_resolver_t goto short_response; } - len -= 2; - if (ngx_resolver_copy(r, &name, buf, &buf[i], &buf[n]) != NGX_OK) { return; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver an:%V", &name); - if (len != (size_t) rn->nlen || ngx_strncmp(name.data, rn->name, len) != 0) + if (name.len != (size_t) rn->nlen + || ngx_strncmp(name.data, rn->name, name.len) != 0) { - ngx_resolver_free(r, rn->name); + if (rn->nlen) { + ngx_resolver_free(r, rn->name); + } + + rn->nlen = (u_short) name.len; rn->name = name.data; - name.data = ngx_resolver_dup(r, rn->name, len); + name.data = ngx_resolver_dup(r, rn->name, name.len); if (name.data == NULL) { goto failed; } diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c --- a/src/core/ngx_slab.c +++ b/src/core/ngx_slab.c @@ -661,11 +661,8 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *po } page->slab = pages | NGX_SLAB_PAGE_START; - -#if (NGX_DEBUG) page->next = NULL; page->prev = NGX_SLAB_PAGE; -#endif if (--pages == 0) { return page; @@ -673,10 +670,8 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *po for (p = page + 1; pages; pages--) { p->slab = NGX_SLAB_PAGE_BUSY; -#if (NGX_DEBUG) p->next = NULL; p->prev = NGX_SLAB_PAGE; -#endif p++; } diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -135,8 +135,8 @@ static ngx_int_t ngx_http_fastcgi_script ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_fastcgi_split(ngx_http_request_t *r, - ngx_http_fastcgi_ctx_t *f, ngx_http_fastcgi_loc_conf_t *flcf); +static ngx_http_fastcgi_ctx_t *ngx_http_fastcgi_split(ngx_http_request_t *r, + ngx_http_fastcgi_loc_conf_t *flcf); static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -2111,10 +2111,11 @@ ngx_http_fastcgi_script_name_variable(ng ngx_http_fastcgi_ctx_t *f; ngx_http_fastcgi_loc_conf_t *flcf; - f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); - if (ngx_http_fastcgi_split(r, f, flcf) != NGX_OK) { + f = ngx_http_fastcgi_split(r, flcf); + + if (f == NULL) { return NGX_ERROR; } @@ -2151,10 +2152,11 @@ ngx_http_fastcgi_path_info_variable(ngx_ ngx_http_fastcgi_ctx_t *f; ngx_http_fastcgi_loc_conf_t *flcf; - f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module); - if (ngx_http_fastcgi_split(r, f, flcf) != NGX_OK) { + f = ngx_http_fastcgi_split(r, flcf); + + if (f == NULL) { return NGX_ERROR; } @@ -2168,35 +2170,46 @@ ngx_http_fastcgi_path_info_variable(ngx_ } -static ngx_int_t -ngx_http_fastcgi_split(ngx_http_request_t *r, ngx_http_fastcgi_ctx_t *f, - ngx_http_fastcgi_loc_conf_t *flcf) +static ngx_http_fastcgi_ctx_t * +ngx_http_fastcgi_split(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf) { + ngx_http_fastcgi_ctx_t *f; #if (NGX_PCRE) - ngx_int_t n; - int captures[(1 + 2) * 3]; + ngx_int_t n; + int captures[(1 + 2) * 3]; + + f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); + + if (f == NULL) { + f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t)); + if (f == NULL) { + return NULL; + } + + ngx_http_set_ctx(r, f, ngx_http_fastcgi_module); + } if (f->script_name.len) { - return NGX_OK; + return f; } if (flcf->split_regex == NULL) { f->script_name = r->uri; - return NGX_OK; + return f; } n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3); if (n == NGX_REGEX_NO_MATCHED) { f->script_name = r->uri; - return NGX_OK; + return f; } if (n < 0) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"", n, &r->uri, &flcf->split_name); - return NGX_ERROR; + return NULL; } /* match */ @@ -2207,13 +2220,24 @@ ngx_http_fastcgi_split(ngx_http_request_ f->path_info.len = captures[5] - captures[4]; f->path_info.data = r->uri.data + f->script_name.len; - return NGX_OK; + return f; #else + f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module); + + if (f == NULL) { + f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t)); + if (f == NULL) { + return NULL; + } + + ngx_http_set_ctx(r, f, ngx_http_fastcgi_module); + } + f->script_name = r->uri; - return NGX_OK; + return f; #endif } diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c --- a/src/http/modules/ngx_http_geo_module.c +++ b/src/http/modules/ngx_http_geo_module.c @@ -636,8 +636,8 @@ ngx_http_geo_add_range(ngx_conf_t *cf, n range = a->elts; - ngx_memcpy(&range[i + 2], &range[i + 1], - (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t)); + ngx_memcpy(&range[i + 1], &range[i], + (a->nelts - 1 - i) * sizeof(ngx_http_geo_range_t)); range[i + 1].start = (u_short) (e + 1); 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 @@ -302,18 +302,18 @@ ngx_http_gzip_body_filter(ngx_http_reque if (ctx->buffering) { if (in) { - switch (ngx_http_gzip_filter_copy_recycled(ctx, in)) { + switch (ngx_http_gzip_filter_copy_recycled(ctx, in)) { - case NGX_OK: - return NGX_OK; + case NGX_OK: + return NGX_OK; - case NGX_DONE: - in = NULL; - break; + case NGX_DONE: + in = NULL; + break; - default: /* NGX_ERROR */ - goto failed; - } + default: /* NGX_ERROR */ + goto failed; + } } else { ctx->buffering = 0; 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 @@ -96,7 +96,7 @@ static ngx_int_t ngx_http_index_handler(ngx_http_request_t *r) { u_char *p, *name; - size_t len, nlen, root, allocated; + size_t len, root, reserve, allocated; ngx_int_t rc; ngx_str_t path, uri; ngx_uint_t i, dir_tested; @@ -128,6 +128,7 @@ ngx_http_index_handler(ngx_http_request_ root = 0; dir_tested = 0; name = NULL; + /* suppress MSVC warning */ path.data = NULL; index = ilcf->indices->elts; @@ -139,8 +140,8 @@ ngx_http_index_handler(ngx_http_request_ return ngx_http_internal_redirect(r, &index[i].name, &r->args); } - len = ilcf->max_index_len; - nlen = index[i].name.len; + reserve = ilcf->max_index_len; + len = index[i].name.len; } else { ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); @@ -149,8 +150,7 @@ ngx_http_index_handler(ngx_http_request_ e.request = r; e.flushed = 1; - /* 1 byte for terminating '\0' */ - + /* 1 is for terminating '\0' as in static names */ len = 1; while (*(uintptr_t *) e.ip) { @@ -158,21 +158,19 @@ ngx_http_index_handler(ngx_http_request_ len += lcode(&e); } - nlen = len; - /* 16 bytes are preallocation */ - len += 16; + reserve = len + 16; } - if (len > (size_t) (path.data + allocated - name)) { + if (reserve > allocated) { - name = ngx_http_map_uri_to_path(r, &path, &root, len); + name = ngx_http_map_uri_to_path(r, &path, &root, reserve); if (name == NULL) { return NGX_ERROR; } - allocated = path.len; + allocated = path.data + path.len - name; } if (index[i].values == NULL) { @@ -193,7 +191,7 @@ ngx_http_index_handler(ngx_http_request_ } if (*name == '/') { - uri.len = nlen - 1; + uri.len = len - 1; uri.data = name; return ngx_http_internal_redirect(r, &uri, &r->args); } @@ -248,7 +246,7 @@ ngx_http_index_handler(ngx_http_request_ return NGX_HTTP_INTERNAL_SERVER_ERROR; } - uri.len = r->uri.len + nlen - 1; + uri.len = r->uri.len + len - 1; if (!clcf->alias) { uri.data = path.data + root; @@ -260,7 +258,7 @@ ngx_http_index_handler(ngx_http_request_ } p = ngx_copy(uri.data, r->uri.data, r->uri.len); - ngx_memcpy(p, name, nlen - 1); + ngx_memcpy(p, name, len - 1); } return ngx_http_internal_redirect(r, &uri, &r->args); @@ -491,7 +489,7 @@ ngx_http_index_set_index(ngx_conf_t *cf, continue; } - /* include the terminating '\0' to the length to use ngx_copy() */ + /* include the terminating '\0' to the length to use ngx_memcpy() */ index->name.len++; continue; 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 @@ -47,7 +47,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.7.31'; +our $VERSION = '0.7.33'; 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 @@ -1034,10 +1034,10 @@ ngx_int_t ngx_http_core_try_files_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph) { - size_t len, root, alias; - ssize_t reserve, allocated; + size_t len, root, alias, reserve, allocated; u_char *p, *name; ngx_str_t path; + ngx_uint_t test_dir; ngx_http_try_file_t *tf; ngx_open_file_info_t of; ngx_http_script_code_pt code; @@ -1058,7 +1058,7 @@ ngx_http_core_try_files_phase(ngx_http_r allocated = 0; root = 0; name = NULL; - path.len = 0; + /* suppress MSVC warning */ path.data = NULL; tf = clcf->try_files; @@ -1133,6 +1133,8 @@ ngx_http_core_try_files_phase(ngx_http_r } } + test_dir = tf->test_dir; + tf++; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -1172,7 +1174,7 @@ ngx_http_core_try_files_phase(ngx_http_r continue; } - if (!of.is_file) { + if (of.is_dir && !test_dir) { continue; } @@ -3853,6 +3855,11 @@ ngx_http_core_try_files(ngx_conf_t *cf, tf[i].name = value[i + 1]; + if (tf[i].name.data[tf[i].name.len - 1] == '/') { + tf[i].test_dir = 1; + tf[i].name.len--; + } + n = ngx_http_script_variables_count(&tf[i].name); if (n) { 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 @@ -245,6 +245,7 @@ typedef struct { ngx_array_t *lengths; ngx_array_t *values; ngx_str_t name; + ngx_uint_t test_dir; /* unsigned test_dir:1; */ } ngx_http_try_file_t; 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 @@ -2185,6 +2185,7 @@ ngx_http_set_keepalive(ngx_http_request_ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler"); if (r->discard_body) { + r->write_event_handler = ngx_http_request_empty_handler; r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000); ngx_add_timer(rev, clcf->lingering_timeout); return; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -2217,7 +2217,7 @@ ngx_http_upstream_process_request(ngx_ht tf = u->pipe->temp_file; - if (p->upstream_eof) { + if (p->upstream_eof || p->upstream_done) { if (u->headers_in.status_n == NGX_HTTP_OK && (u->headers_in.content_length_n == -1 diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -69,6 +69,8 @@ static ngx_int_t ngx_http_variable_sent_ ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_sent_location(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r, @@ -210,6 +212,9 @@ static ngx_http_variable_t ngx_http_cor { ngx_string("sent_http_content_length"), NULL, ngx_http_variable_sent_content_length, 0, 0, 0 }, + { ngx_string("sent_http_location"), NULL, + ngx_http_variable_sent_location, 0, 0, 0 }, + { ngx_string("sent_http_last_modified"), NULL, ngx_http_variable_sent_last_modified, 0, 0, 0 }, @@ -1242,6 +1247,26 @@ ngx_http_variable_sent_content_length(ng static ngx_int_t +ngx_http_variable_sent_location(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->headers_out.location) { + v->len = r->headers_out.location->value.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = r->headers_out.location->value.data; + + return NGX_OK; + } + + return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, + &r->headers_out.headers.part, + sizeof("sent_http_") - 1); +} + + +static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { diff --git a/src/mail/ngx_mail_smtp_handler.c b/src/mail/ngx_mail_smtp_handler.c --- a/src/mail/ngx_mail_smtp_handler.c +++ b/src/mail/ngx_mail_smtp_handler.c @@ -12,6 +12,7 @@ static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx); +static void ngx_mail_smtp_resolve_name(ngx_event_t *rev); static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx); static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c); static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev); @@ -91,9 +92,8 @@ ngx_mail_smtp_init_session(ngx_mail_sess static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx) { - ngx_connection_t *c; - ngx_mail_session_t *s; - ngx_mail_core_srv_conf_t *cscf; + ngx_connection_t *c; + ngx_mail_session_t *s; s = ctx->data; c = s->connection; @@ -134,6 +134,23 @@ ngx_mail_smtp_resolve_addr_handler(ngx_r ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0, "address resolved: %V", &s->host); + c->read->handler = ngx_mail_smtp_resolve_name; + + ngx_post_event(c->read, &ngx_posted_events); +} + + +static void +ngx_mail_smtp_resolve_name(ngx_event_t *rev) +{ + ngx_connection_t *c; + ngx_mail_session_t *s; + ngx_resolver_ctx_t *ctx; + ngx_mail_core_srv_conf_t *cscf; + + c = rev->data; + s = c->data; + cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module); ctx = ngx_resolve_start(cscf->resolver, NULL);