From 0c9a19ded56ed893aab02e1f62ca259236bdf6e0 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Mon, 12 Dec 2016 09:58:56 +0100 Subject: [PATCH] stubs: rework emulation of asynchronous resolver to use pipes With a larger number of configured servers, the handler of the emulated resolver repeatedly scheduled timeout of zero, which triggered the infinite loop detection in the scheduler and caused abort. This bug was introduced in commit 967e358dbc93aa7a99c3c0ee2a634f1fedecba74. Rework the code to use pipes instead of timeouts to avoid this problem. --- stubs.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/stubs.c b/stubs.c index 9bc127c..f3ce4bb 100644 --- a/stubs.c +++ b/stubs.c @@ -42,6 +42,7 @@ #include "privops.h" #include "refclock.h" #include "sched.h" +#include "util.h" #ifndef FEAT_ASYNCDNS @@ -51,10 +52,11 @@ struct DNS_Async_Instance { const char *name; DNS_NameResolveHandler handler; void *arg; + int pipe[2]; }; static void -resolve_name(void *anything) +resolve_name(int fd, int event, void *anything) { struct DNS_Async_Instance *inst; IPAddr addrs[DNS_MAX_ADDRESSES]; @@ -62,6 +64,11 @@ resolve_name(void *anything) int i; inst = (struct DNS_Async_Instance *)anything; + + SCH_RemoveFileHandler(inst->pipe[0]); + close(inst->pipe[0]); + close(inst->pipe[1]); + status = PRV_Name2IPAddress(inst->name, addrs, DNS_MAX_ADDRESSES); for (i = 0; status == DNS_Success && i < DNS_MAX_ADDRESSES && @@ -83,7 +90,16 @@ DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void * inst->handler = handler; inst->arg = anything; - SCH_AddTimeoutByDelay(0.0, resolve_name, inst); + if (pipe(inst->pipe)) + LOG_FATAL(LOGF_Nameserv, "pipe() failed"); + + UTI_FdSetCloexec(inst->pipe[0]); + UTI_FdSetCloexec(inst->pipe[1]); + + SCH_AddFileHandler(inst->pipe[0], SCH_FILE_INPUT, resolve_name, inst); + + if (write(inst->pipe[1], "", 1) < 0) + ; } #endif /* !FEAT_ASYNCDNS */