Closes #16778
Bitcoin uses getaddrinfo to make DNS requests for DNS seed servers and for adding peers with -addnode, -seednode and -connect. Depending on the platform this can be clunky and a system issue could prevent name resolution from completing at all, blocking the thread and in some cases preventing a clean shutdown.
An attempt was made to switch to the asynchronous getaddrinfo_a in #4421 but that was reverted in #9229 after discovering that function has a segfault!
Taking BlueMatt's suggestion in #10215#issue-221886328, this PR modifies our g_dns_lookup function to use evdns_getaddrinfo() from libevent. This is an asynchronous function but I've implemented it in a polling loop so it still blocks -- but now will timeout after 2 seconds.
TODO:
- We could make the polling loop interruptible but I'm not sure the best approach to that, since these functions don't live in a class with a flag like
interruptNet - Is it possible to add functional tests that mess with DNS? Probably not.
- The unit test I added makes a live DNS request for
nic.comthat test will fail the platform has no DNS
Future work:
- libevent has more low-level DNS functions as well, we could ultimately use those to (for example) request
TXTrecords with onion addresses from our DNS seeders