changeset 558:2da4537168f8 NGINX_0_8_31

nginx 0.8.31 *) Feature: now the "error_page" directive may redirect the 301 and 302 responses. *) Feature: the $geoip_city_continent_code, $geoip_latitude, and $geoip_longitude variables. Thanks to Arvind Sundararajan. *) Feature: now the ngx_http_image_filter_module deletes always EXIF and other application specific data if the data consume more than 5% of a JPEG file. *) Bugfix: nginx closed a connection if a cached response had an empty body. Thanks to Piotr Sikora. *) Bugfix: nginx might not be built by gcc 4.x if the -O2 or higher optimization option was used. Thanks to Maxim Dounin and Denis F. Latypoff. *) Bugfix: regular expressions in location were always tested in case-sensitive mode; the bug had appeared in 0.8.25. *) Bugfix: nginx cached a 304 response if there was the "If-None-Match" header line in a proxied request. Thanks to Tim Dettrick and David Kostal. *) Bugfix: nginx/Windows tried to delete a temporary file twice if the file should replace an already existent file.
author Igor Sysoev <http://sysoev.ru>
date Wed, 23 Dec 2009 00:00:00 +0300
parents 72104cd120ec
children 6026569dbf64
files CHANGES CHANGES.ru auto/cc/gcc src/core/nginx.c src/core/nginx.h src/core/ngx_file.c src/core/ngx_palloc.c src/core/ngx_palloc.h src/http/modules/ngx_http_degradation_module.c src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_geoip_module.c src/http/modules/ngx_http_image_filter_module.c src/http/modules/ngx_http_memcached_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/perl/nginx.pm src/http/ngx_http.c src/http/ngx_http.h src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_file_cache.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h src/os/unix/ngx_channel.c
diffstat 23 files changed, 260 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES	Tue Dec 15 00:00:00 2009 +0300
+++ b/CHANGES	Wed Dec 23 00:00:00 2009 +0300
@@ -1,4 +1,36 @@
 
+Changes with nginx 0.8.31                                        23 Dec 2009
+
+    *) Feature: now the "error_page" directive may redirect the 301 and 302 
+       responses.
+
+    *) Feature: the $geoip_city_continent_code, $geoip_latitude, and 
+       $geoip_longitude variables.
+       Thanks to Arvind Sundararajan.
+
+    *) Feature: now the ngx_http_image_filter_module deletes always EXIF 
+       and other application specific data if the data consume more than 5% 
+       of a JPEG file.
+
+    *) Bugfix: nginx closed a connection if a cached response had an empty 
+       body.
+       Thanks to Piotr Sikora.
+
+    *) Bugfix: nginx might not be built by gcc 4.x if the -O2 or higher 
+       optimization option was used.
+       Thanks to Maxim Dounin and Denis F. Latypoff.
+
+    *) Bugfix: regular expressions in location were always tested in 
+       case-sensitive mode; the bug had appeared in 0.8.25.
+
+    *) Bugfix: nginx cached a 304 response if there was the "If-None-Match" 
+       header line in a proxied request.
+       Thanks to Tim Dettrick and David Kostal.
+
+    *) Bugfix: nginx/Windows tried to delete a temporary file twice if the 
+       file should replace an already existent file.
+
+
 Changes with nginx 0.8.30                                        15 Dec 2009
 
     *) Change: now the default buffer size of the 
--- a/CHANGES.ru	Tue Dec 15 00:00:00 2009 +0300
+++ b/CHANGES.ru	Wed Dec 23 00:00:00 2009 +0300
@@ -1,4 +1,36 @@
 
+Изменения в nginx 0.8.31                                          23.12.2009
+
+    *) Добавление: теперь директива error_page может перенаправлять ответы 
+       со статусом 301 и 302.
+
+    *) Добавление: переменные $geoip_city_continent_code, $geoip_latitude и 
+       $geoip_longitude.
+       Спасибо Arvind Sundararajan.
+
+    *) Добавление: модуль ngx_http_image_filter_module теперь всегда 
+       удаляет EXIF и другие данные, если они занимают больше 5% в 
+       JPEG-файле.
+
+    *) Исправление: nginx закрывал соединение при запросе закэшированного 
+       ответа с пустым телом.
+       Спасибо Piotr Sikora.
+
+    *) Исправление: nginx мог не собираться gcc 4.x при использовании 
+       оптимизации -O2 и выше.
+       Спасибо Максиму Дунину и Денису Латыпову.
+
+    *) Исправление: регулярные выражения в location всегда тестировались с 
+       учётом регистра; ошибка появилась в 0.8.25.
+
+    *) Исправление: nginx кэшировал 304 ответ, если в заголовке 
+       проксируемого запроса была строка "If-None-Match".
+       Спасибо Tim Dettrick и David Kostal.
+
+    *) Исправление: nginx/Windows пытался дважды удалить временный файл при 
+       перезаписи уже существующего файла.
+
+
 Изменения в nginx 0.8.30                                          15.12.2009
 
     *) Изменение: теперь по умолчанию размер буфера директивы 
@@ -402,7 +434,7 @@
        Спасибо Максиму Дунину.
 
     *) Исправление: в обработке строк "Last-Modified" и "Accept-Ranges" в 
-       заголовке ответа бэкенда; ошибка появилась в 0.7.44
+       заголовке ответа бэкенда; ошибка появилась в 0.7.44.
        Спасибо Максиму Дунину.
 
     *) Исправление: ошибки "[alert] zero size buf" при получении пустых 
--- a/auto/cc/gcc	Tue Dec 15 00:00:00 2009 +0300
+++ b/auto/cc/gcc	Wed Dec 23 00:00:00 2009 +0300
@@ -51,8 +51,6 @@
 #NGX_GCC_OPT="-Os"
 NGX_GCC_OPT="-O"
 
-CFLAGS="$CFLAGS $NGX_GCC_OPT"
-
 #CFLAGS="$CFLAGS -fomit-frame-pointer"
 
 case $CPU in
--- a/src/core/nginx.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/core/nginx.c	Wed Dec 23 00:00:00 2009 +0300
@@ -287,9 +287,6 @@
     init_cycle.log = log;
     ngx_cycle = &init_cycle;
 
-    /* dummy pagesize to create aligned pool */
-    ngx_pagesize = 1024;
-
     init_cycle.pool = ngx_create_pool(1024, log);
     if (init_cycle.pool == NULL) {
         return 1;
--- a/src/core/nginx.h	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/core/nginx.h	Wed Dec 23 00:00:00 2009 +0300
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         8030
-#define NGINX_VERSION      "0.8.30"
+#define nginx_version         8031
+#define NGINX_VERSION      "0.8.31"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_file.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/core/ngx_file.c	Wed Dec 23 00:00:00 2009 +0300
@@ -592,6 +592,10 @@
 
     if (err == NGX_EEXIST) {
         err = ngx_win32_rename_file(src, to, ext->log);
+
+        if (err == 0) {
+            return NGX_OK;
+        }
     }
 
 #endif
--- a/src/core/ngx_palloc.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/core/ngx_palloc.c	Wed Dec 23 00:00:00 2009 +0300
@@ -17,7 +17,7 @@
 {
     ngx_pool_t  *p;
 
-    p = ngx_memalign(ngx_min(ngx_pagesize, size), size, log);
+    p = ngx_memalign(NGX_POOL_ALIGNMENT, size, log);
     if (p == NULL) {
         return NULL;
     }
@@ -181,7 +181,7 @@
 
     psize = (size_t) (pool->d.end - (u_char *) pool);
 
-    m = ngx_memalign(ngx_min(ngx_pagesize, psize), psize, pool->log);
+    m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);
     if (m == NULL) {
         return NULL;
     }
--- a/src/core/ngx_palloc.h	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/core/ngx_palloc.h	Wed Dec 23 00:00:00 2009 +0300
@@ -19,8 +19,11 @@
 #define NGX_MAX_ALLOC_FROM_POOL  (ngx_pagesize - 1)
 
 #define NGX_DEFAULT_POOL_SIZE    (16 * 1024)
+
+#define NGX_POOL_ALIGNMENT       16
 #define NGX_MIN_POOL_SIZE                                                     \
-    (sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t))
+    ngx_align((sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t)),            \
+              NGX_POOL_ALIGNMENT)
 
 
 typedef void (*ngx_pool_cleanup_pt)(void *data);
--- a/src/http/modules/ngx_http_degradation_module.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_degradation_module.c	Wed Dec 23 00:00:00 2009 +0300
@@ -198,9 +198,14 @@
                                "invalid sbrk size \"%V\"", &value[1]);
             return NGX_CONF_ERROR;
         }
+
+        return NGX_CONF_OK;
     }
 
-    return NGX_CONF_OK;
+    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                       "invalid parameter \"%V\"", &value[1]);
+
+    return NGX_CONF_ERROR;
 }
 
 
--- a/src/http/modules/ngx_http_fastcgi_module.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_fastcgi_module.c	Wed Dec 23 00:00:00 2009 +0300
@@ -242,7 +242,7 @@
 
     { ngx_string("fastcgi_bind"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_upsteam_bind_set_slot,
+      ngx_http_upstream_bind_set_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_fastcgi_loc_conf_t, upstream.local),
       NULL },
--- a/src/http/modules/ngx_http_geoip_module.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_geoip_module.c	Wed Dec 23 00:00:00 2009 +0300
@@ -30,6 +30,9 @@
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
+static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r);
 
 static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
 static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
@@ -93,23 +96,32 @@
 
 static ngx_http_variable_t  ngx_http_geoip_vars[] = {
 
-    { ngx_string("geoip_country_code"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_code"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_country_code3"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_code3"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_country_name"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_name"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_city_country_code"), NULL, ngx_http_geoip_city_variable,
+    { ngx_string("geoip_city_continent_code"), NULL,
+      ngx_http_geoip_city_variable,
+      offsetof(GeoIPRecord, continent_code), 0, 0 },
+
+    { ngx_string("geoip_city_country_code"), NULL,
+      ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_code), 0, 0 },
 
     { ngx_string("geoip_city_country_code3"), NULL,
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_code3), 0, 0 },
 
-    { ngx_string("geoip_city_country_name"), NULL, ngx_http_geoip_city_variable,
+    { ngx_string("geoip_city_country_name"), NULL,
+      ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_name), 0, 0 },
 
     { ngx_string("geoip_region"), NULL,
@@ -124,6 +136,14 @@
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, postal_code), 0, 0 },
 
+    { ngx_string("geoip_latitude"), NULL,
+      ngx_http_geoip_city_float_variable,
+      offsetof(GeoIPRecord, latitude), 0, 0 },
+
+    { ngx_string("geoip_longitude"), NULL,
+      ngx_http_geoip_city_float_variable,
+      offsetof(GeoIPRecord, longitude), 0, 0 },
+
     { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
 
@@ -179,34 +199,16 @@
 ngx_http_geoip_city_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
-    u_long                  addr;
-    char                   *val;
-    size_t                  len;
-    GeoIPRecord            *gr;
-    struct sockaddr_in     *sin;
-    ngx_http_geoip_conf_t  *gcf;
-
-    gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
+    char         *val;
+    size_t        len;
+    GeoIPRecord  *gr;
 
-    if (gcf->city == NULL) {
-        goto not_found;
-    }
-
-    if (r->connection->sockaddr->sa_family != AF_INET) {
-        goto not_found;
-    }
-
-    sin = (struct sockaddr_in *) r->connection->sockaddr;
-    addr = ntohl(sin->sin_addr.s_addr);
-
-    gr = GeoIP_record_by_ipnum(gcf->city, addr);
-
+    gr = ngx_http_geoip_get_city_record(r);
     if (gr == NULL) {
         goto not_found;
     }
 
     val = *(char **) ((char *) gr + data);
-
     if (val == NULL) {
         goto no_value;
     }
@@ -243,6 +245,56 @@
 
 
 static ngx_int_t
+ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    float         val;
+    GeoIPRecord  *gr;
+
+    gr = ngx_http_geoip_get_city_record(r);
+    if (gr == NULL) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN + 5);
+    if (v->data == NULL) {
+        GeoIPRecord_delete(gr);
+        return NGX_ERROR;
+    }
+
+    val = *(float *) ((char *) gr + data);
+
+    v->len = ngx_sprintf(v->data, "%.4f", val) - v->data;
+
+    GeoIPRecord_delete(gr);
+
+    return NGX_OK;
+}
+
+
+static GeoIPRecord *
+ngx_http_geoip_get_city_record(ngx_http_request_t *r)
+{
+    u_long                  addr;
+    struct sockaddr_in     *sin;
+    ngx_http_geoip_conf_t  *gcf;
+
+    gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
+
+    if (gcf->city && r->connection->sockaddr->sa_family == AF_INET) {
+
+        sin = (struct sockaddr_in *) r->connection->sockaddr;
+        addr = ntohl(sin->sin_addr.s_addr);
+
+        return GeoIP_record_by_ipnum(gcf->city, addr);
+    }
+
+    return NULL;
+}
+
+
+static ngx_int_t
 ngx_http_geoip_add_variables(ngx_conf_t *cf)
 {
     ngx_http_variable_t  *var, *v;
--- a/src/http/modules/ngx_http_image_filter_module.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_image_filter_module.c	Wed Dec 23 00:00:00 2009 +0300
@@ -63,6 +63,7 @@
 
     ngx_uint_t                   phase;
     ngx_uint_t                   type;
+    ngx_uint_t                   force;
 } ngx_http_image_filter_ctx_t;
 
 
@@ -501,7 +502,8 @@
 
     if (rc == NGX_OK
         && ctx->width <= ctx->max_width
-        && ctx->height <= ctx->max_height)
+        && ctx->height <= ctx->max_height
+        && !ctx->force)
     {
         return ngx_http_image_asis(r, ctx);
     }
@@ -601,6 +603,7 @@
 ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
 {
     u_char      *p, *last;
+    size_t       len, app;
     ngx_uint_t   width, height;
 
     p = ctx->image;
@@ -611,26 +614,38 @@
 
         p += 2;
         last = ctx->image + ctx->length - 10;
+        width = 0;
+        height = 0;
+        app = 0;
 
         while (p < last) {
 
             if (p[0] == 0xff && p[1] != 0xff) {
 
                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                               "JPEG: %02xd %02xd", *p, *(p + 1));
+                               "JPEG: %02xd %02xd", p[0], p[1]);
 
                 p++;
 
-                if (*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3
-                    || *p == 0xc9 || *p == 0xca || *p == 0xcb)
+                if ((*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3
+                     || *p == 0xc9 || *p == 0xca || *p == 0xcb)
+                    && (width == 0 || height == 0))
                 {
-                    goto found;
+                    width = p[6] * 256 + p[7];
+                    height = p[4] * 256 + p[5];
                 }
 
                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                                "JPEG: %02xd %02xd", p[1], p[2]);
 
-                p += p[1] * 256 + p[2];
+                len = p[1] * 256 + p[2];
+
+                if (*p >= 0xe1 && *p <= 0xef) {
+                    /* application data, e.g., EXIF, Adobe XMP, etc. */
+                    app += len;
+                }
+
+                p += len;
 
                 continue;
             }
@@ -638,12 +653,16 @@
             p++;
         }
 
-        return NGX_DECLINED;
+        if (width == 0 || height == 0) {
+            return NGX_DECLINED;
+        }
 
-    found:
-
-        width = p[6] * 256 + p[7];
-        height = p[4] * 256 + p[5];
+        if (ctx->length / 20 < app) {
+            /* force conversion if application data consume more than 5% */
+            ctx->force = 1;
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "app data size: %uz", app);
+        }
 
         break;
 
@@ -708,7 +727,8 @@
 
     conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
 
-    if ((ngx_uint_t) sx <= ctx->max_width
+    if (!ctx->force
+        && (ngx_uint_t) sx <= ctx->max_width
         && (ngx_uint_t) sy <= ctx->max_height)
     {
         gdImageDestroy(src);
--- a/src/http/modules/ngx_http_memcached_module.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_memcached_module.c	Wed Dec 23 00:00:00 2009 +0300
@@ -65,7 +65,7 @@
 
     { ngx_string("memcached_bind"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_upsteam_bind_set_slot,
+      ngx_http_upstream_bind_set_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_memcached_loc_conf_t, upstream.local),
       NULL },
--- a/src/http/modules/ngx_http_proxy_module.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/modules/ngx_http_proxy_module.c	Wed Dec 23 00:00:00 2009 +0300
@@ -231,7 +231,7 @@
 
     { ngx_string("proxy_bind"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_upsteam_bind_set_slot,
+      ngx_http_upstream_bind_set_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_proxy_loc_conf_t, upstream.local),
       NULL },
@@ -537,7 +537,7 @@
     { ngx_string("Expect"), ngx_string("") },
     { ngx_string("If-Modified-Since"), ngx_string("") },
     { ngx_string("If-Unmodified-Since"), ngx_string("") },
-    { ngx_string("If-Match-None"), ngx_string("") },
+    { ngx_string("If-None-Match"), ngx_string("") },
     { ngx_string("If-Match"), ngx_string("") },
     { ngx_string("Range"), ngx_string("") },
     { ngx_string("If-Range"), ngx_string("") },
--- a/src/http/modules/perl/nginx.pm	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/modules/perl/nginx.pm	Wed Dec 23 00:00:00 2009 +0300
@@ -47,7 +47,7 @@
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '0.8.30';
+our $VERSION = '0.8.31';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/ngx_http.c	Wed Dec 23 00:00:00 2009 +0300
@@ -1117,13 +1117,13 @@
         }
     }
 
-    sa = (struct sockaddr *) &lsopt->sockaddr;
+    sa = &lsopt->u.sockaddr;
 
     switch (sa->sa_family) {
 
 #if (NGX_HAVE_INET6)
     case AF_INET6:
-        sin6 = (struct sockaddr_in6 *) sa;
+        sin6 = &lsopt->u.sockaddr_in6;
         p = sin6->sin6_port;
         break;
 #endif
@@ -1135,7 +1135,7 @@
 #endif
 
     default: /* AF_INET */
-        sin = (struct sockaddr_in *) sa;
+        sin = &lsopt->u.sockaddr_in;
         p = sin->sin_port;
         break;
     }
@@ -1185,7 +1185,7 @@
      * may fill some fields in inherited sockaddr struct's
      */
 
-    sa = (struct sockaddr *) &lsopt->sockaddr;
+    sa = &lsopt->u.sockaddr;
 
     switch (sa->sa_family) {
 
@@ -1209,13 +1209,13 @@
         break;
     }
 
-    p = lsopt->sockaddr + off;
+    p = lsopt->u.sockaddr_data + off;
 
     addr = port->addrs.elts;
 
     for (i = 0; i < port->addrs.nelts; i++) {
 
-        if (ngx_memcmp(p, (u_char *) addr[i].opt.sockaddr + off, len) != 0) {
+        if (ngx_memcmp(p, addr[i].opt.u.sockaddr_data + off, len) != 0) {
             continue;
         }
 
@@ -1674,7 +1674,7 @@
     ngx_http_core_loc_conf_t  *clcf;
     ngx_http_core_srv_conf_t  *cscf;
 
-    ls = ngx_create_listening(cf, addr->opt.sockaddr, addr->opt.socklen);
+    ls = ngx_create_listening(cf, &addr->opt.u.sockaddr, addr->opt.socklen);
     if (ls == NULL) {
         return NULL;
     }
@@ -1743,7 +1743,7 @@
 
     for (i = 0; i < hport->naddrs; i++) {
 
-        sin = (struct sockaddr_in *) addr[i].opt.sockaddr;
+        sin = &addr[i].opt.u.sockaddr_in;
         addrs[i].addr = sin->sin_addr.s_addr;
         addrs[i].conf.default_server = addr[i].default_server;
 #if (NGX_HTTP_SSL)
@@ -1804,7 +1804,7 @@
 
     for (i = 0; i < hport->naddrs; i++) {
 
-        sin6 = (struct sockaddr_in6 *) addr[i].opt.sockaddr;
+        sin6 = &addr[i].opt.u.sockaddr_in6;
         addrs6[i].addr6 = sin6->sin6_addr;
         addrs6[i].conf.default_server = addr[i].default_server;
 #if (NGX_HTTP_SSL)
--- a/src/http/ngx_http.h	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/ngx_http.h	Wed Dec 23 00:00:00 2009 +0300
@@ -94,7 +94,7 @@
 void ngx_http_request_empty_handler(ngx_http_request_t *r);
 
 
-#define ngx_http_ephemeral(r)  (ngx_http_ephemeral_t *) (&r->uri_start)
+#define ngx_http_ephemeral(r)  (void *) (&r->uri_start)
 
 
 #define NGX_HTTP_LAST   1
--- a/src/http/ngx_http_core_module.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/ngx_http_core_module.c	Wed Dec 23 00:00:00 2009 +0300
@@ -2588,6 +2588,8 @@
 
 #if (NGX_HAVE_CASELESS_FILESYSTEM)
     rc.options = NGX_REGEX_CASELESS;
+#else
+    rc.options = caseless;
 #endif
 
     clcf->regex = ngx_http_regex_compile(cf, &rc);
@@ -2848,7 +2850,7 @@
     if (!conf->listen) {
         ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t));
 
-        sin = (struct sockaddr_in *) &lsopt.sockaddr;
+        sin = &lsopt.u.sockaddr_in;
 
         sin->sin_family = AF_INET;
 #if (NGX_WIN32)
@@ -2865,7 +2867,7 @@
         lsopt.sndbuf = -1;
         lsopt.wildcard = 1;
 
-        (void) ngx_sock_ntop((struct sockaddr *) &lsopt.sockaddr, lsopt.addr,
+        (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.addr,
                              NGX_SOCKADDR_STRLEN, 1);
 
         if (ngx_http_add_listen(cf, conf, &lsopt) == NGX_OK) {
@@ -3273,7 +3275,7 @@
 
     ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t));
 
-    ngx_memcpy(lsopt.sockaddr, u.sockaddr, u.socklen);
+    ngx_memcpy(&lsopt.u.sockaddr, u.sockaddr, u.socklen);
 
     lsopt.socklen = u.socklen;
     lsopt.backlog = NGX_LISTEN_BACKLOG;
@@ -3281,7 +3283,7 @@
     lsopt.sndbuf = -1;
     lsopt.wildcard = u.wildcard;
 
-    (void) ngx_sock_ntop((struct sockaddr *) &lsopt.sockaddr, lsopt.addr,
+    (void) ngx_sock_ntop(&lsopt.u.sockaddr, lsopt.addr,
                          NGX_SOCKADDR_STRLEN, 1);
 
     for (n = 2; n < cf->args->nelts; n++) {
@@ -3378,7 +3380,7 @@
 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
             struct sockaddr  *sa;
 
-            sa = (struct sockaddr *) lsopt.sockaddr;
+            sa = &lsopt.u.sockaddr;
 
             if (sa->sa_family == AF_INET6) {
 
@@ -3898,9 +3900,9 @@
             return NGX_CONF_ERROR;
         }
 
-        if (err->status < 400 || err->status > 599) {
+        if (err->status < 300 || err->status > 599) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "value \"%V\" must be between 400 and 599",
+                               "value \"%V\" must be between 300 and 599",
                                &value[i]);
             return NGX_CONF_ERROR;
         }
@@ -4318,8 +4320,15 @@
 
     if (*sp < NGX_MIN_POOL_SIZE) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "pool must be no less than %uz", NGX_MIN_POOL_SIZE);
-
+                           "the pool size must be no less than %uz",
+                           NGX_MIN_POOL_SIZE);
+        return NGX_CONF_ERROR;
+    }
+
+    if (*sp % NGX_POOL_ALIGNMENT) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "the pool size must be a multiple of %uz",
+                           NGX_POOL_ALIGNMENT);
         return NGX_CONF_ERROR;
     }
 
--- a/src/http/ngx_http_core_module.h	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/ngx_http_core_module.h	Wed Dec 23 00:00:00 2009 +0300
@@ -43,7 +43,18 @@
 
 
 typedef struct {
-    u_char                     sockaddr[NGX_SOCKADDRLEN];
+    union {
+        struct sockaddr        sockaddr;
+        struct sockaddr_in     sockaddr_in;
+#if (NGX_HAVE_INET6)
+        struct sockaddr_in6    sockaddr_in6;
+#endif
+#if (NGX_HAVE_UNIX_DOMAIN)
+        struct sockaddr_un     sockaddr_un;
+#endif
+        u_char                 sockaddr_data[NGX_SOCKADDRLEN];
+    } u;
+
     socklen_t                  socklen;
 
     unsigned                   set:1;
--- a/src/http/ngx_http_file_cache.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/ngx_http_file_cache.c	Wed Dec 23 00:00:00 2009 +0300
@@ -783,7 +783,6 @@
 ngx_int_t
 ngx_http_cache_send(ngx_http_request_t *r)
 {
-    off_t              size;
     ngx_int_t          rc;
     ngx_buf_t         *b;
     ngx_chain_t        out;
@@ -806,21 +805,18 @@
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
+    r->header_only = (c->length - c->body_start) == 0;
+
     rc = ngx_http_send_header(r);
 
     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
         return rc;
     }
 
-    size = c->length - c->body_start;
-    if (size == 0) {
-        return rc;
-    }
-
     b->file_pos = c->body_start;
     b->file_last = c->length;
 
-    b->in_file = size ? 1: 0;
+    b->in_file = 1;
     b->last_buf = (r == r->main) ? 1: 0;
     b->last_in_chain = 1;
 
--- a/src/http/ngx_http_upstream.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/ngx_http_upstream.c	Wed Dec 23 00:00:00 2009 +0300
@@ -1548,7 +1548,7 @@
 
     /* rc == NGX_OK */
 
-    if (u->headers_in.status_n >= NGX_HTTP_BAD_REQUEST) {
+    if (u->headers_in.status_n > NGX_HTTP_SPECIAL_RESPONSE) {
 
         if (r->subrequest_in_memory) {
             u->buffer.last = u->buffer.pos;
@@ -4204,7 +4204,7 @@
 
 
 char *
-ngx_http_upsteam_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf)
 {
     char  *p = conf;
--- a/src/http/ngx_http_upstream.h	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/http/ngx_http_upstream.h	Wed Dec 23 00:00:00 2009 +0300
@@ -323,7 +323,7 @@
 void ngx_http_upstream_init(ngx_http_request_t *r);
 ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
     ngx_url_t *u, ngx_uint_t flags);
-char *ngx_http_upsteam_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+char *ngx_http_upstream_bind_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 ngx_int_t ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
     ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
--- a/src/os/unix/ngx_channel.c	Tue Dec 15 00:00:00 2009 +0300
+++ b/src/os/unix/ngx_channel.c	Wed Dec 23 00:00:00 2009 +0300
@@ -36,7 +36,18 @@
         cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
         cmsg.cm.cmsg_level = SOL_SOCKET;
         cmsg.cm.cmsg_type = SCM_RIGHTS;
-        *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
+
+        /*
+         * We have to use ngx_memcpy() instead of simple
+         *   *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
+         * because some gcc 4.4 with -O2/3/s optimization issues the warning:
+         *   dereferencing type-punned pointer will break strict-aliasing rules
+         *
+         * Fortunately, gcc with -O1 compiles this ngx_memcpy()
+         * in the same simple assigment as in the code above
+         */
+
+        ngx_memcpy(CMSG_DATA(&cmsg.cm), &ch->fd, sizeof(int));
     }
 
     msg.msg_flags = 0;
@@ -153,7 +164,9 @@
             return NGX_ERROR;
         }
 
-        ch->fd = *(int *) CMSG_DATA(&cmsg.cm);
+        /* ch->fd = *(int *) CMSG_DATA(&cmsg.cm); */
+
+        ngx_memcpy(&ch->fd, CMSG_DATA(&cmsg.cm), sizeof(int));
     }
 
     if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) {