diff --git a/CHANGES b/CHANGES index 53bf0b65f4..335b9b2b02 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +5238. [bug] Fix a possible deadlock in TCP code. [GL #1046] + 5237. [bug] Recurse to find the root server list with 'dig +trace'. [GL #1028] diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index d62af359d5..fe187028c2 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -2977,6 +2977,13 @@ internal_accept(isc__socket_t *sock) { NEWCONNSOCK(dev)->connected = 1; nthread = &manager->threads[NEWCONNSOCK(dev)->threadid]; + /* + * We already hold a lock on one fdlock in accepting thread, + * we need to make sure that we don't double lock. + */ + bool same_bucket = (sock->threadid == NEWCONNSOCK(dev)->threadid) && + (FDLOCK_ID(sock->fd) == lockid); + /* * Use minimum mtu if possible. */ @@ -2999,13 +3006,17 @@ internal_accept(isc__socket_t *sock) { NEWCONNSOCK(dev)->active = 1; } - LOCK(&nthread->fdlock[lockid]); + if (!same_bucket) { + LOCK(&nthread->fdlock[lockid]); + } nthread->fds[fd] = NEWCONNSOCK(dev); nthread->fdstate[fd] = MANAGED; #if defined(USE_EPOLL) nthread->epoll_events[fd] = 0; #endif - UNLOCK(&nthread->fdlock[lockid]); + if (!same_bucket) { + UNLOCK(&nthread->fdlock[lockid]); + } LOCK(&manager->lock);