diff --git a/src/tests/resolver/fallback.vtc b/src/tests/resolver/fallback.vtc new file mode 100644 index 0000000..8764593 --- /dev/null +++ b/src/tests/resolver/fallback.vtc @@ -0,0 +1,27 @@ +varnishtest "falling back from a resolver to getaddrinfo" + +server s1 { + rxreq + txresp +} -start + +varnish v1 -vcl+backend { + import ${vmod_dynamic}; + + sub vcl_init { + new r1 = dynamic.resolver(); + new d1 = dynamic.director( + resolver = r1.use()); + d1.debug(true); + } + + sub vcl_recv { + set req.backend_hint = d1.backend(host = "img.localhost", port = "${s1_port}"); + } +} -start + +client c1 { + txreq + rxresp + expect resp.status == 200 +} -run diff --git a/src/vmod_dynamic.c b/src/vmod_dynamic.c index d9bfdb5..066af12 100644 --- a/src/vmod_dynamic.c +++ b/src/vmod_dynamic.c @@ -775,6 +775,7 @@ dom_lookup_thread(void *priv) struct vrt_ctx ctx; vtim_real lookup, results, update; const struct res_cb *res; + struct vmod_dynamic_resolver *res_instance; void *res_priv = NULL; int ret; @@ -783,49 +784,63 @@ dom_lookup_thread(void *priv) obj = dom->obj; res = obj->resolver; + res_instance = obj->resolver_inst; Lck_Lock(&dom->mtx); assert(dom->status == DYNAMIC_ST_STARTING); while (dom->status <= DYNAMIC_ST_ACTIVE) { Lck_Unlock(&dom->mtx); - lookup = VTIM_real(); - if (lookup > dom->expires) { - Lck_Lock(&obj->domains_mtx); + while (1) { // Loop run at most twice: one for the resolve, and one for the fallaback gai resolver + lookup = VTIM_real(); if (lookup > dom->expires) { - LOG(NULL, SLT_VCL_Log, dom, "%s", "timeout"); - dom->expires = HUGE_VAL; - VRBT_REMOVE(dom_tree_head, &obj->ref_domains, - dom); - VTAILQ_INSERT_TAIL(&obj->unref_domains, dom, - link.list); + Lck_Lock(&obj->domains_mtx); + if (lookup > dom->expires) { + LOG(NULL, SLT_VCL_Log, dom, "%s", "timeout"); + dom->expires = HUGE_VAL; + VRBT_REMOVE(dom_tree_head, &obj->ref_domains, + dom); + VTAILQ_INSERT_TAIL(&obj->unref_domains, dom, + link.list); + } + Lck_Unlock(&obj->domains_mtx); } - Lck_Unlock(&obj->domains_mtx); - } - dynamic_timestamp(dom, "Lookup", lookup, 0., 0.); + dynamic_timestamp(dom, "Lookup", lookup, 0., 0.); - ret = res->lookup(obj->resolver_inst, dom->addr, - dom_port(dom), &res_priv); + ret = res->lookup(res_instance, dom->addr, + dom_port(dom), &res_priv); - results = VTIM_real(); - dynamic_timestamp(dom, "Results", results, results - lookup, - results - lookup); + results = VTIM_real(); + dynamic_timestamp(dom, "Results", results, results - lookup, + results - lookup); - if (ret == 0) { - dom_update(dom, res, res_priv, results); - update = VTIM_real(); - dynamic_timestamp(dom, "Update", update, - update - lookup, update - results); - } else { - LOG(&ctx, SLT_Error, dom, "%s %d (%s)", - res->name, ret, res->strerror(ret)); - dom->deadline = results + obj->retry_after; - dbg_res_details(NULL, dom->obj, res, res_priv); - } + if (ret == 0) { + dom_update(dom, res, res_priv, results); + update = VTIM_real(); + dynamic_timestamp(dom, "Update", update, + update - lookup, update - results); + } else { + LOG(&ctx, SLT_Error, dom, "%s %d (%s)", + res->name, ret, res->strerror(ret)); + dbg_res_details(NULL, dom->obj, res, res_priv); + } + + res->fini(&res_priv); + AZ(res_priv); - res->fini(&res_priv); - AZ(res_priv); + if (ret == 0) { + break; + } + if (res == &res_gai) { + /* Failed with fallback getaddrinfo resolver: update deadline with default TTL and break */ + dom->deadline = results + obj->retry_after; + break; + } + /* Failed with custom resolver: try again with fallback getaddrinfo resolver */ + res = &res_gai; + res_instance = NULL; + } Lck_Lock(&dom->mtx); diff --git a/src/vmod_dynamic.vcc b/src/vmod_dynamic.vcc index f534934..b166b11 100644 --- a/src/vmod_dynamic.vcc +++ b/src/vmod_dynamic.vcc @@ -306,6 +306,9 @@ Parameters: The argument to the *resolver* parameter must be the return value of the `xresolver.use()`_ method. + If the resolver does not find any addresses, a fallback + attempt to resolve the address without the resolver is made. + .. _ttl_from: - *ttl_from*