diff -upr nginx-1.9.7-old/src/core/ngx_resolver.c nginx-1.9.7/src/core/ngx_resolver.c --- nginx-1.9.7-old/src/core/ngx_resolver.c 2016-01-26 11:54:55.915406799 -0800 +++ nginx-1.9.7/src/core/ngx_resolver.c 2016-01-26 11:55:27.067782268 -0800 @@ -59,15 +59,15 @@ ngx_int_t ngx_udp_connect(ngx_udp_connec static void ngx_resolver_cleanup(void *data); static void ngx_resolver_cleanup_tree(ngx_resolver_t *r, ngx_rbtree_t *tree); static ngx_int_t ngx_resolve_name_locked(ngx_resolver_t *r, - ngx_resolver_ctx_t *ctx); + ngx_resolver_ctx_t *ctx, ngx_str_t *name); static void ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue); static ngx_int_t ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn); -static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_node_t *rn, - ngx_resolver_ctx_t *ctx); -static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, - ngx_resolver_ctx_t *ctx); +static ngx_int_t ngx_resolver_create_name_query(ngx_resolver_t *r, + ngx_resolver_node_t *rn, ngx_str_t *name); +static ngx_int_t ngx_resolver_create_addr_query(ngx_resolver_t *r, + ngx_resolver_node_t *rn, ngx_addr_t *addr); static void ngx_resolver_resend_handler(ngx_event_t *ev); static time_t ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue); @@ -376,7 +376,7 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx /* lock name mutex */ - rc = ngx_resolve_name_locked(r, ctx); + rc = ngx_resolve_name_locked(r, ctx, &ctx->name); if (rc == NGX_OK) { return NGX_OK; @@ -403,7 +403,6 @@ ngx_resolve_name(ngx_resolver_ctx_t *ctx void ngx_resolve_name_done(ngx_resolver_ctx_t *ctx) { - uint32_t hash; ngx_resolver_t *r; ngx_resolver_ctx_t *w, **p; ngx_resolver_node_t *rn; @@ -423,11 +422,9 @@ ngx_resolve_name_done(ngx_resolver_ctx_t /* lock name mutex */ - if (ctx->state == NGX_AGAIN) { - - hash = ngx_crc32_short(ctx->name.data, ctx->name.len); + if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { - rn = ngx_resolver_lookup_name(r, &ctx->name, hash); + rn = ctx->node; if (rn) { p = &rn->waiting; @@ -472,23 +469,28 @@ done: static ngx_int_t -ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx) +ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx, + ngx_str_t *name) { uint32_t hash; ngx_int_t rc; + ngx_str_t cname; ngx_uint_t naddrs; ngx_addr_t *addrs; - ngx_resolver_ctx_t *next; + ngx_resolver_ctx_t *next, *last; ngx_resolver_node_t *rn; - ngx_strlow(ctx->name.data, ctx->name.data, ctx->name.len); + ngx_strlow(name->data, name->data, name->len); - hash = ngx_crc32_short(ctx->name.data, ctx->name.len); + hash = ngx_crc32_short(name->data, name->len); - rn = ngx_resolver_lookup_name(r, &ctx->name, hash); + rn = ngx_resolver_lookup_name(r, name, hash); if (rn) { + /* ctx can be a list after NGX_RESOLVE_CNAME */ + for (last = ctx; last->next; last = last->next); + if (rn->valid >= ngx_time()) { ngx_log_debug0(NGX_LOG_DEBUG_CORE, r->log, 0, "resolve cached"); @@ -516,7 +518,7 @@ ngx_resolve_name_locked(ngx_resolver_t * } } - ctx->next = rn->waiting; + last->next = rn->waiting; rn->waiting = NULL; /* unlock name mutex */ @@ -556,13 +558,13 @@ ngx_resolve_name_locked(ngx_resolver_t * if (ctx->recursion++ < NGX_RESOLVER_MAX_RECURSION) { - ctx->name.len = rn->cnlen; - ctx->name.data = rn->u.cname; + cname.len = rn->cnlen; + cname.data = rn->u.cname; - return ngx_resolve_name_locked(r, ctx); + return ngx_resolve_name_locked(r, ctx, &cname); } - ctx->next = rn->waiting; + last->next = rn->waiting; rn->waiting = NULL; /* unlock name mutex */ @@ -581,10 +583,29 @@ ngx_resolve_name_locked(ngx_resolver_t * if (rn->waiting) { - ctx->next = rn->waiting; + if (ctx->event == NULL) { + ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); + if (ctx->event == NULL) { + return NGX_ERROR; + } + + ctx->event->handler = ngx_resolver_timeout_handler; + ctx->event->data = ctx; + ctx->event->log = r->log; + ctx->ident = -1; + + ngx_add_timer(ctx->event, ctx->timeout); + } + + last->next = rn->waiting; rn->waiting = ctx; ctx->state = NGX_AGAIN; + do { + ctx->node = rn; + ctx = ctx->next; + } while (ctx); + return NGX_AGAIN; } @@ -623,14 +644,14 @@ ngx_resolve_name_locked(ngx_resolver_t * return NGX_ERROR; } - rn->name = ngx_resolver_dup(r, ctx->name.data, ctx->name.len); + rn->name = ngx_resolver_dup(r, name->data, name->len); if (rn->name == NULL) { ngx_resolver_free(r, rn); return NGX_ERROR; } rn->node.key = hash; - rn->nlen = (u_short) ctx->name.len; + rn->nlen = (u_short) name->len; rn->query = NULL; #if (NGX_HAVE_INET6) rn->query6 = NULL; @@ -639,7 +660,7 @@ ngx_resolve_name_locked(ngx_resolver_t * ngx_rbtree_insert(&r->name_rbtree, &rn->node); } - rc = ngx_resolver_create_name_query(rn, ctx); + rc = ngx_resolver_create_name_query(r, rn, name); if (rc == NGX_ERROR) { goto failed; @@ -652,8 +673,14 @@ ngx_resolve_name_locked(ngx_resolver_t * ngx_resolver_free(r, rn->name); ngx_resolver_free(r, rn); - ctx->state = NGX_RESOLVE_NXDOMAIN; - ctx->handler(ctx); + do { + ctx->state = NGX_RESOLVE_NXDOMAIN; + next = ctx->next; + + ctx->handler(ctx); + + ctx = next; + } while (ctx); return NGX_OK; } @@ -674,9 +701,9 @@ ngx_resolve_name_locked(ngx_resolver_t * } ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = rn; + ctx->event->data = ctx; ctx->event->log = r->log; - rn->ident = -1; + ctx->ident = -1; ngx_add_timer(ctx->event, ctx->timeout); } @@ -697,6 +724,11 @@ ngx_resolve_name_locked(ngx_resolver_t * ctx->state = NGX_AGAIN; + do { + ctx->node = rn; + ctx = ctx->next; + } while (ctx); + return NGX_AGAIN; failed: @@ -804,9 +836,22 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx if (rn->waiting) { + ctx->event = ngx_resolver_calloc(r, sizeof(ngx_event_t)); + if (ctx->event == NULL) { + return NGX_ERROR; + } + + ctx->event->handler = ngx_resolver_timeout_handler; + ctx->event->data = ctx; + ctx->event->log = r->log; + ctx->ident = -1; + + ngx_add_timer(ctx->event, ctx->timeout); + ctx->next = rn->waiting; rn->waiting = ctx; ctx->state = NGX_AGAIN; + ctx->node = rn; /* unlock addr mutex */ @@ -848,7 +893,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx ngx_rbtree_insert(tree, &rn->node); } - if (ngx_resolver_create_addr_query(rn, ctx) != NGX_OK) { + if (ngx_resolver_create_addr_query(r, rn, &ctx->addr) != NGX_OK) { goto failed; } @@ -867,9 +912,9 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx } ctx->event->handler = ngx_resolver_timeout_handler; - ctx->event->data = rn; + ctx->event->data = ctx; ctx->event->log = r->log; - rn->ident = -1; + ctx->ident = -1; ngx_add_timer(ctx->event, ctx->timeout); @@ -892,6 +937,7 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx /* unlock addr mutex */ ctx->state = NGX_AGAIN; + ctx->node = rn; return NGX_OK; @@ -922,17 +968,11 @@ failed: void ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx) { - in_addr_t addr; ngx_queue_t *expire_queue; ngx_rbtree_t *tree; ngx_resolver_t *r; ngx_resolver_ctx_t *w, **p; - struct sockaddr_in *sin; ngx_resolver_node_t *rn; -#if (NGX_HAVE_INET6) - uint32_t hash; - struct sockaddr_in6 *sin6; -#endif r = ctx->resolver; @@ -959,23 +999,9 @@ ngx_resolve_addr_done(ngx_resolver_ctx_t /* lock addr mutex */ - if (ctx->state == NGX_AGAIN) { - - switch (ctx->addr.sockaddr->sa_family) { - -#if (NGX_HAVE_INET6) - case AF_INET6: - sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr; - hash = ngx_crc32_short(sin6->sin6_addr.s6_addr, 16); - rn = ngx_resolver_lookup_addr6(r, &sin6->sin6_addr, hash); - break; -#endif + if (ctx->state == NGX_AGAIN || ctx->state == NGX_RESOLVE_TIMEDOUT) { - default: /* AF_INET */ - sin = (struct sockaddr_in *) ctx->addr.sockaddr; - addr = ntohl(sin->sin_addr.s_addr); - rn = ngx_resolver_lookup_addr(r, addr); - } + rn = ctx->node; if (rn) { p = &rn->waiting; @@ -1312,7 +1338,7 @@ ngx_resolver_process_response(ngx_resolv times = 0; for (q = ngx_queue_head(&r->name_resend_queue); - q != ngx_queue_sentinel(&r->name_resend_queue) || times++ < 100; + q != ngx_queue_sentinel(&r->name_resend_queue) && times++ < 100; q = ngx_queue_next(q)) { rn = ngx_queue_data(q, ngx_resolver_node_t, queue); @@ -1975,20 +2001,39 @@ ngx_resolver_process_a(ngx_resolver_t *r ngx_queue_insert_head(&r->name_expire_queue, &rn->queue); + ngx_resolver_free(r, rn->query); + rn->query = NULL; +#if (NGX_HAVE_INET6) + rn->query6 = NULL; +#endif + ctx = rn->waiting; rn->waiting = NULL; if (ctx) { - ctx->name = name; - (void) ngx_resolve_name_locked(r, ctx); - } + if (ctx->recursion++ >= NGX_RESOLVER_MAX_RECURSION) { - ngx_resolver_free(r, rn->query); - rn->query = NULL; -#if (NGX_HAVE_INET6) - rn->query6 = NULL; -#endif + /* unlock name mutex */ + + do { + ctx->state = NGX_RESOLVE_NXDOMAIN; + next = ctx->next; + + ctx->handler(ctx); + + ctx = next; + } while (ctx); + + return; + } + + for (next = ctx; next; next = next->next) { + next->node = NULL; + } + + (void) ngx_resolve_name_locked(r, ctx, &name); + } /* unlock name mutex */ @@ -2496,27 +2541,23 @@ ngx_resolver_rbtree_insert_addr6_value(n static ngx_int_t -ngx_resolver_create_name_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) +ngx_resolver_create_name_query(ngx_resolver_t *r, ngx_resolver_node_t *rn, + ngx_str_t *name) { u_char *p, *s; size_t len, nlen; ngx_uint_t ident; -#if (NGX_HAVE_INET6) - ngx_resolver_t *r; -#endif ngx_resolver_qs_t *qs; ngx_resolver_hdr_t *query; - nlen = ctx->name.len ? (1 + ctx->name.len + 1) : 1; + nlen = name->len ? (1 + name->len + 1) : 1; len = sizeof(ngx_resolver_hdr_t) + nlen + sizeof(ngx_resolver_qs_t); #if (NGX_HAVE_INET6) - r = ctx->resolver; - - p = ngx_resolver_alloc(ctx->resolver, r->ipv6 ? len * 2 : len); + p = ngx_resolver_alloc(r, r->ipv6 ? len * 2 : len); #else - p = ngx_resolver_alloc(ctx->resolver, len); + p = ngx_resolver_alloc(r, len); #endif if (p == NULL) { return NGX_ERROR; @@ -2535,8 +2576,8 @@ ngx_resolver_create_name_query(ngx_resol ident = ngx_random(); - ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, - "resolve: \"%V\" A %i", &ctx->name, ident & 0xffff); + ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0, + "resolve: \"%V\" A %i", name, ident & 0xffff); query->ident_hi = (u_char) ((ident >> 8) & 0xff); query->ident_lo = (u_char) (ident & 0xff); @@ -2566,11 +2607,11 @@ ngx_resolver_create_name_query(ngx_resol p--; *p-- = '\0'; - if (ctx->name.len == 0) { + if (name->len == 0) { return NGX_DECLINED; } - for (s = ctx->name.data + ctx->name.len - 1; s >= ctx->name.data; s--) { + for (s = name->data + name->len - 1; s >= name->data; s--) { if (*s != '.') { *p = *s; len++; @@ -2606,8 +2647,8 @@ ngx_resolver_create_name_query(ngx_resol ident = ngx_random(); - ngx_log_debug2(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, - "resolve: \"%V\" AAAA %i", &ctx->name, ident & 0xffff); + ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0, + "resolve: \"%V\" AAAA %i", name, ident & 0xffff); query->ident_hi = (u_char) ((ident >> 8) & 0xff); query->ident_lo = (u_char) (ident & 0xff); @@ -2624,11 +2665,12 @@ ngx_resolver_create_name_query(ngx_resol static ngx_int_t -ngx_resolver_create_addr_query(ngx_resolver_node_t *rn, ngx_resolver_ctx_t *ctx) +ngx_resolver_create_addr_query(ngx_resolver_t *r, ngx_resolver_node_t *rn, + ngx_addr_t *addr) { u_char *p, *d; size_t len; - in_addr_t addr; + in_addr_t inaddr; ngx_int_t n; ngx_uint_t ident; ngx_resolver_hdr_t *query; @@ -2637,7 +2679,7 @@ ngx_resolver_create_addr_query(ngx_resol struct sockaddr_in6 *sin6; #endif - switch (ctx->addr.sockaddr->sa_family) { + switch (addr->sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: @@ -2654,7 +2696,7 @@ ngx_resolver_create_addr_query(ngx_resol + sizeof(ngx_resolver_qs_t); } - p = ngx_resolver_alloc(ctx->resolver, len); + p = ngx_resolver_alloc(r, len); if (p == NULL) { return NGX_ERROR; } @@ -2678,11 +2720,11 @@ ngx_resolver_create_addr_query(ngx_resol p += sizeof(ngx_resolver_hdr_t); - switch (ctx->addr.sockaddr->sa_family) { + switch (addr->sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: - sin6 = (struct sockaddr_in6 *) ctx->addr.sockaddr; + sin6 = (struct sockaddr_in6 *) addr->sockaddr; for (n = 15; n >= 0; n--) { p = ngx_sprintf(p, "\1%xd\1%xd", @@ -2697,11 +2739,11 @@ ngx_resolver_create_addr_query(ngx_resol default: /* AF_INET */ - sin = (struct sockaddr_in *) ctx->addr.sockaddr; - addr = ntohl(sin->sin_addr.s_addr); + sin = (struct sockaddr_in *) addr->sockaddr; + inaddr = ntohl(sin->sin_addr.s_addr); for (n = 0; n < 32; n += 8) { - d = ngx_sprintf(&p[1], "%ud", (addr >> n) & 0xff); + d = ngx_sprintf(&p[1], "%ud", (inaddr >> n) & 0xff); *p = (u_char) (d - &p[1]); p = d; } @@ -2815,21 +2857,13 @@ done: static void ngx_resolver_timeout_handler(ngx_event_t *ev) { - ngx_resolver_ctx_t *ctx, *next; - ngx_resolver_node_t *rn; + ngx_resolver_ctx_t *ctx; - rn = ev->data; - ctx = rn->waiting; - rn->waiting = NULL; + ctx = ev->data; - do { - ctx->state = NGX_RESOLVE_TIMEDOUT; - next = ctx->next; - - ctx->handler(ctx); + ctx->state = NGX_RESOLVE_TIMEDOUT; - ctx = next; - } while (ctx); + ctx->handler(ctx); } diff -upr nginx-1.9.7-old/src/core/ngx_resolver.h nginx-1.9.7/src/core/ngx_resolver.h --- nginx-1.9.7-old/src/core/ngx_resolver.h 2016-01-26 11:54:55.914404751 -0800 +++ nginx-1.9.7/src/core/ngx_resolver.h 2016-01-26 11:55:27.068784001 -0800 @@ -51,15 +51,11 @@ typedef void (*ngx_resolver_handler_pt)( typedef struct { - /* PTR: resolved name, A: name to resolve */ - u_char *name; - + ngx_rbtree_node_t node; ngx_queue_t queue; - /* event ident must be after 3 pointers as in ngx_connection_t */ - ngx_int_t ident; - - ngx_rbtree_node_t node; + /* PTR: resolved name, A: name to resolve */ + u_char *name; #if (NGX_HAVE_INET6) /* PTR: IPv6 address to resolve (IPv4 address is in rbtree node key) */ @@ -147,6 +143,9 @@ struct ngx_resolver_ctx_s { ngx_resolver_t *resolver; ngx_udp_connection_t *udp_connection; + /* event ident must be after 3 pointers as in ngx_connection_t */ + ngx_int_t ident; + ngx_int_t state; ngx_str_t name; @@ -162,6 +161,8 @@ struct ngx_resolver_ctx_s { ngx_uint_t quick; /* unsigned quick:1; */ ngx_uint_t recursion; ngx_event_t *event; + + ngx_resolver_node_t *node; };