From 06296dd5e75fb93733623bce519a8efda52871fe Mon Sep 17 00:00:00 2001 From: Martin Nagy Date: Wed, 13 Jan 2010 19:42:21 +0100 Subject: Make sure callbacks never retry when ares channel is destroyed When the resolv context destructor is invoked, the callbacks for pending queries could have been called with ARES_EDESTRUCTION and try to re-send the query. --- server/resolv/async_resolv.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/server/resolv/async_resolv.c b/server/resolv/async_resolv.c index ff84b386..0be79185 100644 --- a/server/resolv/async_resolv.c +++ b/server/resolv/async_resolv.c @@ -272,6 +272,8 @@ fd_event_close(struct resolv_ctx *ctx, int s) static int resolv_ctx_destructor(struct resolv_ctx *ctx) { + ares_channel channel; + DLIST_REMOVE(context_list, ctx); if (ctx->channel == NULL) { @@ -279,8 +281,11 @@ resolv_ctx_destructor(struct resolv_ctx *ctx) return -1; } - ares_destroy(ctx->channel); + /* Set ctx->channel to NULL first, so that callbacks that get + * ARES_EDESTRUCTION won't retry. */ + channel = ctx->channel; ctx->channel = NULL; + ares_destroy(channel); return 0; } @@ -489,7 +494,8 @@ resolv_gethostbyname_done(void *arg, int status, int timeouts, struct hostent *h struct tevent_req *req = talloc_get_type(arg, struct tevent_req); struct gethostbyname_state *state = tevent_req_data(req, struct gethostbyname_state); - if (state->retrying == 0 && status == ARES_EDESTRUCTION) { + if (state->retrying == 0 && status == ARES_EDESTRUCTION + && state->resolv_ctx->channel != NULL) { state->retrying = 1; ares_gethostbyname(state->resolv_ctx->channel, state->name, state->family, resolv_gethostbyname_done, req); @@ -692,7 +698,8 @@ resolv_getsrv_done(void *arg, int status, int timeouts, unsigned char *abuf, int int ret; struct ares_srv_reply *reply_list; - if (state->retrying == 0 && status == ARES_EDESTRUCTION) { + if (state->retrying == 0 && status == ARES_EDESTRUCTION + && state->resolv_ctx->channel != NULL) { state->retrying = 1; ares_query(state->resolv_ctx->channel, state->query, ns_c_in, ns_t_srv, resolv_getsrv_done, req); @@ -895,7 +902,8 @@ resolv_gettxt_done(void *arg, int status, int timeouts, unsigned char *abuf, int int ret; struct ares_txt_reply *reply_list; - if (state->retrying == 0 && status == ARES_EDESTRUCTION) { + if (state->retrying == 0 && status == ARES_EDESTRUCTION + && state->resolv_ctx->channel != NULL) { state->retrying = 1; ares_query(state->resolv_ctx->channel, state->query, ns_c_in, ns_t_txt, resolv_gettxt_done, req); -- cgit