changeset 418:ff86d646f9df NGINX_0_7_21

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.
author Igor Sysoev <http://sysoev.ru>
date Tue, 11 Nov 2008 00:00:00 +0300
parents 735cec38a814
children b986babf3f57
files CHANGES CHANGES.ru auto/lib/libxslt/conf src/core/nginx.c src/core/nginx.h src/core/ngx_conf_file.c src/core/ngx_cycle.c src/core/ngx_inet.c src/core/ngx_log.c src/http/modules/ngx_http_limit_req_module.c src/http/modules/ngx_http_xslt_filter_module.c src/http/modules/perl/nginx.pm src/http/ngx_http_request.h src/os/unix/ngx_darwin_init.c src/os/unix/ngx_files.h
diffstat 15 files changed, 230 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- 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.
--- 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.
--- 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 <libexslt/exslt.h>"
+    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
--- 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) {
--- 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"
--- 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);
+        }
     }
 }
 
--- 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;
         }
 
--- 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) {
--- 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);
 }
 
 
--- 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;
 }
--- 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 <libxslt/transform.h>
 #include <libxslt/xsltutils.h>
 
+#if (NGX_HAVE_EXSLT)
+#include <libexslt/exslt.h>
+#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;
 
--- 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);
--- 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;
--- 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) {
--- 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;