Skip to content

Commit caf6150

Browse files
committed
Use async name resolving to improve net thread responsiveness
In the LookupIntern(), things changed are: 1. Call getaddrinfo_a() instead of getaddrinfo() if available, the former is a sync version of the latter; 2. Try using inet_pton()/inet_addr() to convert the input text to a network addr structure at first, if success the extra name resolving thread inside getaddrinfo_a() could be avoided; 3. An interruption point added in the waiting loop for return from getaddrinfo_a(), which completes the improve for thread responsiveness. A easy way to see the effect is to kick off a 'bitcoind stop' immediately after 'bitcoind -daemon', before the change it would take several, or even tens of, minutes on a bad network situation to wait for the running bitcoind to exit, now it costs only seconds. Signed-off-by: Huang Le <[email protected]>
1 parent 236ae86 commit caf6150

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

configure.ac

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,8 @@ if test x$TARGET_OS = xdarwin; then
369369
fi
370370

371371
AC_CHECK_HEADERS([endian.h stdio.h stdlib.h unistd.h strings.h sys/types.h sys/stat.h sys/select.h])
372+
AC_SEARCH_LIBS([getaddrinfo_a], [anl], [AC_DEFINE(HAVE_GETADDRINFO_A, 1, [Define this symbol if you have getaddrinfo_a])])
373+
AC_SEARCH_LIBS([inet_pton], [nsl resolv], [AC_DEFINE(HAVE_INET_PTON, 1, [Define this symbol if you have inet_pton])])
372374

373375
AC_CHECK_DECLS([le32toh, le64toh, htole32, htole64, be32toh, be64toh, htobe32, htobe64],,,
374376
[#if HAVE_ENDIAN_H

src/netbase.cpp

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33
// Distributed under the MIT/X11 software license, see the accompanying
44
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
55

6+
#ifdef HAVE_CONFIG_H
7+
#include "bitcoin-config.h"
8+
#endif
9+
10+
#ifdef HAVE_INET_PTON
11+
#include <arpa/inet.h>
12+
#endif
13+
14+
#ifdef HAVE_GETADDRINFO_A
15+
#include <netdb.h>
16+
#endif
17+
618
#include "netbase.h"
719

820
#include "hash.h"
@@ -71,9 +83,30 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
7183
}
7284
}
7385

86+
#ifdef HAVE_GETADDRINFO_A
87+
struct in_addr ipv4_addr;
88+
#ifdef HAVE_INET_PTON
89+
if (inet_pton(AF_INET, pszName, &ipv4_addr) > 0) {
90+
vIP.push_back(CNetAddr(ipv4_addr));
91+
return true;
92+
}
93+
94+
struct in6_addr ipv6_addr;
95+
if (inet_pton(AF_INET6, pszName, &ipv6_addr) > 0) {
96+
vIP.push_back(CNetAddr(ipv6_addr));
97+
return true;
98+
}
99+
#else
100+
ipv4_addr.s_addr = inet_addr(pszName);
101+
if (ipv4_addr.s_addr != INADDR_NONE) {
102+
vIP.push_back(CNetAddr(ipv4_addr));
103+
return true;
104+
}
105+
#endif
106+
#endif
107+
74108
struct addrinfo aiHint;
75109
memset(&aiHint, 0, sizeof(struct addrinfo));
76-
77110
aiHint.ai_socktype = SOCK_STREAM;
78111
aiHint.ai_protocol = IPPROTO_TCP;
79112
aiHint.ai_family = AF_UNSPEC;
@@ -82,8 +115,33 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
82115
#else
83116
aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
84117
#endif
118+
85119
struct addrinfo *aiRes = NULL;
120+
#ifdef HAVE_GETADDRINFO_A
121+
struct gaicb gcb, *query = &gcb;
122+
memset(query, 0, sizeof(struct gaicb));
123+
gcb.ar_name = pszName;
124+
gcb.ar_request = &aiHint;
125+
int nErr = getaddrinfo_a(GAI_NOWAIT, &query, 1, NULL);
126+
if (nErr)
127+
return false;
128+
129+
do {
130+
// Should set the timeout limit to a resonable value to avoid
131+
// generating unnecessary checking call during the polling loop,
132+
// while it can still response to stop request quick enough.
133+
// 2 seconds looks fine in our situation.
134+
struct timespec ts = { 2, 0 };
135+
gai_suspend(&query, 1, &ts);
136+
boost::this_thread::interruption_point();
137+
138+
nErr = gai_error(query);
139+
if (0 == nErr)
140+
aiRes = query->ar_result;
141+
} while (nErr == EAI_INPROGRESS);
142+
#else
86143
int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
144+
#endif
87145
if (nErr)
88146
return false;
89147

0 commit comments

Comments
 (0)