changeset 516:7efcdb937752 NGINX_0_8_10

nginx 0.8.10 *) Bugfix: memory leaks if GeoIP City database was used. *) Bugfix: in copying temporary files to permanent storage area; the bug had appeared in 0.8.9.
author Igor Sysoev <http://sysoev.ru>
date Mon, 24 Aug 2009 00:00:00 +0400
parents 607556aed0a1
children 15b5cddc5190
files CHANGES CHANGES.ru auto/os/linux src/core/nginx.h src/core/ngx_buf.h src/core/ngx_file.c src/core/ngx_file.h src/event/ngx_event.c src/http/modules/ngx_http_dav_module.c src/http/modules/ngx_http_geoip_module.c src/http/modules/ngx_http_log_module.c src/http/modules/perl/nginx.pm src/http/ngx_http_upstream.c src/os/unix/ngx_process_cycle.c
diffstat 14 files changed, 120 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,10 +1,18 @@
 
+Changes with nginx 0.8.10                                        24 Aug 2009
+
+    *) Bugfix: memory leaks if GeoIP City database was used.
+
+    *) Bugfix: in copying temporary files to permanent storage area; the 
+       bug had appeared in 0.8.9.
+
+
 Changes with nginx 0.8.9                                         17 Aug 2009
 
     *) Feature: now the start cache loader runs in a separate process; this 
        should improve large caches handling.
 
-    *) Feature: now temporarily files and permanent storage area may reside 
+    *) Feature: now temporary files and permanent storage area may reside 
        at different file systems.
 
 
@@ -98,8 +106,7 @@ Changes with nginx 0.8.3                
 
     *) Feature: the $upstream_cache_status variable.
 
-    *) Bugfix: nginx could not be built on MacOSX 10.6. the bug had 
-       appeared in 0.8.2.
+    *) Bugfix: nginx could not be built on MacOSX 10.6.
 
     *) Bugfix: nginx could not be built --without-http-cache; the bug had 
        appeared in 0.8.2.
@@ -1938,8 +1945,8 @@ Changes with nginx 0.5.12               
        amd64, sparc, and ppc; the bug had appeared in 0.5.8.
 
     *) Bugfix: a segmentation fault might occur in worker process if the 
-       temporarily files were used while working with FastCGI server; the 
-       bug had appeared in 0.5.8.
+       temporary files were used while working with FastCGI server; the bug 
+       had appeared in 0.5.8.
 
     *) Bugfix: a segmentation fault might occur in worker process if the 
        $fastcgi_script_name variable was logged.
@@ -2842,8 +2849,8 @@ Changes with nginx 0.3.31               
        in 0.3.18.
 
     *) Bugfix: if the HTTPS protocol was used in the "proxy_pass" directive 
-       and the request body was in temporarily file then the request was 
-       not transferred.
+       and the request body was in temporary file then the request was not 
+       transferred.
 
     *) Bugfix: perl 5.8.8 compatibility.
 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,12 @@
 
+Изменения в nginx 0.8.10                                          24.08.2009
+
+    *) Исправление: утечек памяти при использовании базы GeoIP City.
+
+    *) Исправление: ошибки при копировании временных файлов в постоянное 
+       место хранения; ошибка появилась в 0.8.9.
+
+
 Изменения в nginx 0.8.9                                           17.08.2009
 
     *) Добавление: теперь стартовый загрузчик кэша работает в отдельном 
--- a/auto/os/linux
+++ b/auto/os/linux
@@ -18,7 +18,7 @@ CC_AUX_FLAGS="$cc_aux_flags -D_GNU_SOURC
 # Linux kernel version
 
 version=$((`uname -r \
-         | sed 's/^\([^.]*\)\.\([^.]*\)\.\([^.-]*\).*/\1*256*256+\2*256+\3/'`))
+       | sed 's/^\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1*256*256+\2*256+\3/'`))
 
 version=${version:-0}
 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         8009
-#define NGINX_VERSION      "0.8.9"
+#define nginx_version         8010
+#define NGINX_VERSION      "0.8.10"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_buf.h
+++ b/src/core/ngx_buf.h
@@ -75,13 +75,13 @@ typedef struct {
     ngx_chain_t                 *free;
     ngx_chain_t                 *busy;
 
-    unsigned                     sendfile;
-    unsigned                     directio;
+    unsigned                     sendfile:1;
+    unsigned                     directio:1;
 #if (NGX_HAVE_ALIGNED_DIRECTIO)
-    unsigned                     unaligned;
+    unsigned                     unaligned:1;
 #endif
-    unsigned                     need_in_memory;
-    unsigned                     need_in_temp;
+    unsigned                     need_in_memory:1;
+    unsigned                     need_in_temp:1;
 
     ngx_pool_t                  *pool;
     ngx_int_t                    allocated;
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -8,8 +8,9 @@
 #include <ngx_core.h>
 
 
-static ngx_atomic_uint_t  ngx_temp_number;
-static ngx_atomic_uint_t  ngx_random_number;
+static ngx_atomic_t   temp_number = 0;
+ngx_atomic_t         *ngx_temp_number = &temp_number;
+ngx_atomic_int_t      ngx_random_number = 123456;
 
 
 ssize_t
@@ -205,22 +206,16 @@ ngx_create_full_path(u_char *dir, ngx_ui
 }
 
 
-void
-ngx_init_temp_number(void)
-{
-    ngx_temp_number = 0;
-    ngx_random_number = 123456;
-}
-
-
 ngx_atomic_uint_t
 ngx_next_temp_number(ngx_uint_t collision)
 {
-    if (collision) {
-        ngx_temp_number += ngx_random_number;
-    }
+    ngx_atomic_uint_t  n, add;
+
+    add = collision ? ngx_random_number : 1;
 
-    return ngx_temp_number++;
+    n = ngx_atomic_fetch_add(ngx_temp_number, add);
+
+    return n + add;
 }
 
 
@@ -576,7 +571,6 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_
         }
 
         err = ngx_errno;
-        goto failed;
     }
 
 #if (NGX_WIN32)
@@ -605,34 +599,43 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_
         cf.time = ext->time;
         cf.log = ext->log;
 
-        name = ngx_alloc(to->len + 1 + 10, ext->log);
+        name = ngx_alloc(to->len + 1 + 10 + 1, ext->log);
         if (name == NULL) {
             return NGX_ERROR;
         }
 
-        (void) ngx_sprintf(name, "%*s.%010uD%Z", to->len - 1, to->data,
+        (void) ngx_sprintf(name, "%*s.%010uD%Z", to->len, to->data,
                            (uint32_t) ngx_next_temp_number(0));
 
         if (ngx_copy_file(src->data, name, &cf) == NGX_OK) {
 
-            if (ngx_rename_file(name, to->data) == NGX_FILE_ERROR) {
+            if (ngx_rename_file(name, to->data) != NGX_FILE_ERROR) {
                 ngx_free(name);
-                goto failed;
+
+                if (ngx_delete_file(src->data) == NGX_FILE_ERROR) {
+                    ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno,
+                                  ngx_delete_file_n " \"%s\" failed",
+                                  src->data);
+                    return NGX_ERROR;
+                }
+
+                return NGX_OK;
             }
 
-            ngx_free(name);
+            ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno,
+                          ngx_rename_file_n " \"%s\" to \"%s\" failed",
+                          name, to->data);
 
-            if (ngx_delete_file(src->data) == NGX_FILE_ERROR) {
+            if (ngx_delete_file(name) == NGX_FILE_ERROR) {
                 ngx_log_error(NGX_LOG_CRIT, ext->log, ngx_errno,
-                              ngx_delete_file_n " \"%s\" failed", src->data);
+                              ngx_delete_file_n " \"%s\" failed", name);
 
-                return NGX_ERROR;
             }
-
-            return NGX_OK;
         }
 
         ngx_free(name);
+
+        err = 0;
     }
 
 failed:
--- a/src/core/ngx_file.h
+++ b/src/core/ngx_file.h
@@ -129,7 +129,6 @@ ngx_int_t ngx_ext_rename_file(ngx_str_t 
 ngx_int_t ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf);
 ngx_int_t ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_str_t *tree);
 
-void ngx_init_temp_number(void);
 ngx_atomic_uint_t ngx_next_temp_number(ngx_uint_t collision);
 
 char *ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
@@ -138,4 +137,8 @@ char *ngx_conf_merge_path_value(ngx_conf
 char *ngx_conf_set_access_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 
 
+extern ngx_atomic_t      *ngx_temp_number;
+extern ngx_atomic_int_t   ngx_random_number;
+
+
 #endif /* _NGX_FILE_H_INCLUDED_ */
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -43,7 +43,7 @@ ngx_uint_t            ngx_event_flags;
 ngx_event_actions_t   ngx_event_actions;
 
 
-ngx_atomic_t          connection_counter = 1;
+static ngx_atomic_t   connection_counter = 1;
 ngx_atomic_t         *ngx_connection_counter = &connection_counter;
 
 
@@ -429,6 +429,7 @@ ngx_event_module_init(ngx_cycle_t *cycle
     u_char              *shared;
     size_t               size, cl;
     ngx_shm_t            shm;
+    ngx_time_t          *tp;
     ngx_core_conf_t     *ccf;
     ngx_event_conf_t    *ecf;
 
@@ -492,7 +493,8 @@ ngx_event_module_init(ngx_cycle_t *cycle
     cl = 128;
 
     size = cl            /* ngx_accept_mutex */
-           + cl;         /* ngx_connection_counter */
+           + cl          /* ngx_connection_counter */
+           + cl;         /* ngx_temp_number */
 
 #if (NGX_STAT_STUB)
 
@@ -526,23 +528,29 @@ ngx_event_module_init(ngx_cycle_t *cycle
 
     ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl);
 
-#if (NGX_STAT_STUB)
-
-    ngx_stat_accepted = (ngx_atomic_t *) (shared + 2 * cl);
-    ngx_stat_handled = (ngx_atomic_t *) (shared + 3 * cl);
-    ngx_stat_requests = (ngx_atomic_t *) (shared + 4 * cl);
-    ngx_stat_active = (ngx_atomic_t *) (shared + 5 * cl);
-    ngx_stat_reading = (ngx_atomic_t *) (shared + 6 * cl);
-    ngx_stat_writing = (ngx_atomic_t *) (shared + 7 * cl);
-
-#endif
-
     (void) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1);
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    "counter: %p, %d",
                    ngx_connection_counter, *ngx_connection_counter);
 
+    ngx_temp_number = (ngx_atomic_t *) (shared + 2 * cl);
+
+    tp = ngx_timeofday();
+
+    ngx_random_number = (tp->msec << 16) + ngx_pid;
+
+#if (NGX_STAT_STUB)
+
+    ngx_stat_accepted = (ngx_atomic_t *) (shared + 3 * cl);
+    ngx_stat_handled = (ngx_atomic_t *) (shared + 4 * cl);
+    ngx_stat_requests = (ngx_atomic_t *) (shared + 5 * cl);
+    ngx_stat_active = (ngx_atomic_t *) (shared + 6 * cl);
+    ngx_stat_reading = (ngx_atomic_t *) (shared + 7 * cl);
+    ngx_stat_writing = (ngx_atomic_t *) (shared + 8 * cl);
+
+#endif
+
     return NGX_OK;
 }
 
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -214,6 +214,8 @@ ngx_http_dav_put_handler(ngx_http_reques
 
     ngx_http_map_uri_to_path(r, &path, &root, 0);
 
+    path.len--;
+
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http put filename: \"%s\"", path.data);
 
--- a/src/http/modules/ngx_http_geoip_module.c
+++ b/src/http/modules/ngx_http_geoip_module.c
@@ -181,6 +181,7 @@ ngx_http_geoip_city_variable(ngx_http_re
 {
     u_long                  addr;
     char                   *val;
+    size_t                  len;
     GeoIPRecord            *gr;
     struct sockaddr_in     *sin;
     ngx_http_geoip_conf_t  *gcf;
@@ -207,17 +208,32 @@ ngx_http_geoip_city_variable(ngx_http_re
     val = *(char **) ((char *) gr + data);
 
     if (val == NULL) {
-        goto not_found;
+        goto no_value;
     }
 
-    v->len = ngx_strlen(val);
+    len = ngx_strlen(val);
+    v->data = ngx_pnalloc(r->pool, len);
+
+    if (v->data == NULL) {
+        GeoIPRecord_delete(gr);
+        return NGX_ERROR;
+    }
+
+    ngx_memcpy(v->data, val, len);
+
+    v->len = len;
     v->valid = 1;
     v->no_cacheable = 0;
     v->not_found = 0;
-    v->data = (u_char *) val;
+
+    GeoIPRecord_delete(gr);
 
     return NGX_OK;
 
+no_value:
+
+    GeoIPRecord_delete(gr);
+
 not_found:
 
     v->not_found = 1;
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -837,7 +837,13 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx
 
     if (ngx_strcmp(value[1].data, "off") == 0) {
         llcf->off = 1;
-        return NGX_CONF_OK;
+        if (cf->args->nelts == 2) {
+            return NGX_CONF_OK;
+        }
+
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid parameter \"%V\"", &value[2]);
+        return NGX_CONF_ERROR;
     }
 
     if (llcf->logs == NULL) {
--- 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.9';
+our $VERSION = '0.8.10';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -161,6 +161,12 @@ ngx_http_upstream_header_t  ngx_http_ups
                  offsetof(ngx_http_upstream_headers_in_t, last_modified),
                  ngx_http_upstream_copy_last_modified, 0, 0 },
 
+    { ngx_string("ETag"),
+                 ngx_http_upstream_process_header_line,
+                 offsetof(ngx_http_upstream_headers_in_t, etag),
+                 ngx_http_upstream_copy_header_line,
+                 offsetof(ngx_http_headers_out_t, etag), 0 },
+
     { ngx_string("Server"),
                  ngx_http_upstream_process_header_line,
                  offsetof(ngx_http_upstream_headers_in_t, server),
@@ -2661,6 +2667,8 @@ ngx_http_upstream_store(ngx_http_request
         }
     }
 
+    path.len--;
+
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "upstream stores \"%s\" to \"%s\"",
                    tf->file.name.data, path.data);
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -277,8 +277,6 @@ ngx_single_process_cycle(ngx_cycle_t *cy
 {
     ngx_uint_t  i;
 
-    ngx_init_temp_number();
-
     for (i = 0; ngx_modules[i]; i++) {
         if (ngx_modules[i]->init_process) {
             if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) {
@@ -930,8 +928,6 @@ ngx_worker_process_init(ngx_cycle_t *cyc
                       "sigprocmask() failed");
     }
 
-    ngx_init_temp_number();
-
     /*
      * disable deleting previous events for the listening sockets because
      * in the worker processes there are no events at all at this point