diff --git a/CHANGES b/CHANGES index 93d5f4c452..6c87beb8e9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +5173. [bug] Fixed a race in socket code that could occur when + accept, send, or recv were called from an event + loop but the socket had been closed by another + thread. [RT #874] + 5172. [bug] nsupdate now honors the operating system's preferred ephemeral port range. [GL #905] diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index 4a3365cb47..00ea6a27cf 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -2816,6 +2816,11 @@ internal_accept(isc__socket_t *sock) { INSIST(VALID_SOCKET(sock)); LOCK(&sock->lock); + if (sock->fd < 0) { + /* Socket is gone */ + UNLOCK(&sock->lock); + return; + } socket_log(sock, NULL, TRACE, "internal_accept called, locked socket"); @@ -3051,6 +3056,11 @@ internal_recv(isc__socket_t *sock) { INSIST(VALID_SOCKET(sock)); LOCK(&sock->lock); + if (sock->fd < 0) { + /* Socket is gone */ + UNLOCK(&sock->lock); + return; + } dev = ISC_LIST_HEAD(sock->recv_list); if (dev == NULL) { goto finish; @@ -3105,6 +3115,11 @@ internal_send(isc__socket_t *sock) { INSIST(VALID_SOCKET(sock)); LOCK(&sock->lock); + if (sock->fd < 0) { + /* Socket is gone */ + UNLOCK(&sock->lock); + return; + } dev = ISC_LIST_HEAD(sock->send_list); if (dev == NULL) { goto finish;