# HG changeset patch # User Igor Sysoev # Date 1245009600 -14400 # Node ID 116d5de7cbb6a89b47b1491bffc5cf9f172a21ea # Parent 6d9fb4461113f8e861a39200c87699c3405060d4 nginx 0.7.60 *) Feature: the "updating" parameter in "proxy_cache_use_stale" and "fastcgi_cache_use_stale" directives. *) Feature: the "keepalive_requests" directive. *) Bugfix: in open_file_cache and proxy/fastcgi cache interaction on start up. *) Bugfix: open_file_cache might cache open file descriptors too long. *) Bugfix: the "If-Modified-Since", "If-Range", etc. client request header lines were passed to backend while caching if no "proxy_set_header" directive was used with any parameters. *) Bugfix: the "Set-Cookie" and "P3P" response header lines were not hidden while caching if no "proxy_hide_header/fastcgi_hide_header" directives were used with any parameters. *) Bugfix: the ngx_http_image_filter_module did not support GIF87a format. Thanks to Denis Ilyinyh. *) Bugfix: nginx could not be built modules on Solaris 10 and early; the bug had appeared in 0.7.56. *) Bugfix: XLST filter did not work in subrequests. *) Bugfix: in relative paths handling in nginx/Windows. *) Bugfix: in proxy_store, fastcgi_store, proxy_cache, and fastcgi_cache in nginx/Windows. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,39 @@ +Changes with nginx 0.7.60 15 Jun 2009 + + *) Feature: the "updating" parameter in "proxy_cache_use_stale" and + "fastcgi_cache_use_stale" directives. + + *) Feature: the "keepalive_requests" directive. + + *) Bugfix: in open_file_cache and proxy/fastcgi cache interaction on + start up. + + *) Bugfix: open_file_cache might cache open file descriptors too long. + + *) Bugfix: the "If-Modified-Since", "If-Range", etc. client request + header lines were passed to backend while caching if no + "proxy_set_header" directive was used with any parameters. + + *) Bugfix: the "Set-Cookie" and "P3P" response header lines were not + hidden while caching if no "proxy_hide_header/fastcgi_hide_header" + directives were used with any parameters. + + *) Bugfix: the ngx_http_image_filter_module did not support GIF87a + format. + Thanks to Denis Ilyinyh. + + *) Bugfix: nginx could not be built modules on Solaris 10 and early; + the bug had appeared in 0.7.56. + + *) Bugfix: XLST filter did not work in subrequests. + + *) Bugfix: in relative paths handling in nginx/Windows. + + *) Bugfix: in proxy_store, fastcgi_store, proxy_cache, and + fastcgi_cache in nginx/Windows. + + Changes with nginx 0.7.59 25 May 2009 *) Feature: the "proxy_cache_methods" and "fastcgi_cache_methods" @@ -12,7 +47,7 @@ Changes with nginx 0.7.59 the bug had appeared in 0.7.58. *) Bugfix: the SSL modules might not built on Solaris and Linux; - the bug had appeared in 0.7.58. + the bug had appeared in 0.7.56. *) Bugfix: ngx_http_xslt_filter_module responses were not handled by SSI, charset, and gzip filters. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,40 @@ +Изменения в nginx 0.7.60 15.06.2009 + + *) Добавление: параметр updating в директивах proxy_cache_use_stale и + fastcgi_cache_use_stale. + + *) Добавление: директива keepalive_requests. + + *) Исправление: во взаимодействии open_file_cache и proxy/fastcgi кэша + на старте. + + *) Исправление: open_file_cache мог кэшировать открытые файлы очень + долго. + + *) Исправление: строки "If-Modified-Since", "If-Range" и им подобные в + заголовке запроса клиента передавались бэкенду при кэшировании, если + не использовалась директива proxy_set_header с любыми параметрами. + + *) Исправление: строки "Set-Cookie" и "P3P" в заголовке ответа бэкенда + не скрывались при кэшировании, если не использовались директивы + proxy_hide_header/fastcgi_hide_header с любыми параметрами. + + *) Исправление: модуль ngx_http_image_filter_module не понимал формат + GIF87a. + Спасибо Денису Ильиных. + + *) Исправление: nginx не собирался на Solaris 10 и более ранних; ошибка + появилась в 0.7.56. + + *) Исправление: XSLT-фильтр не работал в подзапросах. + + *) Исправление: обработке относительных путей в nginx/Windows. + + *) Исправление: в proxy_store, fastcgi_store, proxy_cache и + fastcgi_cache в nginx/Windows. + + Изменения в nginx 0.7.59 25.05.2009 *) Добавление: директивы proxy_cache_methods и fastcgi_cache_methods. @@ -56,7 +92,7 @@ Изменения в nginx 0.7.55 06.05.2009 - *) Исправление: параметры http_XXX в директиве proxy_cache_use_stale и + *) Исправление: параметры http_XXX в директивах proxy_cache_use_stale и fastcgi_cache_use_stale не работали. *) Исправление: fastcgi кэш не кэшировал ответы, состоящие только из diff --git a/auto/cc/msvc b/auto/cc/msvc --- a/auto/cc/msvc +++ b/auto/cc/msvc @@ -125,7 +125,7 @@ ngx_objext="obj" ngx_binext=".exe" ngx_long_start='@<< - ' + ' ngx_long_end='<<' ngx_long_regex_cont=' \ ' diff --git a/auto/lib/conf b/auto/lib/conf --- a/auto/lib/conf +++ b/auto/lib/conf @@ -4,15 +4,29 @@ if [ $USE_PCRE = YES -o $PCRE != NONE ]; then . auto/lib/pcre/conf + +else + if [ $USE_PCRE = DISABLED -a $HTTP_REWRITE = YES ]; then + +cat << END + +$0: error: the HTTP rewrite module requires the PCRE library. +You can either disable the module by using --without-http_rewrite_module +option or you have to enable the PCRE support. + +END + exit 1 + fi fi + if [ $USE_OPENSSL = YES ]; then . auto/lib/openssl/conf fi if [ $USE_MD5 = YES ]; then - if [ $OPENSSL != NONE -a $OPENSSL != NO ]; then + if [ $USE_OPENSSL = YES ]; then have=NGX_HAVE_OPENSSL_MD5_H . auto/have have=NGX_OPENSSL_MD5 . auto/have MD5=YES @@ -26,7 +40,7 @@ fi if [ $USE_SHA1 = YES ]; then - if [ $OPENSSL != NONE -a $OPENSSL != NO ]; then + if [ $USE_OPENSSL = YES ]; then have=NGX_HAVE_OPENSSL_SHA1_H . auto/have SHA1=YES SHA1_LIB=OpenSSL diff --git a/auto/lib/google-perftools/conf b/auto/lib/google-perftools/conf --- a/auto/lib/google-perftools/conf +++ b/auto/lib/google-perftools/conf @@ -30,4 +30,15 @@ fi if [ $ngx_found = yes ]; then CORE_LIBS="$CORE_LIBS $ngx_feature_libs" + +else + +cat << END + +$0: error: the Google perftool module requires the Google perftools +library. You can either do not enable the module or install the library. + +END + + exit 1 fi diff --git a/auto/lib/md5/conf b/auto/lib/md5/conf --- a/auto/lib/md5/conf +++ b/auto/lib/md5/conf @@ -94,6 +94,18 @@ else CORE_LIBS="$CORE_LIBS $ngx_feature_libs" MD5=YES MD5_LIB=$ngx_md5_lib + else + +cat << END + +$0: error: the HTTP cache module requires md5 functions +from OpenSSL library. You can either disable the module by using +--without-http_cache option, or install the OpenSSL library into the system, +or build the OpenSSL library statically from the source with nginx by using +--with-openssl= option. + +END + exit 1 fi fi diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf --- a/auto/lib/openssl/conf +++ b/auto/lib/openssl/conf @@ -66,6 +66,17 @@ else have=NGX_SSL . auto/have CORE_LIBS="$CORE_LIBS $ngx_feature_libs $NGX_LIBDL" OPENSSL=YES + else + +cat << END + +$0: error: SSL modules require the OpenSSL library. +You can either do not enable the modules, or install the OpenSSL library +into the system, or build the OpenSSL library statically from the source +with nginx by using --with-openssl= option. + +END + exit 1 fi ;; diff --git a/auto/lib/openssl/make b/auto/lib/openssl/make --- a/auto/lib/openssl/make +++ b/auto/lib/openssl/make @@ -2,11 +2,6 @@ # Copyright (C) Igor Sysoev -case $USE_THREADS in - NO) OPENSSL_OPT="$OPENSSL_OPT no-threads" ;; - *) OPENSSL_OPT="$OPENSSL_OPT threads" ;; -esac - case "$CC" in cl) @@ -21,7 +16,7 @@ END ;; - cl | bcc32) + bcc32) ngx_opt=`echo "-DOPENSSL=\"$OPENSSL\" -DOPENSSL_OPT=\"$OPENSSL_OPT\"" \ | sed -e "s/\//$ngx_regex_dirsep/g"` @@ -45,16 +40,14 @@ END ;; *) - case $OPENSSL in + case $USE_THREADS in + NO) OPENSSL_OPT="$OPENSSL_OPT no-threads" ;; + *) OPENSSL_OPT="$OPENSSL_OPT threads" ;; + esac - /*) - ngx_prefix="$OPENSSL/openssl" - ;; - - *) - ngx_prefix="$PWD/$OPENSSL/openssl" - ;; - + case $OPENSSL in + /*) ngx_prefix="$OPENSSL/openssl" ;; + *) ngx_prefix="$PWD/$OPENSSL/openssl" ;; esac cat << END >> $NGX_MAKEFILE diff --git a/auto/lib/pcre/conf b/auto/lib/pcre/conf --- a/auto/lib/pcre/conf +++ b/auto/lib/pcre/conf @@ -161,6 +161,18 @@ else CORE_INCS="$CORE_INCS $ngx_feature_path" CORE_LIBS="$CORE_LIBS $ngx_feature_libs" PCRE=YES + else + +cat << END + +$0: error: the HTTP rewrite module requires the PCRE library. +You can either disable the module by using --without-http_rewrite_module +option, or install the PCRE library into the system, or build the PCRE library +statically from the source with nginx by using --with-pcre= option. + +END + exit 1 + fi fi diff --git a/auto/lib/zlib/conf b/auto/lib/zlib/conf --- a/auto/lib/zlib/conf +++ b/auto/lib/zlib/conf @@ -57,6 +57,17 @@ else CORE_LIBS="$CORE_LIBS $ngx_feature_libs" ZLIB=YES ngx_found=no + else + +cat << END + +$0: error: the HTTP gzip module requires the zlib library. +You can either disable the module by using --without-http_gzip_module +option, or install the zlib library into the system, or build the zlib library +statically from the source with nginx by using --with-zlib= option. + +END + exit 1 fi fi diff --git a/auto/os/features b/auto/os/features --- a/auto/os/features +++ b/auto/os/features @@ -252,3 +252,25 @@ if [ $ngx_found != yes ]; then NGX_LIBDL="-ldl" fi fi + + +ngx_feature="sched_yield()" +ngx_feature_name="NGX_HAVE_SCHED_YIELD" +ngx_feature_run=no +ngx_feature_incs="#include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="sched_yield()" +. auto/feature + + +if [ $ngx_found != yes ]; then + + ngx_feature="sched_yield() in librt" + ngx_feature_libs="-lrt" + . auto/feature + + if [ $ngx_found = yes ]; then + CORE_LIBS="$CORE_LIBS -lrt" + fi +fi diff --git a/auto/summary b/auto/summary --- a/auto/summary +++ b/auto/summary @@ -74,65 +74,6 @@ esac echo -if [ $HTTP_REWRITE = YES ]; then - if [ $USE_PCRE = DISABLED ]; then - -cat << END -$0: error: the HTTP rewrite module requires the PCRE library. -You can either disable the module by using --without-http_rewrite_module -option or you have to enable the PCRE support. - -END - exit 1 - fi - - if [ $PCRE = NONE -o $PCRE = NO ]; then - -cat << END -$0: error: the HTTP rewrite module requires the PCRE library. -You can either disable the module by using --without-http_rewrite_module -option, or install the PCRE library into the system, or build the PCRE library -statically from the source with nginx by using --with-pcre= option. - -END - - exit 1 - fi -fi - - -if [ $HTTP_GZIP = YES ]; then - if [ $ZLIB = NONE -o $ZLIB = NO ]; then - -cat << END -$0: error: the HTTP gzip module requires the zlib library. -You can either disable the module by using --without-http_gzip_module -option, or install the zlib library into the system, or build the zlib library -statically from the source with nginx by using --with-zlib= option. - -END - - exit 1 - fi -fi - - -if [ $HTTP_SSL = YES ]; then - if [ $OPENSSL = NONE -o $OPENSSL = NO ]; then - -cat << END -$0: error: the HTTP SSL module requires the OpenSSL library. -You can either do not enable the module, or install the OpenSSL library -into the system, or build the OpenSSL library statically from the source -with nginx by using --with-openssl= option. - -END - - exit 1 - fi -fi - - cat << END nginx path prefix: "$NGX_PREFIX" nginx binary file: "$NGX_SBIN_PATH" diff --git a/auto/unix b/auto/unix --- a/auto/unix +++ b/auto/unix @@ -163,28 +163,6 @@ ngx_feature_test="void *p; p = memalign( . auto/feature -ngx_feature="sched_yield()" -ngx_feature_name="NGX_HAVE_SCHED_YIELD" -ngx_feature_run=no -ngx_feature_incs="#include " -ngx_feature_path= -ngx_feature_libs= -ngx_feature_test="sched_yield()" -. auto/feature - - -if [ $ngx_found != yes ]; then - - ngx_feature="sched_yield() in librt" - ngx_feature_libs="-lrt" - . auto/feature - - if [ $ngx_found = yes ]; then - CORE_LIBS="$CORE_LIBS -lrt" - fi -fi - - ngx_feature="mmap(MAP_ANON|MAP_SHARED)" ngx_feature_name="NGX_HAVE_MAP_ANON" ngx_feature_run=yes diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -330,6 +330,10 @@ main(int argc, char *const *argv) return 0; } + if (ngx_signal) { + return ngx_signal_process(cycle, ngx_signal); + } + ngx_os_status(cycle->log); ngx_cycle = cycle; @@ -340,10 +344,6 @@ main(int argc, char *const *argv) ngx_process = NGX_PROCESS_MASTER; } - if (ngx_signal) { - return ngx_signal_process(cycle, ngx_signal); - } - #if !(NGX_WIN32) if (ngx_init_signals(cycle->log) != NGX_OK) { 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 7059 -#define NGINX_VERSION "0.7.59" +#define nginx_version 7060 +#define NGINX_VERSION "0.7.60" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" 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 @@ -12,6 +12,7 @@ static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last); static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf); static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static ngx_int_t ngx_conf_test_full_name(ngx_str_t *name); static void ngx_conf_flush_files(ngx_cycle_t *cycle); @@ -802,29 +803,15 @@ ngx_int_t ngx_conf_full_name(ngx_cycle_t *cycle, ngx_str_t *name, ngx_uint_t conf_prefix) { size_t len; - u_char *p, *prefix; - ngx_str_t old; - -#if (NGX_WIN32) + u_char *p, *n, *prefix; + ngx_int_t rc; - if (name->len > 2 - && name->data[1] == ':' - && ((name->data[0] >= 'a' && name->data[0] <= 'z') - || (name->data[0] >= 'A' && name->data[0] <= 'Z'))) - { - return NGX_OK; - } + rc = ngx_conf_test_full_name(name); -#else - - if (name->data[0] == '/') { - return NGX_OK; + if (rc == NGX_OK) { + return rc; } -#endif - - old = *name; - if (conf_prefix) { len = cycle->conf_prefix.len; prefix = cycle->conf_prefix.data; @@ -834,19 +821,79 @@ ngx_conf_full_name(ngx_cycle_t *cycle, n prefix = cycle->prefix.data; } - name->len = len + old.len; - name->data = ngx_pnalloc(cycle->pool, name->len + 1); - if (name->data == NULL) { +#if (NGX_WIN32) + + if (rc == 2) { + len = rc; + } + +#endif + + n = ngx_pnalloc(cycle->pool, len + name->len + 1); + if (n == NULL) { return NGX_ERROR; } - p = ngx_cpymem(name->data, prefix, len); - ngx_cpystrn(p, old.data, old.len + 1); + p = ngx_cpymem(n, prefix, len); + ngx_cpystrn(p, name->data, name->len + 1); + + name->len += len; + name->data = n; return NGX_OK; } +static ngx_int_t +ngx_conf_test_full_name(ngx_str_t *name) +{ +#if (NGX_WIN32) + u_char c0, c1; + + c0 = name->data[0]; + + if (name->len < 2) { + if (c0 == '/') { + return 2; + } + + return NGX_DECLINED; + } + + c1 = name->data[1]; + + if (c1 == ':') { + c0 |= 0x20; + + if ((c0 >= 'a' && c0 <= 'z')) { + return NGX_OK; + } + + return NGX_DECLINED; + } + + if (c1 == '/') { + return NGX_OK; + } + + if (c0 == '/') { + return 2; + } + + return NGX_DECLINED; + +#else + + if (name->data[0] == '/') { + return NGX_OK; + } + + return NGX_DECLINED; + +#endif +} + + ngx_open_file_t * ngx_conf_open_file(ngx_cycle_t *cycle, ngx_str_t *name) { diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -603,6 +603,8 @@ ngx_close_listening_sockets(ngx_cycle_t ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); } + + ls[i].fd = (ngx_socket_t) -1; } } diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -135,6 +135,8 @@ struct ngx_connection_s { ngx_atomic_uint_t number; + ngx_uint_t requests; + unsigned buffered:8; unsigned log_error:3; /* ngx_connection_log_error_e */ 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 @@ -269,7 +269,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) cycle->conf_file.data); } - for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; @@ -287,6 +286,9 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) } } + if (ngx_process == NGX_PROCESS_SIGNALLER) { + return cycle; + } ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); @@ -463,11 +465,8 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) goto failed; } - if (!shm_zone[i].shm.exists) { - - if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) { - goto failed; - } + if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) { + goto failed; } if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) { @@ -567,14 +566,12 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) } } - if (ngx_process != NGX_PROCESS_SIGNALLER) { - if (ngx_open_listening_sockets(cycle) != NGX_OK) { - goto failed; - } + if (ngx_open_listening_sockets(cycle) != NGX_OK) { + goto failed; + } - if (!ngx_test_config) { - ngx_configure_listening_sockets(cycle); - } + if (!ngx_test_config) { + ngx_configure_listening_sockets(cycle); } @@ -656,7 +653,8 @@ old_shm_zone_done: ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { - if (ls[i].remain) { + + if (ls[i].remain || ls[i].fd == -1) { continue; } @@ -885,8 +883,21 @@ ngx_init_zone_pool(ngx_cycle_t *cycle, n sp = (ngx_slab_pool_t *) zn->shm.addr; + if (zn->shm.exists) { + + if (sp == sp->addr) { + return NGX_OK; + } + + ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, + "shared zone \"%V\" has no equal addresses: %p vs %p", + &zn->shm.name, sp->addr, sp); + return NGX_ERROR; + } + sp->end = zn->shm.addr + zn->shm.size; sp->min_shift = 3; + sp->addr = zn->shm.addr; #if (NGX_HAVE_ATOMIC_OPS) diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -558,8 +558,14 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_ err = ngx_errno; - if (err == NGX_ENOENT) { - + if (err +#if (NGX_WIN32) + == ERROR_PATH_NOT_FOUND +#else + == NGX_ENOENT +#endif + ) + { if (!ext->create_path) { goto failed; } 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 @@ -360,6 +360,7 @@ create: file->uses = 1; file->count = 0; + file->use_event = 0; file->event = NULL; add_event: 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 @@ -503,6 +503,7 @@ ngx_output_chain_copy_buf(ngx_output_cha if (src->pos == src->last) { dst->flush = src->flush; dst->last_buf = src->last_buf; + dst->last_in_chain = src->last_in_chain; } } else { @@ -577,6 +578,7 @@ ngx_output_chain_copy_buf(ngx_output_cha if (src->file_pos == src->file_last) { dst->flush = src->flush; dst->last_buf = src->last_buf; + dst->last_in_chain = src->last_in_chain; } } diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c --- a/src/core/ngx_palloc.c +++ b/src/core/ngx_palloc.c @@ -25,6 +25,7 @@ ngx_create_pool(size_t size, ngx_log_t * p->d.last = (u_char *) p + sizeof(ngx_pool_t); p->d.end = (u_char *) p + size; p->d.next = NULL; + p->d.failed = 0; size = size - sizeof(ngx_pool_t); p->max = (size < NGX_MAX_ALLOC_FROM_POOL) ? size : NGX_MAX_ALLOC_FROM_POOL; @@ -189,6 +190,7 @@ ngx_palloc_block(ngx_pool_t *pool, size_ new->d.end = m + psize; new->d.next = NULL; + new->d.failed = 0; m += sizeof(ngx_pool_data_t); m = ngx_align_ptr(m, NGX_ALIGNMENT); @@ -197,7 +199,7 @@ ngx_palloc_block(ngx_pool_t *pool, size_ current = pool->current; for (p = current; p->d.next; p = p->d.next) { - if ((size_t) (p->d.end - p->d.last) < NGX_ALIGNMENT) { + if (p->d.failed++ > 4) { current = p->d.next; } } @@ -214,6 +216,7 @@ static void * ngx_palloc_large(ngx_pool_t *pool, size_t size) { void *p; + ngx_uint_t n; ngx_pool_large_t *large; p = ngx_alloc(size, pool->log); @@ -221,6 +224,19 @@ ngx_palloc_large(ngx_pool_t *pool, size_ return NULL; } + n = 0; + + for (large = pool->large; large; large = large->next) { + if (large->alloc == NULL) { + large->alloc = p; + return p; + } + + if (n++ > 3) { + break; + } + } + large = ngx_palloc(pool, sizeof(ngx_pool_large_t)); if (large == NULL) { ngx_free(p); diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h --- a/src/core/ngx_palloc.h +++ b/src/core/ngx_palloc.h @@ -46,6 +46,7 @@ typedef struct { u_char *last; u_char *end; ngx_pool_t *next; + ngx_uint_t failed; } ngx_pool_data_t; diff --git a/src/core/ngx_slab.h b/src/core/ngx_slab.h --- a/src/core/ngx_slab.h +++ b/src/core/ngx_slab.h @@ -39,6 +39,7 @@ typedef struct { u_char zero; void *data; + void *addr; } ngx_slab_pool_t; 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 @@ -178,6 +178,7 @@ static ngx_conf_bitmask_t ngx_http_fast { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 }, { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 }, { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 }, + { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING }, { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, { ngx_null_string, 0 } }; @@ -1911,7 +1912,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf if (conf->upstream.store != 0) { ngx_conf_merge_value(conf->upstream.store, - prev->upstream.store, 0); + prev->upstream.store, 0); if (conf->upstream.store_lengths == NULL) { conf->upstream.store_lengths = prev->upstream.store_lengths; @@ -2541,20 +2542,31 @@ ngx_http_fastcgi_store(ngx_conf_t *cf, n ngx_str_t *value; ngx_http_script_compile_t sc; - if (flcf->upstream.store != NGX_CONF_UNSET || flcf->upstream.store_lengths) + if (flcf->upstream.store != NGX_CONF_UNSET + || flcf->upstream.store_lengths) { return "is duplicate"; } value = cf->args->elts; - if (ngx_strcmp(value[1].data, "on") == 0) { - flcf->upstream.store = 1; + if (ngx_strcmp(value[1].data, "off") == 0) { + flcf->upstream.store = 0; return NGX_CONF_OK; } - if (ngx_strcmp(value[1].data, "off") == 0) { - flcf->upstream.store = 0; +#if (NGX_HTTP_CACHE) + + if (flcf->upstream.cache != NGX_CONF_UNSET_PTR + && flcf->upstream.cache != NULL) + { + return "is incompatible with \"fastcgi_cache\""; + } + +#endif + + if (ngx_strcmp(value[1].data, "on") == 0) { + flcf->upstream.store = 1; return NGX_CONF_OK; } @@ -2599,6 +2611,10 @@ ngx_http_fastcgi_cache(ngx_conf_t *cf, n return NGX_CONF_OK; } + if (flcf->upstream.store > 0 || flcf->upstream.store_lengths) { + return "is incompatible with \"fastcgi_store\""; + } + flcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0, &ngx_http_fastcgi_module); if (flcf->upstream.cache == NULL) { diff --git a/src/http/modules/ngx_http_image_filter_module.c b/src/http/modules/ngx_http_image_filter_module.c --- a/src/http/modules/ngx_http_image_filter_module.c +++ b/src/http/modules/ngx_http_image_filter_module.c @@ -383,11 +383,12 @@ ngx_http_image_test(ngx_http_request_t * return NGX_HTTP_IMAGE_JPEG; } else if (p[0] == 'G' && p[1] == 'I' && p[2] == 'F' && p[3] == '8' - && p[4] == '9' && p[5] == 'a') + && p[5] == 'a') { - /* GIF */ - - return NGX_HTTP_IMAGE_GIF; + if (p[4] == '9' || p[4] == '7') { + /* GIF */ + return NGX_HTTP_IMAGE_GIF; + } } else if (p[0] == 0x89 && p[1] == 'P' && p[2] == 'N' && p[3] == 'G' && p[4] == 0x0d && p[5] == 0x0a && p[6] == 0x1a && p[7] == 0x0a) diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -167,6 +167,7 @@ static ngx_conf_bitmask_t ngx_http_prox { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 }, { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 }, { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 }, + { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING }, { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF }, { ngx_null_string, 0 } }; @@ -1973,7 +1974,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t if (conf->upstream.store != 0) { ngx_conf_merge_value(conf->upstream.store, - prev->upstream.store, 0); + prev->upstream.store, 0); if (conf->upstream.store_lengths == NULL) { conf->upstream.store_lengths = prev->upstream.store_lengths; @@ -2341,7 +2342,9 @@ ngx_http_proxy_merge_headers(ngx_conf_t conf->headers_source = prev->headers_source; } - if (conf->headers_set_hash.buckets) { + if (conf->headers_set_hash.buckets + && ((conf->upstream.cache == NULL) == (prev->upstream.cache == NULL))) + { return NGX_OK; } @@ -2809,20 +2812,31 @@ ngx_http_proxy_store(ngx_conf_t *cf, ngx ngx_str_t *value; ngx_http_script_compile_t sc; - if (plcf->upstream.store != NGX_CONF_UNSET || plcf->upstream.store_lengths) + if (plcf->upstream.store != NGX_CONF_UNSET + || plcf->upstream.store_lengths) { return "is duplicate"; } value = cf->args->elts; - if (ngx_strcmp(value[1].data, "on") == 0) { - plcf->upstream.store = 1; + if (ngx_strcmp(value[1].data, "off") == 0) { + plcf->upstream.store = 0; return NGX_CONF_OK; } - if (ngx_strcmp(value[1].data, "off") == 0) { - plcf->upstream.store = 0; +#if (NGX_HTTP_CACHE) + + if (plcf->upstream.cache != NGX_CONF_UNSET_PTR + && plcf->upstream.cache != NULL) + { + return "is incompatible with \"proxy_cache\""; + } + +#endif + + if (ngx_strcmp(value[1].data, "on") == 0) { + plcf->upstream.store = 1; return NGX_CONF_OK; } @@ -2867,6 +2881,10 @@ ngx_http_proxy_cache(ngx_conf_t *cf, ngx return NGX_CONF_OK; } + if (plcf->upstream.store > 0 || plcf->upstream.store_lengths) { + return "is incompatible with \"proxy_store\""; + } + plcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0, &ngx_http_proxy_module); if (plcf->upstream.cache == NULL) { diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c --- a/src/http/modules/ngx_http_xslt_filter_module.c +++ b/src/http/modules/ngx_http_xslt_filter_module.c @@ -280,7 +280,7 @@ ngx_http_xslt_body_filter(ngx_http_reque return ngx_http_xslt_send(r, ctx, NULL); } - if (cl->buf->last_buf) { + if (cl->buf->last_buf || cl->buf->last_in_chain) { ctx->doc = ctx->ctxt->myDoc; @@ -427,8 +427,8 @@ ngx_http_xslt_add_chunk(ngx_http_request ctx->request = r; } - err = xmlParseChunk(ctx->ctxt, (char *) b->pos, - (int) (b->last - b->pos), b->last_buf); + err = xmlParseChunk(ctx->ctxt, (char *) b->pos, (int) (b->last - b->pos), + (b->last_buf) || (b->last_in_chain)); if (err == 0) { b->pos = b->last; @@ -812,7 +812,6 @@ ngx_http_xslt_apply_stylesheet(ngx_http_ b->pos = buf; b->last = buf + len; b->memory = 1; - b->last_buf = 1; if (encoding) { r->headers_out.charset.len = ngx_strlen(encoding); @@ -823,6 +822,8 @@ ngx_http_xslt_apply_stylesheet(ngx_http_ return b; } + b->last_buf = 1; + if (type) { len = ngx_strlen(type); 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.59'; +our $VERSION = '0.7.60'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -13,11 +13,8 @@ #include -/**/ #define NGX_HTTP_CACHE_STALE 1 -#define NGX_HTTP_CACHE_AGED 2 -#define NGX_HTTP_CACHE_THE_SAME 3 -/**/ +#define NGX_HTTP_CACHE_UPDATING 2 #define NGX_HTTP_CACHE_KEY_LEN 16 @@ -28,8 +25,6 @@ typedef struct { } ngx_http_cache_valid_t; -/* ngx_http_file_cache_node_t takes exactly 64 bytes on FreeBSD/i386 */ - typedef struct { ngx_rbtree_node_t node; ngx_queue_t queue; @@ -41,8 +36,9 @@ typedef struct { unsigned uses:10; unsigned valid_msec:10; unsigned error:10; - /* 7 unused bits */ unsigned exists:1; + unsigned updating:1; + /* 12 unused bits */ ngx_file_uniq_t uniq; time_t expire; @@ -68,7 +64,6 @@ struct ngx_http_cache_s { off_t length; ngx_uint_t min_uses; - ngx_uint_t uses; ngx_uint_t error; ngx_uint_t valid_msec; 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 @@ -440,6 +440,13 @@ static ngx_command_t ngx_http_core_comm 0, NULL }, + { ngx_string("keepalive_requests"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, keepalive_requests), + NULL }, + { ngx_string("satisfy"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_enum_slot, @@ -1326,8 +1333,13 @@ ngx_http_update_location_config(ngx_http r->request_body_in_single_buf = clcf->client_body_in_single_buffer; - if (r->keepalive && clcf->keepalive_timeout == 0) { - r->keepalive = 0; + if (r->keepalive) { + if (clcf->keepalive_timeout == 0) { + r->keepalive = 0; + + } else if (r->connection->requests >= clcf->keepalive_requests) { + r->keepalive = 0; + } } if (!clcf->tcp_nopush) { @@ -2914,6 +2926,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t lcf->limit_rate = NGX_CONF_UNSET_SIZE; lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC; lcf->keepalive_header = NGX_CONF_UNSET; + lcf->keepalive_requests = NGX_CONF_UNSET_UINT; lcf->lingering_time = NGX_CONF_UNSET_MSEC; lcf->lingering_timeout = NGX_CONF_UNSET_MSEC; lcf->resolver_timeout = NGX_CONF_UNSET_MSEC; @@ -3114,6 +3127,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t prev->keepalive_timeout, 75000); ngx_conf_merge_sec_value(conf->keepalive_header, prev->keepalive_header, 0); + ngx_conf_merge_uint_value(conf->keepalive_requests, + prev->keepalive_requests, 100); ngx_conf_merge_msec_value(conf->lingering_time, prev->lingering_time, 30000); ngx_conf_merge_msec_value(conf->lingering_timeout, 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 @@ -337,6 +337,7 @@ struct ngx_http_core_loc_conf_s { time_t keepalive_header; /* keepalive_timeout */ + ngx_uint_t keepalive_requests; /* keepalive_requests */ ngx_uint_t satisfy; /* satisfy */ ngx_uint_t if_modified_since; /* if_modified_since */ ngx_uint_t client_body_in_file_only; /* client_body_in_file_only */ diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -172,9 +172,8 @@ ngx_http_file_cache_open(ngx_http_reques rc = ngx_http_file_cache_exists(cache, c); - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http file cache exists: %i u:%ui e:%d", - rc, c->uses, c->exists); + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http file cache exists: %i e:%d", rc, c->exists); if (rc == NGX_ERROR) { return rc; @@ -321,6 +320,7 @@ ngx_http_file_cache_open(ngx_http_reques c->node->uses = 1; c->node->body_start = c->body_start; c->node->exists = 1; + c->node->uniq = of.uniq; cache->sh->size += (c->length + cache->bsize - 1) / cache->bsize; } @@ -332,16 +332,25 @@ ngx_http_file_cache_open(ngx_http_reques if (c->valid_sec < now) { - c->uses = c->min_uses; + ngx_shmtx_lock(&cache->shpool->mutex); - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http file cache expired: %T %T", c->valid_sec, now); + if (c->node->updating) { + rc = NGX_HTTP_CACHE_UPDATING; - return NGX_HTTP_CACHE_STALE; + } else { + c->node->updating = 1; + rc = NGX_HTTP_CACHE_STALE; + } + + ngx_shmtx_unlock(&cache->shpool->mutex); + + ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http file cache expired: %i %T %T", + rc, c->valid_sec, now); + + return rc; } - /* TODO: NGX_HTTP_CACHE_AGED */ - return NGX_OK; } @@ -442,7 +451,6 @@ done: ngx_queue_insert_head(&cache->sh->queue, &fcn->queue); c->uniq = fcn->uniq; - c->uses = fcn->uses; c->error = fcn->error; c->node = fcn; @@ -654,6 +662,8 @@ ngx_http_file_cache_update(ngx_http_requ c->node->exists = 1; } + c->node->updating = 0; + ngx_shmtx_unlock(&cache->shpool->mutex); } @@ -736,6 +746,8 @@ ngx_http_file_cache_free(ngx_http_reques c->node->error = c->error; } + c->node->updating = 0; + ngx_shmtx_unlock(&cache->shpool->mutex); if (c->temp_file) { 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 @@ -259,6 +259,8 @@ ngx_http_init_request(ngx_event_t *rev) return; } + c->requests++; + hc = c->data; if (hc == NULL) { 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 @@ -577,8 +577,17 @@ ngx_http_upstream_cache(ngx_http_request rc = ngx_http_file_cache_open(r); - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http upstream cache: %i u:%ui", rc, c->uses); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http upstream cache: %i", rc); + + if (rc == NGX_HTTP_CACHE_UPDATING) { + if (u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING) { + rc = NGX_OK; + + } else { + rc = NGX_HTTP_CACHE_STALE; + } + } if (rc == NGX_OK) { @@ -4076,7 +4085,9 @@ ngx_http_upstream_hide_headers_hash(ngx_ { conf->hide_headers_hash = prev->hide_headers_hash; - if (conf->hide_headers_hash.buckets) { + if (conf->hide_headers_hash.buckets + && ((conf->cache == NULL) == (prev->cache == NULL))) + { return NGX_OK; } diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -24,8 +24,9 @@ #define NGX_HTTP_UPSTREAM_FT_HTTP_503 0x00000040 #define NGX_HTTP_UPSTREAM_FT_HTTP_504 0x00000080 #define NGX_HTTP_UPSTREAM_FT_HTTP_404 0x00000100 -#define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00000200 -#define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00000400 +#define NGX_HTTP_UPSTREAM_FT_UPDATING 0x00000200 +#define NGX_HTTP_UPSTREAM_FT_BUSY_LOCK 0x00000400 +#define NGX_HTTP_UPSTREAM_FT_MAX_WAITING 0x00000800 #define NGX_HTTP_UPSTREAM_FT_NOLIVE 0x40000000 #define NGX_HTTP_UPSTREAM_FT_OFF 0x80000000