changeset 480:a28a95b7a86d

Merge with nginx 0.7.33.
author Maxim Dounin <mdounin@mdounin.ru>
date Wed, 04 Feb 2009 01:03:03 +0300
parents 96428109ec3b (current diff) 28335b730750 (diff)
children abbf48179d76
files .hgtags src/mail/ngx_mail_smtp_handler.c
diffstat 19 files changed, 207 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags
+++ b/.hgtags
@@ -225,3 +225,5 @@ dc98ed169c03366ef89869d49da3b21b4b6663fe
 2580fe1c5a9a300134ea707c5e27d871bc0237f0 PATCH_NGINX_MAIL_0_6
 2c989ee54dbd4bfa12b53f3b0ff59e5def929818 PATCH_NGINX_MAIL_0_7
 ce4f9ff90bfa58834c5b0db35395fd980c8c4aa0 NGINX_0_7_31
+6281966854a55e092674b01b6861bd025fe158ee NGINX_0_7_32
+670af56a1158749e82d7b1fce1ce348f8e10472a NGINX_0_7_33
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,32 @@
 
+Changes with nginx 0.7.33                                        02 Feb 2009
+
+    *) Bugfix: a double response might be returned if the epoll or rtsig 
+       methods are used and a redirect was returned to a request with 
+       body.
+       Thanks to Eden Li.
+
+    *) Bugfix: the $sent_http_location variable was empty for some 
+       redirects types.
+
+    *) Bugfix: a segmentation fault might occur in worker process if 
+       "resolver" directive was used in SMTP proxy.
+
+
+Changes with nginx 0.7.32                                        26 Jan 2009
+
+    *) Feature: now a directory existence testing can be set explicitly in 
+       the "try_files" directive.
+
+    *) Bugfix: fastcgi_store stored files not always.
+
+    *) Bugfix: in geo ranges.
+
+    *) Bugfix: in shared memory allocations if nginx was built without 
+       debugging.
+       Thanks to Andrey Kvasov.
+
+
 Changes with nginx 0.7.31                                        19 Jan 2009
 
     *) Change: now the "try_files" directive tests files only and ignores 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,31 @@
 
+Изменения в nginx 0.7.33                                          02.02.2009
+
+    *) Исправление: если на запрос с телом возвращался редирект, то ответ 
+       мог быть двойным при использовании методов epoll или rtsig.
+       Спасибо Eden Li.
+
+    *) Исправление: для некоторых типов редиректов в переменной 
+       $sent_http_location было пустое значение.
+
+    *) Исправление: при использовании директивы resolver в SMTP 
+       прокси-сервере в рабочем процессе мог произойти segmentation fault.
+
+
+Изменения в nginx 0.7.32                                          26.01.2009
+
+    *) Добавление: теперь в директиве try_files можно явно указать проверку 
+       каталога.
+
+    *) Исправление: fastcgi_store не всегда сохранял файлы.
+
+    *) Исправление: в гео-диапазонах.
+
+    *) Исправление: ошибки выделения больших блоков в разделяемой памяти, 
+       если nginx был собран без отладки.
+       Спасибо Андрею Квасову.
+
+
 Изменения в nginx 0.7.31                                          19.01.2009
 
     *) Изменение: теперь директива try_files проверяет только файлы, 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VERSION      "0.7.31"
+#define NGINX_VERSION      "0.7.33"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -394,6 +394,10 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
     cycle->log = cycle->new_log;
     pool->log = cycle->new_log;
 
+    if (cycle->log->log_level == 0) {
+        cycle->log->log_level = NGX_LOG_ERR;
+    }
+
 
     /* create shared memory */
 
--- a/src/core/ngx_open_file_cache.c
+++ b/src/core/ngx_open_file_cache.c
@@ -457,7 +457,7 @@ ngx_open_and_stat_file(u_char *name, ngx
             goto failed;
         }
 
-        if (of->is_dir) {
+        if (ngx_is_dir(&fi)) {
             goto done;
         }
     }
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -578,6 +578,7 @@ failed:
 ngx_int_t
 ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
 {
+    u_char               *name;
     ngx_resolver_t       *r;
     ngx_resolver_node_t  *rn;
 
@@ -601,19 +602,21 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx
 
             ngx_queue_insert_head(&r->addr_expire_queue, &rn->queue);
 
-            ctx->name.len = rn->nlen;
-            ctx->name.data = ngx_resolver_dup(r, rn->name, rn->nlen);
-            if (ctx->name.data == NULL) {
+            name = ngx_resolver_dup(r, rn->name, rn->nlen);
+            if (name == NULL) {
                 goto failed;
             }
 
+            ctx->name.len = rn->nlen;
+            ctx->name.data = name;
+
             /* unlock addr mutex */
 
             ctx->state = NGX_OK;
 
             ctx->handler(ctx);
 
-            ngx_resolver_free(r, ctx->name.data);
+            ngx_resolver_free(r, name);
 
             return NGX_OK;
         }
@@ -623,7 +626,9 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx
             ctx->next = rn->waiting;
             rn->waiting = ctx;
 
-            return NGX_AGAIN;
+            /* unlock addr mutex */
+
+            return NGX_OK;
         }
 
         ngx_queue_remove(&rn->queue);
@@ -1336,7 +1341,7 @@ ngx_resolver_process_a(ngx_resolver_t *r
              ctx->handler(ctx);
         }
 
-        if (naddrs) {
+        if (naddrs > 1) {
             ngx_resolver_free(r, addrs);
         }
 
@@ -1513,20 +1518,23 @@ ngx_resolver_process_ptr(ngx_resolver_t 
         goto short_response;
     }
 
-    len -= 2;
-
     if (ngx_resolver_copy(r, &name, buf, &buf[i], &buf[n]) != NGX_OK) {
         return;
     }
 
     ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0, "resolver an:%V", &name);
 
-    if (len != (size_t) rn->nlen || ngx_strncmp(name.data, rn->name, len) != 0)
+    if (name.len != (size_t) rn->nlen
+        || ngx_strncmp(name.data, rn->name, name.len) != 0)
     {
-        ngx_resolver_free(r, rn->name);
+        if (rn->nlen) {
+            ngx_resolver_free(r, rn->name);
+        }
+
+        rn->nlen = (u_short) name.len;
         rn->name = name.data;
 
-        name.data = ngx_resolver_dup(r, rn->name, len);
+        name.data = ngx_resolver_dup(r, rn->name, name.len);
         if (name.data == NULL) {
             goto failed;
         }
--- a/src/core/ngx_slab.c
+++ b/src/core/ngx_slab.c
@@ -661,11 +661,8 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *po
             }
 
             page->slab = pages | NGX_SLAB_PAGE_START;
-
-#if (NGX_DEBUG)
             page->next = NULL;
             page->prev = NGX_SLAB_PAGE;
-#endif
 
             if (--pages == 0) {
                 return page;
@@ -673,10 +670,8 @@ ngx_slab_alloc_pages(ngx_slab_pool_t *po
 
             for (p = page + 1; pages; pages--) {
                 p->slab = NGX_SLAB_PAGE_BUSY;
-#if (NGX_DEBUG)
                 p->next = NULL;
                 p->prev = NGX_SLAB_PAGE;
-#endif
                 p++;
             }
 
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -135,8 +135,8 @@ static ngx_int_t ngx_http_fastcgi_script
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_fastcgi_split(ngx_http_request_t *r,
-    ngx_http_fastcgi_ctx_t *f, ngx_http_fastcgi_loc_conf_t *flcf);
+static ngx_http_fastcgi_ctx_t *ngx_http_fastcgi_split(ngx_http_request_t *r,
+    ngx_http_fastcgi_loc_conf_t *flcf);
 
 static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
@@ -2111,10 +2111,11 @@ ngx_http_fastcgi_script_name_variable(ng
     ngx_http_fastcgi_ctx_t       *f;
     ngx_http_fastcgi_loc_conf_t  *flcf;
 
-    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
     flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
 
-    if (ngx_http_fastcgi_split(r, f, flcf) != NGX_OK) {
+    f = ngx_http_fastcgi_split(r, flcf);
+
+    if (f == NULL) {
         return NGX_ERROR;
     }
 
@@ -2151,10 +2152,11 @@ ngx_http_fastcgi_path_info_variable(ngx_
     ngx_http_fastcgi_ctx_t       *f;
     ngx_http_fastcgi_loc_conf_t  *flcf;
 
-    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
     flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
 
-    if (ngx_http_fastcgi_split(r, f, flcf) != NGX_OK) {
+    f = ngx_http_fastcgi_split(r, flcf);
+
+    if (f == NULL) {
         return NGX_ERROR;
     }
 
@@ -2168,35 +2170,46 @@ ngx_http_fastcgi_path_info_variable(ngx_
 }
 
 
-static ngx_int_t
-ngx_http_fastcgi_split(ngx_http_request_t *r, ngx_http_fastcgi_ctx_t *f,
-    ngx_http_fastcgi_loc_conf_t *flcf)
+static ngx_http_fastcgi_ctx_t *
+ngx_http_fastcgi_split(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf)
 {
+    ngx_http_fastcgi_ctx_t       *f;
 #if (NGX_PCRE)
-    ngx_int_t  n;
-    int        captures[(1 + 2) * 3];
+    ngx_int_t                     n;
+    int                           captures[(1 + 2) * 3];
+
+    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
+
+    if (f == NULL) {
+        f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
+        if (f == NULL) {
+            return NULL;
+        }
+
+        ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
+    }
 
     if (f->script_name.len) {
-        return NGX_OK;
+        return f;
     }
 
     if (flcf->split_regex == NULL) {
         f->script_name = r->uri;
-        return NGX_OK;
+        return f;
     }
 
     n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3);
 
     if (n == NGX_REGEX_NO_MATCHED) {
         f->script_name = r->uri;
-        return NGX_OK;
+        return f;
     }
 
     if (n < 0) {
         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                       ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
                       n, &r->uri, &flcf->split_name);
-        return NGX_ERROR;
+        return NULL;
     }
 
     /* match */
@@ -2207,13 +2220,24 @@ ngx_http_fastcgi_split(ngx_http_request_
     f->path_info.len = captures[5] - captures[4];
     f->path_info.data = r->uri.data + f->script_name.len;
 
-    return NGX_OK;
+    return f;
 
 #else
 
+    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
+
+    if (f == NULL) {
+        f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
+        if (f == NULL) {
+            return NULL;
+        }
+
+        ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
+    }
+
     f->script_name = r->uri;
 
-    return NGX_OK;
+    return f;
 
 #endif
 }
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -636,8 +636,8 @@ ngx_http_geo_add_range(ngx_conf_t *cf, n
 
                 range = a->elts;
 
-                ngx_memcpy(&range[i + 2], &range[i + 1],
-                           (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t));
+                ngx_memcpy(&range[i + 1], &range[i],
+                           (a->nelts - 1 - i) * sizeof(ngx_http_geo_range_t));
 
                 range[i + 1].start = (u_short) (e + 1);
 
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -302,18 +302,18 @@ ngx_http_gzip_body_filter(ngx_http_reque
     if (ctx->buffering) {
 
         if (in) {
-	    switch (ngx_http_gzip_filter_copy_recycled(ctx, in)) {
+            switch (ngx_http_gzip_filter_copy_recycled(ctx, in)) {
 
-	    case NGX_OK:
-		return NGX_OK;
+            case NGX_OK:
+                return NGX_OK;
 
-	    case NGX_DONE:
-		in = NULL;
-		break;
+            case NGX_DONE:
+                in = NULL;
+                break;
 
-	    default:  /* NGX_ERROR */
-		goto failed;
-	    }
+            default:  /* NGX_ERROR */
+                goto failed;
+            }
 
         } else {
             ctx->buffering = 0;
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -96,7 +96,7 @@ static ngx_int_t
 ngx_http_index_handler(ngx_http_request_t *r)
 {
     u_char                       *p, *name;
-    size_t                        len, nlen, root, allocated;
+    size_t                        len, root, reserve, allocated;
     ngx_int_t                     rc;
     ngx_str_t                     path, uri;
     ngx_uint_t                    i, dir_tested;
@@ -128,6 +128,7 @@ ngx_http_index_handler(ngx_http_request_
     root = 0;
     dir_tested = 0;
     name = NULL;
+    /* suppress MSVC warning */
     path.data = NULL;
 
     index = ilcf->indices->elts;
@@ -139,8 +140,8 @@ ngx_http_index_handler(ngx_http_request_
                 return ngx_http_internal_redirect(r, &index[i].name, &r->args);
             }
 
-            len = ilcf->max_index_len;
-            nlen = index[i].name.len;
+            reserve = ilcf->max_index_len;
+            len = index[i].name.len;
 
         } else {
             ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
@@ -149,8 +150,7 @@ ngx_http_index_handler(ngx_http_request_
             e.request = r;
             e.flushed = 1;
 
-            /* 1 byte for terminating '\0' */
-
+            /* 1 is for terminating '\0' as in static names */
             len = 1;
 
             while (*(uintptr_t *) e.ip) {
@@ -158,21 +158,19 @@ ngx_http_index_handler(ngx_http_request_
                 len += lcode(&e);
             }
 
-            nlen = len;
-
             /* 16 bytes are preallocation */
 
-            len += 16;
+            reserve = len + 16;
         }
 
-        if (len > (size_t) (path.data + allocated - name)) {
+        if (reserve > allocated) {
 
-            name = ngx_http_map_uri_to_path(r, &path, &root, len);
+            name = ngx_http_map_uri_to_path(r, &path, &root, reserve);
             if (name == NULL) {
                 return NGX_ERROR;
             }
 
-            allocated = path.len;
+            allocated = path.data + path.len - name;
         }
 
         if (index[i].values == NULL) {
@@ -193,7 +191,7 @@ ngx_http_index_handler(ngx_http_request_
             }
 
             if (*name == '/') {
-                uri.len = nlen - 1;
+                uri.len = len - 1;
                 uri.data = name;
                 return ngx_http_internal_redirect(r, &uri, &r->args);
             }
@@ -248,7 +246,7 @@ ngx_http_index_handler(ngx_http_request_
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
 
-        uri.len = r->uri.len + nlen - 1;
+        uri.len = r->uri.len + len - 1;
 
         if (!clcf->alias) {
             uri.data = path.data + root;
@@ -260,7 +258,7 @@ ngx_http_index_handler(ngx_http_request_
             }
 
             p = ngx_copy(uri.data, r->uri.data, r->uri.len);
-            ngx_memcpy(p, name, nlen - 1);
+            ngx_memcpy(p, name, len - 1);
         }
 
         return ngx_http_internal_redirect(r, &uri, &r->args);
@@ -491,7 +489,7 @@ ngx_http_index_set_index(ngx_conf_t *cf,
                 continue;
             }
 
-            /* include the terminating '\0' to the length to use ngx_copy() */
+            /* include the terminating '\0' to the length to use ngx_memcpy() */
             index->name.len++;
 
             continue;
--- 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.7.31';
+our $VERSION = '0.7.33';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1034,10 +1034,10 @@ ngx_int_t
 ngx_http_core_try_files_phase(ngx_http_request_t *r,
     ngx_http_phase_handler_t *ph)
 {
-    size_t                        len, root, alias;
-    ssize_t                       reserve, allocated;
+    size_t                        len, root, alias, reserve, allocated;
     u_char                       *p, *name;
     ngx_str_t                     path;
+    ngx_uint_t                    test_dir;
     ngx_http_try_file_t          *tf;
     ngx_open_file_info_t          of;
     ngx_http_script_code_pt       code;
@@ -1058,7 +1058,7 @@ ngx_http_core_try_files_phase(ngx_http_r
     allocated = 0;
     root = 0;
     name = NULL;
-    path.len = 0;
+    /* suppress MSVC warning */
     path.data = NULL;
 
     tf = clcf->try_files;
@@ -1133,6 +1133,8 @@ ngx_http_core_try_files_phase(ngx_http_r
             }
         }
 
+        test_dir = tf->test_dir;
+
         tf++;
 
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -1172,7 +1174,7 @@ ngx_http_core_try_files_phase(ngx_http_r
             continue;
         }
 
-        if (!of.is_file) {
+        if (of.is_dir && !test_dir) {
             continue;
         }
 
@@ -3853,6 +3855,11 @@ ngx_http_core_try_files(ngx_conf_t *cf, 
 
         tf[i].name = value[i + 1];
 
+        if (tf[i].name.data[tf[i].name.len - 1] == '/') {
+            tf[i].test_dir = 1;
+            tf[i].name.len--;
+        }
+
         n = ngx_http_script_variables_count(&tf[i].name);
 
         if (n) {
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -245,6 +245,7 @@ typedef struct {
     ngx_array_t               *lengths;
     ngx_array_t               *values;
     ngx_str_t                  name;
+    ngx_uint_t                 test_dir;   /* unsigned  test_dir:1; */
 } ngx_http_try_file_t;
 
 
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -2185,6 +2185,7 @@ ngx_http_set_keepalive(ngx_http_request_
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
 
     if (r->discard_body) {
+        r->write_event_handler = ngx_http_request_empty_handler;
         r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
         ngx_add_timer(rev, clcf->lingering_timeout);
         return;
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -2217,7 +2217,7 @@ ngx_http_upstream_process_request(ngx_ht
 
             tf = u->pipe->temp_file;
 
-            if (p->upstream_eof) {
+            if (p->upstream_eof || p->upstream_done) {
 
                 if (u->headers_in.status_n == NGX_HTTP_OK
                     && (u->headers_in.content_length_n == -1
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -69,6 +69,8 @@ static ngx_int_t ngx_http_variable_sent_
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_sent_content_length(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_sent_location(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_sent_connection(ngx_http_request_t *r,
@@ -210,6 +212,9 @@ static ngx_http_variable_t  ngx_http_cor
     { ngx_string("sent_http_content_length"), NULL,
       ngx_http_variable_sent_content_length, 0, 0, 0 },
 
+    { ngx_string("sent_http_location"), NULL,
+      ngx_http_variable_sent_location, 0, 0, 0 },
+
     { ngx_string("sent_http_last_modified"), NULL,
       ngx_http_variable_sent_last_modified, 0, 0, 0 },
 
@@ -1242,6 +1247,26 @@ ngx_http_variable_sent_content_length(ng
 
 
 static ngx_int_t
+ngx_http_variable_sent_location(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    if (r->headers_out.location) {
+        v->len = r->headers_out.location->value.len;
+        v->valid = 1;
+        v->no_cacheable = 0;
+        v->not_found = 0;
+        v->data = r->headers_out.location->value.data;
+
+        return NGX_OK;
+    }
+
+    return ngx_http_variable_unknown_header(v, (ngx_str_t *) data,
+                                            &r->headers_out.headers.part,
+                                            sizeof("sent_http_") - 1);
+}
+
+
+static ngx_int_t
 ngx_http_variable_sent_last_modified(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -12,6 +12,7 @@
 
 
 static void ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx);
+static void ngx_mail_smtp_resolve_name(ngx_event_t *rev);
 static void ngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx);
 static void ngx_mail_smtp_greeting(ngx_mail_session_t *s, ngx_connection_t *c);
 static void ngx_mail_smtp_invalid_pipelining(ngx_event_t *rev);
@@ -91,9 +92,8 @@ ngx_mail_smtp_init_session(ngx_mail_sess
 static void
 ngx_mail_smtp_resolve_addr_handler(ngx_resolver_ctx_t *ctx)
 {
-    ngx_connection_t          *c;
-    ngx_mail_session_t        *s;
-    ngx_mail_core_srv_conf_t  *cscf;
+    ngx_connection_t    *c;
+    ngx_mail_session_t  *s;
 
     s = ctx->data;
     c = s->connection;
@@ -134,6 +134,23 @@ ngx_mail_smtp_resolve_addr_handler(ngx_r
     ngx_log_debug1(NGX_LOG_DEBUG_MAIL, c->log, 0,
                    "address resolved: %V", &s->host);
 
+    c->read->handler = ngx_mail_smtp_resolve_name;
+
+    ngx_post_event(c->read, &ngx_posted_events);
+}
+
+
+static void
+ngx_mail_smtp_resolve_name(ngx_event_t *rev)
+{
+    ngx_connection_t          *c;
+    ngx_mail_session_t        *s;
+    ngx_resolver_ctx_t        *ctx;
+    ngx_mail_core_srv_conf_t  *cscf;
+
+    c = rev->data;
+    s = c->data;
+
     cscf = ngx_mail_get_module_srv_conf(s, ngx_mail_core_module);
 
     ctx = ngx_resolve_start(cscf->resolver, NULL);