# HG changeset patch # User Igor Sysoev # Date 1261515600 -10800 # Node ID 2da4537168f879f528f09d0e0ce80abe68adf05e # Parent 72104cd120ece09b3004261b2a29ace3e0aab812 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. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -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 diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -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" при получении пустых diff --git a/auto/cc/gcc b/auto/cc/gcc --- a/auto/cc/gcc +++ b/auto/cc/gcc @@ -51,8 +51,6 @@ esac #NGX_GCC_OPT="-Os" NGX_GCC_OPT="-O" -CFLAGS="$CFLAGS $NGX_GCC_OPT" - #CFLAGS="$CFLAGS -fomit-frame-pointer" case $CPU in diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -287,9 +287,6 @@ main(int argc, char *const *argv) 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; 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 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" 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 @@ -592,6 +592,10 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_ if (err == NGX_EEXIST) { err = ngx_win32_rename_file(src, to, ext->log); + + if (err == 0) { + return NGX_OK; + } } #endif diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c --- a/src/core/ngx_palloc.c +++ b/src/core/ngx_palloc.c @@ -17,7 +17,7 @@ ngx_create_pool(size_t size, ngx_log_t * { 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 @@ ngx_palloc_block(ngx_pool_t *pool, size_ 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; } diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h --- a/src/core/ngx_palloc.h +++ b/src/core/ngx_palloc.h @@ -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); diff --git a/src/http/modules/ngx_http_degradation_module.c b/src/http/modules/ngx_http_degradation_module.c --- a/src/http/modules/ngx_http_degradation_module.c +++ b/src/http/modules/ngx_http_degradation_module.c @@ -198,9 +198,14 @@ ngx_http_degradation(ngx_conf_t *cf, ngx "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; } 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 @@ -242,7 +242,7 @@ static ngx_command_t ngx_http_fastcgi_c { 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 }, diff --git a/src/http/modules/ngx_http_geoip_module.c b/src/http/modules/ngx_http_geoip_module.c --- a/src/http/modules/ngx_http_geoip_module.c +++ b/src/http/modules/ngx_http_geoip_module.c @@ -30,6 +30,9 @@ static ngx_int_t ngx_http_geoip_country_ 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 @@ ngx_module_t ngx_http_geoip_module = { 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 @@ static ngx_http_variable_t ngx_http_geo 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 @@ static ngx_int_t 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 @@ not_found: 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; diff --git a/src/http/modules/ngx_http_image_filter_module.c b/src/http/modules/ngx_http_image_filter_module.c --- a/src/http/modules/ngx_http_image_filter_module.c +++ b/src/http/modules/ngx_http_image_filter_module.c @@ -63,6 +63,7 @@ typedef struct { ngx_uint_t phase; ngx_uint_t type; + ngx_uint_t force; } ngx_http_image_filter_ctx_t; @@ -501,7 +502,8 @@ ngx_http_image_process(ngx_http_request_ 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 @@ static ngx_int_t 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 @@ ngx_http_image_size(ngx_http_request_t * 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 @@ ngx_http_image_size(ngx_http_request_t * 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 @@ ngx_http_image_resize(ngx_http_request_t 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); 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 @@ -65,7 +65,7 @@ static ngx_command_t ngx_http_memcached { 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 }, 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 @@ -231,7 +231,7 @@ static ngx_command_t ngx_http_proxy_com { 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 @@ static ngx_keyval_t ngx_http_proxy_cach { 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("") }, 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.30'; +our $VERSION = '0.8.31'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -1117,13 +1117,13 @@ ngx_http_add_listen(ngx_conf_t *cf, ngx_ } } - 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 @@ ngx_http_add_listen(ngx_conf_t *cf, ngx_ #endif default: /* AF_INET */ - sin = (struct sockaddr_in *) sa; + sin = &lsopt->u.sockaddr_in; p = sin->sin_port; break; } @@ -1185,7 +1185,7 @@ ngx_http_add_addresses(ngx_conf_t *cf, n * 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 @@ ngx_http_add_addresses(ngx_conf_t *cf, n 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_add_listening(ngx_conf_t *cf, n 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 @@ ngx_http_add_addrs(ngx_conf_t *cf, ngx_h 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 @@ ngx_http_add_addrs6(ngx_conf_t *cf, ngx_ 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) diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -94,7 +94,7 @@ void ngx_http_empty_handler(ngx_event_t 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 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 @@ -2588,6 +2588,8 @@ ngx_http_core_regex_location(ngx_conf_t #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 @@ ngx_http_core_merge_srv_conf(ngx_conf_t 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 @@ ngx_http_core_merge_srv_conf(ngx_conf_t 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_http_core_listen(ngx_conf_t *cf, ngx 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 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx 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 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx #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 @@ ngx_http_core_error_page(ngx_conf_t *cf, 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 @@ ngx_http_core_pool_size(ngx_conf_t *cf, 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; } 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 @@ -43,7 +43,18 @@ typedef struct ngx_http_core_loc_conf_s 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; 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 @@ -783,7 +783,6 @@ ngx_http_file_cache_update(ngx_http_requ 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 @@ ngx_http_cache_send(ngx_http_request_t * 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; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1548,7 +1548,7 @@ ngx_http_upstream_process_header(ngx_htt /* 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 @@ ngx_http_upstream_add(ngx_conf_t *cf, ng 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; diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -323,7 +323,7 @@ ngx_int_t ngx_http_upstream_create(ngx_h 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, diff --git a/src/os/unix/ngx_channel.c b/src/os/unix/ngx_channel.c --- a/src/os/unix/ngx_channel.c +++ b/src/os/unix/ngx_channel.c @@ -36,7 +36,18 @@ ngx_write_channel(ngx_socket_t s, ngx_ch 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 @@ ngx_read_channel(ngx_socket_t s, ngx_cha 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)) {