mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-02 15:45:25 +00:00
Fix a possible deadlock in TCP accepting
Each network thread holds an array of locks, indexed by a hash of fd. When we accept a connection we hold a lock in accepting thread. We then generate the thread number and lock bucket for the new connection socket - if we hit the same thread and lock bucket as accepting socket we get a deadlock. Avoid this by checking if we're in the same thread/lock bucket and not locking in this case.
This commit is contained in:
committed by
Witold Krecicki
parent
4d498b3dac
commit
75815c1581
2
CHANGES
2
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'.
|
5237. [bug] Recurse to find the root server list with 'dig +trace'.
|
||||||
[GL #1028]
|
[GL #1028]
|
||||||
|
|
||||||
|
@@ -2977,6 +2977,13 @@ internal_accept(isc__socket_t *sock) {
|
|||||||
NEWCONNSOCK(dev)->connected = 1;
|
NEWCONNSOCK(dev)->connected = 1;
|
||||||
nthread = &manager->threads[NEWCONNSOCK(dev)->threadid];
|
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.
|
* Use minimum mtu if possible.
|
||||||
*/
|
*/
|
||||||
@@ -2999,13 +3006,17 @@ internal_accept(isc__socket_t *sock) {
|
|||||||
NEWCONNSOCK(dev)->active = 1;
|
NEWCONNSOCK(dev)->active = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!same_bucket) {
|
||||||
LOCK(&nthread->fdlock[lockid]);
|
LOCK(&nthread->fdlock[lockid]);
|
||||||
|
}
|
||||||
nthread->fds[fd] = NEWCONNSOCK(dev);
|
nthread->fds[fd] = NEWCONNSOCK(dev);
|
||||||
nthread->fdstate[fd] = MANAGED;
|
nthread->fdstate[fd] = MANAGED;
|
||||||
#if defined(USE_EPOLL)
|
#if defined(USE_EPOLL)
|
||||||
nthread->epoll_events[fd] = 0;
|
nthread->epoll_events[fd] = 0;
|
||||||
#endif
|
#endif
|
||||||
|
if (!same_bucket) {
|
||||||
UNLOCK(&nthread->fdlock[lockid]);
|
UNLOCK(&nthread->fdlock[lockid]);
|
||||||
|
}
|
||||||
|
|
||||||
LOCK(&manager->lock);
|
LOCK(&manager->lock);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user