changeset 594:3436cf38d59e NGINX_0_8_49

nginx 0.8.49 *) Feature: the "image_filter_jpeg_quality" directive supports variables. *) Bugfix: a segmentation fault might occur in a worker process, if the $geoip_region_name variables was used; the bug had appeared in 0.8.48. *) Bugfix: errors intercepted by error_page were cached only for next request; the bug had appeared in 0.8.48.
author Igor Sysoev <http://sysoev.ru>
date Mon, 09 Aug 2010 00:00:00 +0400
parents ad310549c5d4
children 57dcc025db4f
files CHANGES CHANGES.ru src/core/nginx.h src/http/modules/ngx_http_geoip_module.c src/http/modules/ngx_http_image_filter_module.c src/http/modules/perl/nginx.pm src/http/ngx_http_file_cache.c
diffstat 7 files changed, 109 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,17 @@
 
+Changes with nginx 0.8.49                                        09 Aug 2010
+
+    *) Feature: the "image_filter_jpeg_quality" directive supports 
+       variables.
+
+    *) Bugfix: a segmentation fault might occur in a worker process, if the 
+       $geoip_region_name variables was used; the bug had appeared in 
+       0.8.48.
+
+    *) Bugfix: errors intercepted by error_page were cached only for next 
+       request; the bug had appeared in 0.8.48.
+
+
 Changes with nginx 0.8.48                                        03 Aug 2010
 
     *) Change: now the "server_name" directive default value is an empty 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,17 @@
 
+Изменения в nginx 0.8.49                                          09.08.2010
+
+    *) Добавление: директива image_filter_jpeg_quality поддерживает 
+       переменные.
+
+    *) Исправление: при использовании переменной $geoip_region_name в 
+       рабочем процессе мог произойти segmentation fault; ошибка появилась 
+       в 0.8.48.
+
+    *) Исправление: ошибки, перехваченные error_page, кэшировались только 
+       до следующего запроса; ошибка появилась в 0.8.48.
+
+
 Изменения в nginx 0.8.48                                          03.08.2010
 
     *) Изменение: теперь по умолчанию директива server_name имеет значение 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         8048
-#define NGINX_VERSION      "0.8.48"
+#define nginx_version         8049
+#define NGINX_VERSION      "0.8.49"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/http/modules/ngx_http_geoip_module.c
+++ b/src/http/modules/ngx_http_geoip_module.c
@@ -231,7 +231,6 @@ ngx_http_geoip_city_variable(ngx_http_re
 
     len = ngx_strlen(val);
     v->data = ngx_pnalloc(r->pool, len);
-
     if (v->data == NULL) {
         GeoIPRecord_delete(gr);
         return NGX_ERROR;
@@ -275,11 +274,15 @@ ngx_http_geoip_region_name_variable(ngx_
 
     val = GeoIP_region_name_by_code(gr->country_code, gr->region);
 
+    GeoIPRecord_delete(gr);
+
+    if (val == NULL) {
+        goto not_found;
+    }
+
     len = ngx_strlen(val);
     v->data = ngx_pnalloc(r->pool, len);
-
     if (v->data == NULL) {
-        GeoIPRecord_delete(gr);
         return NGX_ERROR;
     }
 
@@ -290,8 +293,6 @@ ngx_http_geoip_region_name_variable(ngx_
     v->no_cacheable = 0;
     v->not_found = 0;
 
-    GeoIPRecord_delete(gr);
-
     return NGX_OK;
 
 not_found:
--- a/src/http/modules/ngx_http_image_filter_module.c
+++ b/src/http/modules/ngx_http_image_filter_module.c
@@ -38,12 +38,13 @@ typedef struct {
     ngx_uint_t                   filter;
     ngx_uint_t                   width;
     ngx_uint_t                   height;
-    ngx_int_t                    jpeg_quality;
+    ngx_uint_t                   jpeg_quality;
 
     ngx_flag_t                   transparency;
 
     ngx_http_complex_value_t    *wcv;
     ngx_http_complex_value_t    *hcv;
+    ngx_http_complex_value_t    *jqcv;
 
     size_t                       buffer_size;
 } ngx_http_image_filter_conf_t;
@@ -99,6 +100,8 @@ static char *ngx_http_image_filter_merge
     void *child);
 static char *ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+static char *ngx_http_image_filter_jpeg_quality(ngx_conf_t *cf,
+    ngx_command_t *cmd, void *conf);
 static ngx_int_t ngx_http_image_filter_init(ngx_conf_t *cf);
 
 
@@ -113,9 +116,9 @@ static ngx_command_t  ngx_http_image_fil
 
     { ngx_string("image_filter_jpeg_quality"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_num_slot,
+      ngx_http_image_filter_jpeg_quality,
       NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_image_filter_conf_t, jpeg_quality),
+      0,
       NULL },
 
     { ngx_string("image_filter_transparency"),
@@ -989,6 +992,7 @@ ngx_http_image_out(ngx_http_request_t *r
 {
     char                          *failed;
     u_char                        *out;
+    ngx_int_t                      jq;
     ngx_http_image_filter_conf_t  *conf;
 
     out = NULL;
@@ -997,7 +1001,13 @@ ngx_http_image_out(ngx_http_request_t *r
 
     case NGX_HTTP_IMAGE_JPEG:
         conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
-        out = gdImageJpegPtr(img, size, conf->jpeg_quality);
+
+        jq = ngx_http_image_filter_get_value(r, conf->jqcv, conf->jpeg_quality);
+        if (jq <= 0) {
+            return NULL;
+        }
+
+        out = gdImageJpegPtr(img, size, jq);
         failed = "gdImageJpegPtr() failed";
         break;
 
@@ -1079,7 +1089,7 @@ ngx_http_image_filter_create_conf(ngx_co
     }
 
     conf->filter = NGX_CONF_UNSET_UINT;
-    conf->jpeg_quality = NGX_CONF_UNSET;
+    conf->jpeg_quality = NGX_CONF_UNSET_UINT;
     conf->transparency = NGX_CONF_UNSET;
     conf->buffer_size = NGX_CONF_UNSET_SIZE;
 
@@ -1108,7 +1118,11 @@ ngx_http_image_filter_merge_conf(ngx_con
     }
 
     /* 75 is libjpeg default quality */
-    ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75);
+    ngx_conf_merge_uint_value(conf->jpeg_quality, prev->jpeg_quality, 75);
+
+    if (conf->jqcv == NULL) {
+        conf->jqcv = prev->jqcv;
+    }
 
     ngx_conf_merge_value(conf->transparency, prev->transparency, 1);
 
@@ -1228,6 +1242,53 @@ failed:
 }
 
 
+static char *
+ngx_http_image_filter_jpeg_quality(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf)
+{
+    ngx_http_image_filter_conf_t *imcf = conf;
+
+    ngx_str_t                         *value;
+    ngx_int_t                          n;
+    ngx_http_complex_value_t           cv;
+    ngx_http_compile_complex_value_t   ccv;
+
+    value = cf->args->elts;
+
+    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+    ccv.cf = cf;
+    ccv.value = &value[1];
+    ccv.complex_value = &cv;
+
+    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (cv.lengths == NULL) {
+        n = ngx_http_image_filter_value(&value[1]);
+
+        if (n <= 0) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid parameter \"%V\"", &value[1]);
+            return NGX_CONF_ERROR;
+        }
+
+        imcf->jpeg_quality = (ngx_uint_t) n;
+
+    } else {
+        imcf->jqcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
+        if (imcf->jqcv == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        *imcf->jqcv = cv;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
 static ngx_int_t
 ngx_http_image_filter_init(ngx_conf_t *cf)
 {
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -48,7 +48,7 @@ our @EXPORT = qw(
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '0.8.48';
+our $VERSION = '0.8.49';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -581,6 +581,7 @@ ngx_http_file_cache_exists(ngx_http_file
 
     fcn->uses = 1;
     fcn->count = 1;
+    fcn->updating = 0;
 
 renew:
 
@@ -927,10 +928,13 @@ ngx_http_file_cache_free(ngx_http_cache_
     }
 
     if (c->error) {
-        fcn->valid_sec = c->valid_sec;
-        fcn->valid_msec = c->valid_msec;
         fcn->error = c->error;
 
+        if (c->valid_sec) {
+            fcn->valid_sec = c->valid_sec;
+            fcn->valid_msec = c->valid_msec;
+        }
+
     } else if (!fcn->exists && fcn->count == 0 && c->min_uses == 1) {
         ngx_queue_remove(&fcn->queue);
         ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
@@ -1426,6 +1430,7 @@ ngx_http_file_cache_add(ngx_http_file_ca
         fcn->valid_msec = c->valid_msec;
         fcn->error = 0;
         fcn->exists = 1;
+        fcn->updating = 0;
         fcn->uniq = c->uniq;
         fcn->valid_sec = c->valid_sec;
         fcn->body_start = c->body_start;