# HG changeset patch # User Igor Sysoev # Date 1269806400 -14400 # Node ID be4f34123024c582d06401144a678ed96f7963bc # Parent dd7104f21940d9026698b6db4a52622f49745caa nginx 0.8.35 *) Change: now the charset filter runs before the SSI filter. *) Feature: the "chunked_transfer_encoding" directive. *) Bugfix: an "&" character was not escaped when it was copied in arguments part in a rewrite rule. *) Bugfix: nginx might be terminated abnormally while a signal processing or if the directive "timer_resolution" was used on platforms which do not support kqueue or eventport notification methods. Thanks to George Xie and Maxim Dounin. *) Bugfix: if temporary files and permanent storage area resided at different file systems, then permanent file modification times were incorrect. Thanks to Maxim Dounin. *) Bugfix: ngx_http_memcached_module might issue the error message "memcached sent invalid trailer". Thanks to Maxim Dounin. *) Bugfix: nginx could not built zlib-1.2.4 library using the library sources. Thanks to Maxim Dounin. *) Bugfix: a segmentation fault occurred in a worker process, if there was large stderr output before FastCGI response; the bug had appeared in 0.8.34. Thanks to Maxim Dounin. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,38 @@ +Changes with nginx 0.8.35 29 Mar 2010 + + *) Change: now the charset filter runs before the SSI filter. + + *) Feature: the "chunked_transfer_encoding" directive. + + *) Bugfix: an "&" character was not escaped when it was copied in + arguments part in a rewrite rule. + + *) Bugfix: nginx might be terminated abnormally while a signal + processing or if the directive "timer_resolution" was used on + platforms which do not support kqueue or eventport notification + methods. + Thanks to George Xie and Maxim Dounin. + + *) Bugfix: if temporary files and permanent storage area resided at + different file systems, then permanent file modification times were + incorrect. + Thanks to Maxim Dounin. + + *) Bugfix: ngx_http_memcached_module might issue the error message + "memcached sent invalid trailer". + Thanks to Maxim Dounin. + + *) Bugfix: nginx could not built zlib-1.2.4 library using the library + sources. + Thanks to Maxim Dounin. + + *) Bugfix: a segmentation fault occurred in a worker process, if there + was large stderr output before FastCGI response; the bug had + appeared in 0.8.34. + Thanks to Maxim Dounin. + + Changes with nginx 0.8.34 03 Mar 2010 *) Bugfix: nginx did not support all ciphers and digests used in client @@ -11,7 +45,7 @@ Changes with nginx 0.8.34 *) Bugfix: nginx did not support HTTPS referrers. *) Bugfix: nginx/Windows might not find file if path in configuration - was given in other character case; the bug had appeared in 0.8.34. + was given in other character case; the bug had appeared in 0.8.33. *) Bugfix: the $date_local variable has an incorrect value, if the "%s" format was used. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,37 @@ +Изменения в nginx 0.8.35 29.03.2010 + + *) Изменение: теперь charset-фильтр работает до SSI-фильтра. + + *) Добавление: директива chunked_transfer_encoding. + + *) Исправление: символ "&" при копировании в аргументы в правилах + rewrite не экранировался. + + *) Исправление: nginx мог завершаться аварийно во время обработки + сигнала или при использовании директивы timer_resolution на + платформах, не поддерживающих методы kqueue или eventport. + Спасибо George Xie и Максиму Дунину. + + *) Исправление: если временные файлы и постоянное место хранения + располагались на разных файловых системах, то у постоянных файлов + время изменения было неверным. + Спасибо Максиму Дунину. + + *) Исправление: модуль ngx_http_memcached_module мог выдавать ошибку + "memcached sent invalid trailer". + Спасибо Максиму Дунину. + + *) Исправление: nginx не мог собрать библиотеку zlib-1.2.4 из исходных + текстов. + Спасибо Максиму Дунину. + + *) Исправление: в рабочем процессе происходил segmentation fault, если + перед ответом FastCGI-сервера было много вывода в stderr; ошибка + появилась в 0.8.34. + Спасибо Максиму Дунину. + + Изменения в nginx 0.8.34 03.03.2010 *) Исправление: nginx не поддерживал все шифры, используемые в @@ -11,7 +44,7 @@ *) Исправление: nginx не поддерживал HTTPS-рефереры. *) Исправление: nginx/Windows мог не находить файлы, если путь в - конфигурации был задан в другом регистре; ошибка появилась в 0.8.34. + конфигурации был задан в другом регистре; ошибка появилась в 0.8.33. *) Исправление: переменная $date_local выдавала неверное время, если использовался формат "%s". @@ -1962,7 +1995,7 @@ Спасибо Андрею Нигматулину. *) Исправление: ngx_http_memcached_module не устанавливал - upstream_response_time. + $upstream_response_time. Спасибо Максиму Дунину. *) Исправление: рабочий процесс мог зациклиться при использовании diff --git a/auto/lib/openssl/conf b/auto/lib/openssl/conf --- a/auto/lib/openssl/conf +++ b/auto/lib/openssl/conf @@ -19,6 +19,8 @@ if [ $OPENSSL != NONE ]; then # libeay32.lib requires gdi32.lib CORE_LIBS="$CORE_LIBS gdi32.lib" + # OpenSSL 1.0.0 requires crypt32.lib + CORE_LIBS="$CORE_LIBS crypt32.lib" ;; *) diff --git a/auto/lib/openssl/makefile.bcc b/auto/lib/openssl/makefile.bcc --- a/auto/lib/openssl/makefile.bcc +++ b/auto/lib/openssl/makefile.bcc @@ -5,8 +5,7 @@ all: cd $(OPENSSL) - perl Configure BC-32 no-shared --prefix=openssl -DNO_SYS_TYPES_H \ - $(OPENSSL_OPT) + perl Configure BC-32 no-shared --prefix=openssl $(OPENSSL_OPT) ms\do_nasm diff --git a/auto/lib/openssl/makefile.msvc b/auto/lib/openssl/makefile.msvc --- a/auto/lib/openssl/makefile.msvc +++ b/auto/lib/openssl/makefile.msvc @@ -5,8 +5,7 @@ all: cd $(OPENSSL) - perl Configure VC-WIN32 no-shared --prefix=openssl -DNO_SYS_TYPES_H \ - $(OPENSSL_OPT) + perl Configure VC-WIN32 no-shared --prefix=openssl $(OPENSSL_OPT) ms\do_ms diff --git a/auto/lib/zlib/make b/auto/lib/zlib/make --- a/auto/lib/zlib/make +++ b/auto/lib/zlib/make @@ -53,7 +53,7 @@ END $ZLIB/libz.a: $NGX_MAKEFILE cd $ZLIB \\ - && \$(MAKE) clean \\ + && \$(MAKE) distclean \\ && cp contrib/asm586/match.S . \\ && CFLAGS="$ZLIB_OPT -DASMV" CC="\$(CC)" \\ ./configure \\ @@ -70,7 +70,7 @@ END $ZLIB/libz.a: $NGX_MAKEFILE cd $ZLIB \\ - && \$(MAKE) clean \\ + && \$(MAKE) distclean \\ && cp contrib/asm686/match.S . \\ && CFLAGS="$ZLIB_OPT -DASMV" CC="\$(CC)" \\ ./configure \\ @@ -103,7 +103,7 @@ if [ $done = NO ]; then $ZLIB/libz.a: $NGX_MAKEFILE cd $ZLIB \\ - && \$(MAKE) clean \\ + && \$(MAKE) distclean \\ && CFLAGS="$ZLIB_OPT" CC="\$(CC)" \\ ./configure \\ && \$(MAKE) libz.a diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -102,10 +102,10 @@ fi # ngx_http_range_header_filter # ngx_http_gzip_filter # ngx_http_postpone_filter +# ngx_http_ssi_filter # ngx_http_charset_filter -# ngx_http_ssi_filter # ngx_http_xslt_filter -# ngx_http_image_filter_filter +# ngx_http_image_filter # ngx_http_sub_filter # ngx_http_addition_filter # ngx_http_userid_filter @@ -131,12 +131,6 @@ if [ $HTTP_POSTPONE = YES ]; then HTTP_SRCS="$HTTP_SRCS $HTTP_POSTPONE_FILTER_SRCS" fi -if [ $HTTP_CHARSET = YES ]; then - have=NGX_HTTP_CHARSET . auto/have - HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_CHARSET_FILTER_MODULE" - HTTP_SRCS="$HTTP_SRCS $HTTP_CHARSET_SRCS" -fi - if [ $HTTP_SSI = YES ]; then have=NGX_HTTP_SSI . auto/have HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SSI_FILTER_MODULE" @@ -144,6 +138,12 @@ if [ $HTTP_SSI = YES ]; then HTTP_SRCS="$HTTP_SRCS $HTTP_SSI_SRCS" fi +if [ $HTTP_CHARSET = YES ]; then + have=NGX_HTTP_CHARSET . auto/have + HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_CHARSET_FILTER_MODULE" + HTTP_SRCS="$HTTP_SRCS $HTTP_CHARSET_SRCS" +fi + if [ $HTTP_XSLT = YES ]; then USE_LIBXSLT=YES HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_XSLT_FILTER_MODULE" diff --git a/auto/unix b/auto/unix --- a/auto/unix +++ b/auto/unix @@ -133,6 +133,16 @@ ngx_feature_test="char buf[1024]; long n . auto/feature +ngx_feature="sys_errlist[]" +ngx_feature_name="NGX_HAVE_SYS_ERRLIST" +ngx_feature_run=yes +ngx_feature_incs="#include " +ngx_feature_path= +ngx_feature_libs= +ngx_feature_test="int n = sys_nerr; const char *p = sys_errlist[1];" +. auto/feature + + ngx_feature="localtime_r()" ngx_feature_name="NGX_HAVE_LOCALTIME_R" ngx_feature_run=no diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -919,7 +919,7 @@ ngx_core_module_create_conf(ngx_cycle_t } /* - * set by pcalloc() + * set by ngx_pcalloc() * * ccf->pid = NULL; * ccf->oldpid = NULL; 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 8034 -#define NGINX_VERSION "0.8.34" +#define nginx_version 8035 +#define NGINX_VERSION "0.8.35" #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 @@ -63,7 +63,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) tp = ngx_timeofday(); tp->sec = 0; - ngx_time_update(0, 0); + ngx_time_update(); log = old_cycle->log; 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 @@ -762,10 +762,12 @@ ngx_copy_file(u_char *from, u_char *to, size -= n; } - if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) { - ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, - ngx_set_file_time_n " \"%s\" failed", to); - goto failed; + if (cf->time != -1) { + if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) { + ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno, + ngx_set_file_time_n " \"%s\" failed", to); + goto failed; + } } rc = NGX_OK; diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -1278,13 +1278,13 @@ ngx_escape_uri(u_char *dst, u_char *src, 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; - /* " ", "#", "%", "+", "?", %00-%1F, %7F-%FF */ + /* " ", "#", "%", "&", "+", "?", %00-%1F, %7F-%FF */ static uint32_t args[] = { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ - 0x80000829, /* 1000 0000 0000 0000 0000 1000 0010 1001 */ + 0x80000869, /* 1000 0000 0000 0000 0000 1000 0110 1001 */ /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -28,6 +28,17 @@ volatile ngx_str_t ngx_cached_err_ volatile ngx_str_t ngx_cached_http_time; volatile ngx_str_t ngx_cached_http_log_time; +#if !(NGX_WIN32) + +/* + * locatime() and localtime_r() are not Async-Signal-Safe functions, therefore, + * they must not be called by a signal handler, so we use the cached + * GMT offset value. Fortunately the value is changed only two times a year. + */ + +static ngx_int_t cached_gmtoff; +#endif + static ngx_time_t cached_time[NGX_TIME_SLOTS]; static u_char cached_err_log_time[NGX_TIME_SLOTS] [sizeof("1970/09/28 12:00:00")]; @@ -50,15 +61,17 @@ ngx_time_init(void) ngx_cached_time = &cached_time[0]; - ngx_time_update(0, 0); + ngx_time_update(); } void -ngx_time_update(time_t sec, ngx_uint_t msec) +ngx_time_update(void) { u_char *p0, *p1, *p2; ngx_tm_t tm, gmt; + time_t sec; + ngx_uint_t msec; ngx_time_t *tp; struct timeval tv; @@ -66,12 +79,10 @@ ngx_time_update(time_t sec, ngx_uint_t m return; } - if (sec == 0) { - ngx_gettimeofday(&tv); + ngx_gettimeofday(&tv); - sec = tv.tv_sec; - msec = tv.tv_usec / 1000; - } + sec = tv.tv_sec; + msec = tv.tv_usec / 1000; ngx_current_msec = (ngx_msec_t) sec * 1000 + msec; @@ -112,12 +123,14 @@ ngx_time_update(time_t sec, ngx_uint_t m #elif (NGX_HAVE_GMTOFF) ngx_localtime(sec, &tm); - tp->gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60); + cached_gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60); + tp->gmtoff = cached_gmtoff; #else ngx_localtime(sec, &tm); - tp->gmtoff = ngx_timezone(tm.ngx_tm_isdst); + cached_gmtoff = ngx_timezone(tm.ngx_tm_isdst); + tp->gmtoff = cached_gmtoff; #endif @@ -151,6 +164,59 @@ ngx_time_update(time_t sec, ngx_uint_t m } +#if !(NGX_WIN32) + +void +ngx_time_sigsafe_update(void) +{ + u_char *p; + ngx_tm_t tm; + time_t sec; + ngx_uint_t msec; + ngx_time_t *tp; + struct timeval tv; + + if (!ngx_trylock(&ngx_time_lock)) { + return; + } + + ngx_gettimeofday(&tv); + + sec = tv.tv_sec; + msec = tv.tv_usec / 1000; + + tp = &cached_time[slot]; + + if (tp->sec == sec) { + ngx_unlock(&ngx_time_lock); + return; + } + + if (slot == NGX_TIME_SLOTS - 1) { + slot = 0; + } else { + slot++; + } + + ngx_gmtime(sec + cached_gmtoff * 60, &tm); + + p = &cached_err_log_time[slot][0]; + + (void) ngx_sprintf(p, "%4d/%02d/%02d %02d:%02d:%02d", + tm.ngx_tm_year, tm.ngx_tm_mon, + tm.ngx_tm_mday, tm.ngx_tm_hour, + tm.ngx_tm_min, tm.ngx_tm_sec); + + ngx_memory_barrier(); + + ngx_cached_err_log_time.data = p; + + ngx_unlock(&ngx_time_lock); +} + +#endif + + u_char * ngx_http_time(u_char *buf, time_t t) { diff --git a/src/core/ngx_times.h b/src/core/ngx_times.h --- a/src/core/ngx_times.h +++ b/src/core/ngx_times.h @@ -20,7 +20,8 @@ typedef struct { void ngx_time_init(void); -void ngx_time_update(time_t sec, ngx_uint_t msec); +void ngx_time_update(void); +void ngx_time_sigsafe_update(void); u_char *ngx_http_time(u_char *buf, time_t t); u_char *ngx_http_cookie_time(u_char *buf, time_t t); void ngx_gmtime(time_t t, ngx_tm_t *tp); diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c --- a/src/event/modules/ngx_devpoll_module.c +++ b/src/event/modules/ngx_devpoll_module.c @@ -371,8 +371,8 @@ ngx_devpoll_process_events(ngx_cycle_t * err = (events == -1) ? ngx_errno : 0; - if (flags & NGX_UPDATE_TIME) { - ngx_time_update(0, 0); + if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) { + ngx_time_update(); } if (err) { diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -531,8 +531,8 @@ ngx_epoll_process_events(ngx_cycle_t *cy err = (events == -1) ? ngx_errno : 0; - if (flags & NGX_UPDATE_TIME) { - ngx_time_update(0, 0); + if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) { + ngx_time_update(); } if (err) { diff --git a/src/event/modules/ngx_eventport_module.c b/src/event/modules/ngx_eventport_module.c --- a/src/event/modules/ngx_eventport_module.c +++ b/src/event/modules/ngx_eventport_module.c @@ -405,7 +405,7 @@ ngx_eventport_process_events(ngx_cycle_t err = ngx_errno; if (flags & NGX_UPDATE_TIME) { - ngx_time_update(0, 0); + ngx_time_update(); } if (n == -1) { @@ -439,7 +439,7 @@ ngx_eventport_process_events(ngx_cycle_t for (i = 0; i < events; i++) { if (event_list[i].portev_source == PORT_SOURCE_TIMER) { - ngx_time_update(0, 0); + ngx_time_update(); continue; } diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -537,8 +537,8 @@ ngx_kqueue_process_events(ngx_cycle_t *c err = (events == -1) ? ngx_errno : 0; - if (flags & NGX_UPDATE_TIME) { - ngx_time_update(0, 0); + if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) { + ngx_time_update(); } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, @@ -589,7 +589,7 @@ ngx_kqueue_process_events(ngx_cycle_t *c #if (NGX_HAVE_TIMER_EVENT) if (event_list[i].filter == EVFILT_TIMER) { - ngx_time_update(0, 0); + ngx_time_update(); continue; } diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c --- a/src/event/modules/ngx_poll_module.c +++ b/src/event/modules/ngx_poll_module.c @@ -262,8 +262,8 @@ ngx_poll_process_events(ngx_cycle_t *cyc err = (ready == -1) ? ngx_errno : 0; - if (flags & NGX_UPDATE_TIME) { - ngx_time_update(0, 0); + if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) { + ngx_time_update(); } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, diff --git a/src/event/modules/ngx_rtsig_module.c b/src/event/modules/ngx_rtsig_module.c --- a/src/event/modules/ngx_rtsig_module.c +++ b/src/event/modules/ngx_rtsig_module.c @@ -323,7 +323,7 @@ ngx_rtsig_process_events(ngx_cycle_t *cy "rtsig signo:%d", signo); if (flags & NGX_UPDATE_TIME) { - ngx_time_update(0, 0); + ngx_time_update(); } if (err == NGX_EAGAIN) { @@ -349,7 +349,7 @@ ngx_rtsig_process_events(ngx_cycle_t *cy signo, si.si_fd, si.si_band); if (flags & NGX_UPDATE_TIME) { - ngx_time_update(0, 0); + ngx_time_update(); } rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module); @@ -419,7 +419,7 @@ ngx_rtsig_process_events(ngx_cycle_t *cy } else if (signo == SIGALRM) { - ngx_time_update(0, 0); + ngx_time_update(); return NGX_OK; @@ -671,7 +671,7 @@ ngx_rtsig_process_overflow(ngx_cycle_t * } if (flags & NGX_UPDATE_TIME) { - ngx_time_update(0, 0); + ngx_time_update(); } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c --- a/src/event/modules/ngx_select_module.c +++ b/src/event/modules/ngx_select_module.c @@ -262,8 +262,8 @@ ngx_select_process_events(ngx_cycle_t *c err = (ready == -1) ? ngx_errno : 0; - if (flags & NGX_UPDATE_TIME) { - ngx_time_update(0, 0); + if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) { + ngx_time_update(); } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, diff --git a/src/event/modules/ngx_win32_select_module.c b/src/event/modules/ngx_win32_select_module.c --- a/src/event/modules/ngx_win32_select_module.c +++ b/src/event/modules/ngx_win32_select_module.c @@ -269,7 +269,7 @@ ngx_select_process_events(ngx_cycle_t *c err = (ready == -1) ? ngx_socket_errno : 0; if (flags & NGX_UPDATE_TIME) { - ngx_time_update(0, 0); + ngx_time_update(); } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -562,8 +562,6 @@ ngx_timer_signal_handler(int signo) { ngx_event_timer_alarm = 1; - ngx_time_update(0, 0); - #if 1 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, "timer signal"); #endif diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -561,6 +561,9 @@ ngx_ssl_handshake(ngx_connection_t *c) #if (NGX_DEBUG) { char buf[129], *s, *d; +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + const +#endif SSL_CIPHER *cipher; cipher = SSL_get_current_cipher(c->ssl->connection); diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c --- a/src/http/modules/ngx_http_chunked_filter_module.c +++ b/src/http/modules/ngx_http_chunked_filter_module.c @@ -50,6 +50,8 @@ static ngx_http_output_body_filter_pt static ngx_int_t ngx_http_chunked_header_filter(ngx_http_request_t *r) { + ngx_http_core_loc_conf_t *clcf; + if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED || r->headers_out.status == NGX_HTTP_NO_CONTENT || r != r->main @@ -63,7 +65,14 @@ ngx_http_chunked_header_filter(ngx_http_ r->keepalive = 0; } else { - r->chunked = 1; + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (clcf->chunked_transfer_encoding) { + r->chunked = 1; + + } else { + r->keepalive = 0; + } } } 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 @@ -1254,7 +1254,7 @@ ngx_http_fastcgi_process_header(ngx_http #if (NGX_HTTP_CACHE) - if (f->large_stderr) { + if (f->large_stderr && r->cache) { u_char *start; ssize_t len; 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 @@ -432,15 +432,20 @@ ngx_http_memcached_filter(void *data, ss if (ngx_strncmp(b->last, ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest, - ctx->rest) + bytes) != 0) { ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0, "memcached sent invalid trailer"); + + u->length = 0; + ctx->rest = 0; + + return NGX_OK; } - u->length = 0; - ctx->rest = 0; + u->length -= bytes; + ctx->rest -= bytes; return NGX_OK; } 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 @@ -637,6 +637,7 @@ ngx_http_proxy_handler(ngx_http_request_ u->process_header = ngx_http_proxy_process_status_line; u->abort_request = ngx_http_proxy_abort_request; u->finalize_request = ngx_http_proxy_finalize_request; + r->state = 0; if (plcf->redirects) { u->rewrite_redirect = ngx_http_proxy_rewrite_redirect; @@ -1198,6 +1199,7 @@ ngx_http_proxy_reinit_request(ngx_http_r ctx->status_end = NULL; r->upstream->process_header = ngx_http_proxy_process_status_line; + r->state = 0; return NGX_OK; } @@ -1913,7 +1915,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ * conf->body_set_len = NULL; * conf->body_set = NULL; * conf->body_source = { 0, NULL }; - * conf->rewrite_locations = NULL; + * conf->redirects = NULL; */ conf->upstream.store = NGX_CONF_UNSET; @@ -2754,9 +2756,16 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, } if (ngx_strcmp(value[1].data, "default") == 0) { + if (plcf->proxy_lengths) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"proxy_redirect default\" may not be used " + "with \"proxy_pass\" directive with variables"); + return NGX_CONF_ERROR; + } + if (plcf->url.data == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"proxy_rewrite_location default\" must go " + "\"proxy_redirect default\" must go " "after the \"proxy_pass\" directive"); return NGX_CONF_ERROR; } 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.8.34'; +our $VERSION = '0.8.35'; 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 @@ -599,6 +599,13 @@ static ngx_command_t ngx_http_core_comm offsetof(ngx_http_core_loc_conf_t, if_modified_since), &ngx_http_core_if_modified_since }, + { ngx_string("chunked_transfer_encoding"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, chunked_transfer_encoding), + NULL }, + { ngx_string("error_page"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_2MORE, @@ -2972,6 +2979,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t clcf->log_subrequest = NGX_CONF_UNSET; clcf->recursive_error_pages = NGX_CONF_UNSET; clcf->server_tokens = NGX_CONF_UNSET; + clcf->chunked_transfer_encoding = NGX_CONF_UNSET; clcf->types_hash_max_size = NGX_CONF_UNSET_UINT; clcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT; @@ -3215,6 +3223,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_conf_merge_value(conf->recursive_error_pages, prev->recursive_error_pages, 0); ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1); + ngx_conf_merge_value(conf->chunked_transfer_encoding, + prev->chunked_transfer_encoding, 1); ngx_conf_merge_ptr_value(conf->open_file_cache, prev->open_file_cache, NULL); 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 @@ -363,6 +363,7 @@ struct ngx_http_core_loc_conf_s { ngx_flag_t log_subrequest; /* log_subrequest */ ngx_flag_t recursive_error_pages; /* recursive_error_pages */ ngx_flag_t server_tokens; /* server_tokens */ + ngx_flag_t chunked_transfer_encoding; /* chunked_transfer_encoding */ #if (NGX_HTTP_GZIP) ngx_flag_t gzip_vary; /* gzip_vary */ 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 @@ -1216,7 +1216,7 @@ ngx_http_file_cache_manager_sleep(ngx_ht if (cache->files++ > 100) { - ngx_time_update(0, 0); + ngx_time_update(); elapsed = ngx_abs((ngx_msec_int_t) (ngx_current_msec - cache->last)); @@ -1233,7 +1233,7 @@ ngx_http_file_cache_manager_sleep(ngx_ht ngx_msleep(200); - ngx_time_update(0, 0); + ngx_time_update(); } cache->last = ngx_current_msec; diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -338,6 +338,11 @@ ngx_http_header_filter(ngx_http_request_ port = ntohs(sin6->sin6_port); break; #endif +#if (NGX_HAVE_UNIX_DOMAIN) + case AF_UNIX: + port = 0; + break; +#endif default: /* AF_INET */ sin = (struct sockaddr_in *) c->local_sockaddr; port = ntohs(sin->sin_port); diff --git a/src/misc/ngx_google_perftools_module.c b/src/misc/ngx_google_perftools_module.c --- a/src/misc/ngx_google_perftools_module.c +++ b/src/misc/ngx_google_perftools_module.c @@ -8,7 +8,7 @@ #include /* - * declare Profiler here interface because + * declare Profiler interface here because * is C++ header file */ @@ -73,7 +73,7 @@ ngx_google_perftools_create_conf(ngx_cyc } /* - * set by pcalloc() + * set by ngx_pcalloc() * * gptcf->profiles = { 0, NULL }; */ @@ -101,7 +101,6 @@ ngx_google_perftools_worker(ngx_cycle_t } if (getenv("CPUPROFILE")) { - /* disable inherited Profiler enabled in master process */ ProfilerStop(); } @@ -109,7 +108,6 @@ ngx_google_perftools_worker(ngx_cycle_t ngx_sprintf(profile, "%V.%d%Z", &gptcf->profiles, ngx_pid); if (ProfilerStart(profile)) { - /* start ITIMER_PROF timer */ ProfilerRegisterThread(); diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h --- a/src/os/unix/ngx_errno.h +++ b/src/os/unix/ngx_errno.h @@ -64,10 +64,22 @@ u_char *ngx_strerror_r(int err, u_char * /* Solaris and Tru64 UNIX have thread-safe strerror() */ -#define ngx_strerror_r(err, errstr, size) \ +#define ngx_strerror_r(err, errstr, size) \ ngx_cpystrn(errstr, (u_char *) strerror(err), size) #endif +#if (NGX_HAVE_SYS_ERRLIST) + +#define ngx_sigsafe_strerror(err) \ + (err > 0 && err < sys_nerr) ? sys_errlist[err] : "Unknown error" + +#else + +#define ngx_sigsafe_strerror(err) "" + +#endif + + #endif /* _NGX_ERRNO_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c --- a/src/os/unix/ngx_process.c +++ b/src/os/unix/ngx_process.c @@ -317,7 +317,7 @@ ngx_signal_handler(int signo) } } - ngx_time_update(0, 0); + ngx_time_sigsafe_update(); action = ""; @@ -479,16 +479,17 @@ ngx_process_get_status(void) */ if (err == NGX_ECHILD) { - ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, errno, - "waitpid() failed"); + ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0, + "waitpid() failed (%d: %s)", + err, ngx_sigsafe_strerror(err)); return; } #endif - ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, errno, - "waitpid() failed"); - + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "waitpid() failed (%d: %s)", + err, ngx_sigsafe_strerror(err)); return; } diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -168,7 +168,7 @@ ngx_master_process_cycle(ngx_cycle_t *cy sigsuspend(&set); - ngx_time_update(0, 0); + ngx_time_update(); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up, sigio %i", sigio); @@ -1342,7 +1342,7 @@ ngx_cache_manager_process_handler(ngx_ev next = (n <= next) ? n : next; - ngx_time_update(0, 0); + ngx_time_update(); } } @@ -1372,7 +1372,7 @@ ngx_cache_loader_process_handler(ngx_eve if (path[i]->loader) { path[i]->loader(path[i]->data); - ngx_time_update(0, 0); + ngx_time_update(); } } diff --git a/src/os/unix/ngx_sunpro_amd64.il b/src/os/unix/ngx_sunpro_amd64.il --- a/src/os/unix/ngx_sunpro_amd64.il +++ b/src/os/unix/ngx_sunpro_amd64.il @@ -31,7 +31,12 @@ / ngx_cpu_pause() +/ +/ the "rep; nop" is used instead of "pause" to avoid the "[ PAUSE ]" hardware +/ capability added by linker because Solaris/amd64 does not know about it: +/ +/ ld.so.1: nginx: fatal: hardware capability unsupported: 0x2000 [ PAUSE ] .inline ngx_cpu_pause,0 - pause + rep; nop .end