From: Miroslav Lichvar Date: Mon, 12 Dec 2016 08:58:56 +0000 (+0100) Subject: stubs: rework emulation of asynchronous resolver to use pipes X-Git-Tag: 3.0-pre2~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0c9a19ded56ed893aab02e1f62ca259236bdf6e0;p=thirdparty%2Fchrony.git 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. --- diff --git a/stubs.c b/stubs.c index 9bc127cb..f3ce4bb4 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 */