retry isc_nm_udpconnect() if it fails

On FreeBSD, we sometimes see spurious transient EADDRINUSE errors
when connecting to a UDP socket. We now try a few times to ensure
the error is real before giving up.

This commit also fixes a memory leak that occurred if an error was
encountered in isc__nm_async_udpconnect().
This commit is contained in:
Evan Hunt
2020-09-28 13:31:38 -07:00
parent 0efb8864bf
commit cdf3e5b04e
2 changed files with 15 additions and 10 deletions

View File

@@ -2918,7 +2918,8 @@ static void
start_udp(dig_query_t *query) {
dig_lookup_t *l = NULL;
isc_result_t result;
dig_query_t *next;
dig_query_t *next = NULL;
int i = 0;
REQUIRE(DIG_VALID_QUERY(query));
@@ -2971,9 +2972,16 @@ start_udp(dig_query_t *query) {
}
}
result = isc_nm_udpconnect(netmgr, (isc_nmiface_t *)&localaddr,
(isc_nmiface_t *)&query->sockaddr, udp_ready,
query, 0);
do {
/*
* On FreeBSD the UDP connect() call sometimes results
* in a spurious transient EADDRINUSE. Try a few more times
* before giving up.
*/
result = isc_nm_udpconnect(netmgr, (isc_nmiface_t *)&localaddr,
(isc_nmiface_t *)&query->sockaddr,
udp_ready, query, 0);
} while (result != ISC_R_SUCCESS && i++ < 2);
check_result(result, "isc_nm_udpconnect");
}

View File

@@ -607,7 +607,6 @@ isc__nm_async_udpconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
uv_udp_init(&worker->loop, &sock->uv_handle.udp);
uv_handle_set_data(&sock->uv_handle.handle, NULL);
uv_handle_set_data(&sock->uv_handle.handle, sock);
handle = isc__nmhandle_get(sock, &ievent->peer, &sock->iface->addr);
r = uv_udp_open(&sock->uv_handle.udp, sock->fd);
if (r != 0) {
@@ -654,16 +653,17 @@ isc__nm_async_udpconnect(isc__networker_t *worker, isc__netievent_t *ev0) {
atomic_store(&sock->connected, true);
sock->result = ISC_R_SUCCESS;
done:
cb = sock->connect_cb;
cbarg = sock->connect_cbarg;
handle = isc__nmhandle_get(sock, &ievent->peer, &sock->iface->addr);
cb(handle, sock->result, cbarg);
LOCK(&sock->lock);
SIGNAL(&sock->cond);
UNLOCK(&sock->lock);
done:
isc__nmsocket_detach(&sock);
}
@@ -743,10 +743,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_nmiface_t *local, isc_nmiface_t *peer,
UNLOCK(&sock->lock);
}
if (sock->result != ISC_R_SUCCESS) {
result = sock->result;
isc__nmsocket_detach(&sock);
}
sock->result = result;
isc__nmsocket_detach(&tmp);