diff src/core/ngx_regex.c @ 4423:196c3dacff0d

Fixed memory leak on HUP signal when PCRE JIT was used. The PCRE JIT compiler uses mmap to allocate memory for its executable codes, so we have to explicitly call the pcre_free_study() function to free this memory.
author Valentin Bartenev <vbart@nginx.com>
date Mon, 30 Jan 2012 12:53:57 +0000
parents 23ea4e72c85a
children 6e1a48bcf915
line wrap: on
line diff
--- a/src/core/ngx_regex.c
+++ b/src/core/ngx_regex.c
@@ -16,6 +16,9 @@ typedef struct {
 
 static void * ngx_libc_cdecl ngx_regex_malloc(size_t size);
 static void ngx_libc_cdecl ngx_regex_free(void *p);
+#if (NGX_HAVE_PCRE_JIT)
+static void ngx_pcre_free_studies(void *data);
+#endif
 
 static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle);
 
@@ -274,6 +277,41 @@ ngx_regex_free(void *p)
 }
 
 
+#if (NGX_HAVE_PCRE_JIT)
+
+static void
+ngx_pcre_free_studies(void *data)
+{
+    ngx_list_t *studies = data;
+
+    ngx_uint_t        i;
+    ngx_list_part_t  *part;
+    ngx_regex_elt_t  *elts;
+
+    part = &studies->part;
+    elts = part->elts;
+
+    for (i = 0 ; /* void */ ; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            elts = part->elts;
+            i = 0;
+        }
+
+        if (elts[i].regex->extra != NULL) {
+            pcre_free_study(elts[i].regex->extra);
+        }
+    }
+}
+
+#endif
+
+
 static ngx_int_t
 ngx_regex_module_init(ngx_cycle_t *cycle)
 {
@@ -287,12 +325,27 @@ ngx_regex_module_init(ngx_cycle_t *cycle
 
 #if (NGX_HAVE_PCRE_JIT)
     {
-    ngx_regex_conf_t  *rcf;
+    ngx_regex_conf_t    *rcf;
+    ngx_pool_cleanup_t  *cln;
 
     rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module);
 
     if (rcf->pcre_jit) {
         opt = PCRE_STUDY_JIT_COMPILE;
+
+        /*
+         * The PCRE JIT compiler uses mmap for its executable codes, so we
+         * have to explicitly call the pcre_free_study() function to free
+         * this memory.
+         */
+
+        cln = ngx_pool_cleanup_add(cycle->pool, 0);
+        if (cln == NULL) {
+            return NGX_ERROR;
+        }
+
+        cln->handler = ngx_pcre_free_studies;
+        cln->data = ngx_pcre_studies;
     }
     }
 #endif