# HG changeset patch # User Igor Sysoev # Date 1226350800 -10800 # Node ID ff86d646f9df4cf9ec14662fe09269d57d9598ea # Parent 735cec38a8143c2b061d63296791facc92d27880 nginx 0.7.21 *) Changes in the ngx_http_limit_req_module. *) Feature: the EXSLT support in the ngx_http_xslt_module. Thanks to Denis F. Latypoff. *) Workaround: compatibility with glibc 2.3. Thanks to Eric Benson and Maxim Dounin. *) Bugfix: nginx could not run on MacOSX 10.4 and earlier; the bug had appeared in 0.7.6. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,18 @@ +Changes with nginx 0.7.21 11 Nov 2008 + + *) Changes in the ngx_http_limit_req_module. + + *) Feature: the EXSLT support in the ngx_http_xslt_module. + Thanks to Denis F. Latypoff. + + *) Workaround: compatibility with glibc 2.3. + Thanks to Eric Benson and Maxim Dounin. + + *) Bugfix: nginx could not run on MacOSX 10.4 and earlier; the bug had + appeared in 0.7.6. + + Changes with nginx 0.7.20 10 Nov 2008 *) Changes in the ngx_http_gzip_filter_module. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,9 +1,23 @@ +Изменения в nginx 0.7.21 11.11.2008 + + *) Изменения в модуле ngx_http_limit_req_module. + + *) Добавление: поддержка EXSLT в модуле ngx_http_xslt_module. + Спасибо Денису Латыпову. + + *) Изменение: совместимость с glibc 2.3. + Спасибо Eric Benson и Максиму Дунину. + + *) Исправление: nginx не запускался на MacOSX 10.4 и более ранних; + ошибка появилась в 0.7.6. + + Изменения в nginx 0.7.20 10.11.2008 *) Изменения в модуле ngx_http_gzip_filter_module. - *) Добавление: модуль ngx_http_limit_req_module + *) Добавление: модуль ngx_http_limit_req_module. *) Исправление: на платформах sparc и ppc рабочие процессы могли выходить по сигналу SIGBUS; ошибка появилась в 0.7.3. diff --git a/auto/lib/libxslt/conf b/auto/lib/libxslt/conf --- a/auto/lib/libxslt/conf +++ b/auto/lib/libxslt/conf @@ -88,3 +88,68 @@ END exit 1 fi + + + ngx_feature="libexslt" + ngx_feature_name=NGX_HAVE_EXSLT + ngx_feature_run=no + ngx_feature_incs="#include " + ngx_feature_path="/usr/include/libxml2" + ngx_feature_libs="-lexslt" + ngx_feature_test="exsltRegisterAll();" + . auto/feature + +if [ $ngx_found = no ]; then + + # FreeBSD port + + ngx_feature="libexslt in /usr/local/" + ngx_feature_path="/usr/local/include/libxml2 /usr/local/include" + + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R/usr/local/lib -L/usr/local/lib -lexslt" + else + ngx_feature_libs="-L/usr/local/lib -lexslt" + fi + + . auto/feature +fi + + +if [ $ngx_found = no ]; then + + # NetBSD port + + ngx_feature="libexslt in /usr/pkg/" + ngx_feature_path="/usr/pkg/include/libxml2 /usr/local/include" + + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lexslt" + else + ngx_feature_libs="-L/usr/pkg/lib -lexslt" + fi + + . auto/feature +fi + + +if [ $ngx_found = no ]; then + + # MacPorts + + ngx_feature="libexslt in /opt/local/" + ngx_feature_path="/opt/local/include/libxml2 /opt/local/include" + + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lexslt" + else + ngx_feature_libs="-L/opt/local/lib -lexslt" + fi + + . auto/feature +fi + + +if [ $ngx_found = yes ]; then + CORE_LIBS="$CORE_LIBS -lexslt" +fi diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -191,6 +191,8 @@ static char **ngx_os_environ; int ngx_cdecl main(int argc, char *const *argv) { + char *p; + ssize_t n; ngx_int_t i; ngx_log_t *log; ngx_cycle_t *cycle, init_cycle; @@ -240,23 +242,30 @@ main(int argc, char *const *argv) } if (ngx_show_version) { - ngx_write_fd(ngx_stderr_fileno, "nginx version: " NGINX_VER CRLF, - sizeof("nginx version: " NGINX_VER CRLF) - 1); + + p = "nginx version: " NGINX_VER CRLF; + n = sizeof("nginx version: " NGINX_VER CRLF) - 1; + + if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) { + return 1; + } if (ngx_show_configure) { #ifdef NGX_COMPILER - ngx_write_fd(ngx_stderr_fileno, "built by " NGX_COMPILER CRLF, - sizeof("built by " NGX_COMPILER CRLF) - 1); + p = "built by " NGX_COMPILER CRLF; + n = sizeof("built by " NGX_COMPILER CRLF) - 1; + + if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) { + return 1; + } #endif -#ifndef __WATCOMC__ - - /* OpenWatcomC could not build the long NGX_CONFIGURE string */ + p = "configure arguments: " NGX_CONFIGURE CRLF; + n = sizeof("configure arguments :" NGX_CONFIGURE CRLF) - 1; - ngx_write_fd(ngx_stderr_fileno, - "configure arguments: " NGX_CONFIGURE CRLF, - sizeof("configure arguments :" NGX_CONFIGURE CRLF) - 1); -#endif + if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) { + return 1; + } } if (!ngx_test_config) { 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.20" +#define NGINX_VERSION "0.7.21" #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 @@ -912,6 +912,7 @@ ngx_conf_open_file(ngx_cycle_t *cycle, n static void ngx_conf_flush_files(ngx_cycle_t *cycle) { + ssize_t n, len; ngx_uint_t i; ngx_list_part_t *part; ngx_open_file_t *file; @@ -932,11 +933,24 @@ ngx_conf_flush_files(ngx_cycle_t *cycle) i = 0; } - if (file[i].buffer == NULL || file[i].pos - file[i].buffer == 0) { + len = file[i].pos - file[i].buffer; + + if (file[i].buffer == NULL || len == 0) { continue; } - ngx_write_fd(file[i].fd, file[i].buffer, file[i].pos - file[i].buffer); + n = ngx_write_fd(file[i].fd, file[i].buffer, len); + + if (n == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + ngx_write_fd_n " to \"%s\" failed", + file[i].name.data); + + } else if (n != len) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", + file[i].name.data, n, len); + } } } 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 @@ -996,6 +996,7 @@ ngx_test_lockfile(u_char *file, ngx_log_ void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { + ssize_t n, len; ngx_fd_t fd; ngx_uint_t i; ngx_list_part_t *part; @@ -1019,9 +1020,23 @@ ngx_reopen_files(ngx_cycle_t *cycle, ngx continue; } - if (file[i].buffer && file[i].pos - file[i].buffer != 0) { - ngx_write_fd(file[i].fd, file[i].buffer, - file[i].pos - file[i].buffer); + len = file[i].pos - file[i].buffer; + + if (file[i].buffer && len != 0) { + + n = ngx_write_fd(file[i].fd, file[i].buffer, len); + + if (n == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + ngx_write_fd_n " to \"%s\" failed", + file[i].name.data); + + } else if (n != len) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", + file[i].name.data, n, len); + } + file[i].pos = file[i].buffer; } diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -290,7 +290,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx if (uri < port) { port = NULL; - } + } } if (port) { diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c --- a/src/core/ngx_log.c +++ b/src/core/ngx_log.c @@ -158,7 +158,7 @@ ngx_log_error_core(ngx_uint_t level, ngx ngx_linefeed(p); - ngx_write_fd(log->file->fd, errstr, p - errstr); + (void) ngx_write_fd(log->file->fd, errstr, p - errstr); } diff --git a/src/http/modules/ngx_http_limit_req_module.c b/src/http/modules/ngx_http_limit_req_module.c --- a/src/http/modules/ngx_http_limit_req_module.c +++ b/src/http/modules/ngx_http_limit_req_module.c @@ -33,7 +33,7 @@ typedef struct { typedef struct { ngx_shm_zone_t *shm_zone; float burst; - ngx_msec_t delay; + ngx_uint_t nodelay; /* unsigned nodelay:1 */ } ngx_http_limit_req_conf_t; @@ -178,7 +178,7 @@ ngx_http_limit_req_handler(ngx_http_requ ngx_shmtx_unlock(&ctx->shpool->mutex); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "limiting requests, %.3f r/s", rate); + "limiting requests, excess: %.3f", rate); return NGX_HTTP_SERVICE_UNAVAILABLE; } @@ -186,22 +186,22 @@ ngx_http_limit_req_handler(ngx_http_requ if (rc == NGX_AGAIN) { ngx_shmtx_unlock(&ctx->shpool->mutex); - if (lzcf->delay) { - ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, - "delaying requests, %.3f r/s", rate); - - if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { - return NGX_HTTP_INTERNAL_SERVER_ERROR; - } - - r->read_event_handler = ngx_http_test_reading; - r->write_event_handler = ngx_http_limit_req_delay; - ngx_add_timer(r->connection->write, lzcf->delay); - - return NGX_AGAIN; + if (lzcf->nodelay) { + return NGX_DECLINED; } - return NGX_DECLINED; + ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, + "delaying request, excess: %.3f", rate); + + if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + r->read_event_handler = ngx_http_test_reading; + r->write_event_handler = ngx_http_limit_req_delay; + ngx_add_timer(r->connection->write, (ngx_msec_t) (rate * 1000)); + + return NGX_AGAIN; } if (rc == NGX_OK) { @@ -365,7 +365,7 @@ ngx_http_limit_req_lookup(ngx_http_limit return NGX_BUSY; } - if (lz->rate > ctx->rate) { + if (lz->rate > 0.0) { return NGX_AGAIN; } @@ -511,7 +511,7 @@ ngx_http_limit_req_create_conf(ngx_conf_ * * conf->shm_zone = NULL; * conf->burst = 0.0; - * conf->delay = 0; + * conf->nodelay = 0; */ return conf; @@ -670,12 +670,9 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c { ngx_http_limit_req_conf_t *lzcf = conf; - u_char *p; - size_t len; - ngx_int_t burst, scale, delay; - ngx_str_t *value, s; - ngx_uint_t i; - ngx_http_limit_req_ctx_t *ctx; + ngx_int_t burst; + ngx_str_t *value, s; + ngx_uint_t i; if (lzcf->shm_zone) { return "is duplicate"; @@ -684,8 +681,6 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c value = cf->args->elts; burst = 0; - scale = 1; - delay = 0; for (i = 1; i < cf->args->nelts; i++) { @@ -705,19 +700,7 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c if (ngx_strncmp(value[i].data, "burst=", 6) == 0) { - len = value[i].len; - p = value[i].data + len - 3; - - if (ngx_strncmp(p, "r/s", 3) == 0) { - scale = 1; - len -= 3; - - } else if (ngx_strncmp(p, "r/m", 3) == 0) { - scale = 60; - len -= 3; - } - - burst = ngx_atoi(value[i].data + 6, len - 6); + burst = ngx_atoi(value[i].data + 6, value[i].len - 6); if (burst <= 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid burst rate \"%V\"", &value[i]); @@ -727,18 +710,8 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c continue; } - if (ngx_strncmp(value[i].data, "delay=", 6) == 0) { - - s.len = value[i].len - 6; - s.data = value[i].data + 6; - - delay = ngx_parse_time(&s, 0); - if (delay < 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid clean_time value \"%V\"", &value[i]); - return NGX_CONF_ERROR; - } - + if (ngx_strncmp(value[i].data, "nodelay", 7) == 0) { + lzcf->nodelay = 1; continue; } @@ -761,15 +734,7 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c return NGX_CONF_ERROR; } - if (burst) { - lzcf->burst = (float) burst / scale; - - } else { - ctx = lzcf->shm_zone->data; - lzcf->burst = ctx->rate; - } - - lzcf->delay = (ngx_msec_t) delay; + lzcf->burst = (float) burst; return NGX_CONF_OK; } 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 @@ -15,6 +15,10 @@ #include #include +#if (NGX_HAVE_EXSLT) +#include +#endif + #ifndef NGX_HTTP_XSLT_REUSE_DTD #define NGX_HTTP_XSLT_REUSE_DTD 1 @@ -1269,6 +1273,10 @@ ngx_http_xslt_filter_init(ngx_conf_t *cf { xmlInitParser(); +#if (NGX_HAVE_EXSLT) + exsltRegisterAll(); +#endif + ngx_http_next_header_filter = ngx_http_top_header_filter; ngx_http_top_header_filter = ngx_http_xslt_header_filter; 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.20'; +our $VERSION = '0.7.21'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -439,7 +439,7 @@ struct ngx_http_request_s { /* * instead of using the request context data in - * ngx_http_limit_zone_module and ngx_http_limit_req_module + * ngx_http_limit_zone_module and ngx_http_limit_req_module * we use the single bits in the request structure */ unsigned limit_zone_set:1; diff --git a/src/os/unix/ngx_darwin_init.c b/src/os/unix/ngx_darwin_init.c --- a/src/os/unix/ngx_darwin_init.c +++ b/src/os/unix/ngx_darwin_init.c @@ -64,32 +64,44 @@ ngx_os_specific_init(ngx_log_t *log) ngx_uint_t i; size = sizeof(ngx_darwin_kern_ostype); - if (sysctlbyname("kern.ostype", - ngx_darwin_kern_ostype, &size, NULL, 0) == -1) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - "sysctlbyname(kern.ostype) failed"); + if (sysctlbyname("kern.ostype", ngx_darwin_kern_ostype, &size, NULL, 0) + == -1) + { + err = ngx_errno; + + if (err != NGX_ENOENT) { - if (ngx_errno != NGX_ENOMEM) { - return NGX_ERROR; + ngx_log_error(NGX_LOG_ALERT, log, err, + "sysctlbyname(kern.ostype) failed"); + + if (err != NGX_ENOMEM) { + return NGX_ERROR; + } + + ngx_darwin_kern_ostype[size - 1] = '\0'; } - - ngx_darwin_kern_ostype[size - 1] = '\0'; } size = sizeof(ngx_darwin_kern_osrelease); - if (sysctlbyname("kern.osrelease", - ngx_darwin_kern_osrelease, &size, NULL, 0) == -1) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - "sysctlbyname(kern.osrelease) failed"); + if (sysctlbyname("kern.osrelease", ngx_darwin_kern_osrelease, &size, + NULL, 0) + == -1) + { + err = ngx_errno; + + if (err != NGX_ENOENT) { - if (ngx_errno != NGX_ENOMEM) { - return NGX_ERROR; - } + ngx_log_error(NGX_LOG_ALERT, log, err, + "sysctlbyname(kern.osrelease) failed"); - ngx_darwin_kern_osrelease[size - 1] = '\0'; + if (err != NGX_ENOMEM) { + return NGX_ERROR; + } + + ngx_darwin_kern_osrelease[size - 1] = '\0'; + } } - for (i = 0; sysctls[i].name; i++) { size = sysctls[i].size; @@ -136,8 +148,10 @@ ngx_os_specific_status(ngx_log_t *log) u_long value; ngx_uint_t i; - ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s", - ngx_darwin_kern_ostype, ngx_darwin_kern_osrelease); + if (ngx_darwin_kern_ostype[0]) { + ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s", + ngx_darwin_kern_ostype, ngx_darwin_kern_osrelease); + } for (i = 0; sysctls[i].name; i++) { if (sysctls[i].exists) { diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -99,7 +99,17 @@ ssize_t ngx_write_chain_to_file(ngx_file #define ngx_read_fd read #define ngx_read_fd_n "read()" -#define ngx_write_fd write +/* + * we use inlined function instead of simple #define + * because glibc 2.3 sets warn_unused_result attribute for write() + * and in this case gcc 4.3 ignores (void) cast + */ +static ngx_inline ssize_t +ngx_write_fd(ngx_fd_t fd, void *buf, size_t n) +{ + return write(fd, buf, n); +} + #define ngx_write_fd_n "write()" #define ngx_linefeed(p) *p++ = LF;