Merge branch '2226-tsan-error-in-dispatch-c' into 'main'

Resolve "TSAN error in dispatch.c accessing disp->portentry"

Closes #2226

See merge request isc-projects/bind9!4286
This commit is contained in:
Mark Andrews 2020-10-23 20:08:43 +00:00
commit f8de3df76c

View file

@ -619,11 +619,10 @@ new_portentry(dns_dispatch_t *disp, in_port_t port) {
}
/*%
* The caller must not hold the qid->lock.
* The caller must hold the qid->lock.
*/
static void
deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
dns_qid_t *qid;
dispportentry_t *portentry = *portentryp;
*portentryp = NULL;
@ -631,13 +630,10 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) {
REQUIRE(portentry != NULL);
if (isc_refcount_decrement(&portentry->refs) == 1) {
qid = DNS_QID(disp);
LOCK(&qid->lock);
ISC_LIST_UNLINK(disp->port_table[portentry->port %
DNS_DISPATCH_PORTTABLESIZE],
portentry, link);
isc_mempool_put(disp->portpool, portentry);
UNLOCK(&qid->lock);
}
}
@ -777,9 +773,9 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
if (result == ISC_R_SUCCESS) {
dispsock->socket = sock;
dispsock->host = *dest;
dispsock->portentry = portentry;
dispsock->bucket = bucket;
LOCK(&qid->lock);
dispsock->portentry = portentry;
ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink);
UNLOCK(&qid->lock);
*dispsockp = dispsock;
@ -805,7 +801,7 @@ get_dispsocket(dns_dispatch_t *disp, const isc_sockaddr_t *dest,
static void
destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
dispsocket_t *dispsock;
dns_qid_t *qid;
dns_qid_t *qid = DNS_QID(disp);
/*
* The dispatch must be locked.
@ -819,13 +815,15 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
disp->nsockets--;
dispsock->magic = 0;
if (dispsock->portentry != NULL) {
/* socket_search() tests and dereferences portentry. */
LOCK(&qid->lock);
deref_portentry(disp, &dispsock->portentry);
UNLOCK(&qid->lock);
}
if (dispsock->socket != NULL) {
isc_socket_detach(&dispsock->socket);
}
if (ISC_LINK_LINKED(dispsock, blink)) {
qid = DNS_QID(disp);
LOCK(&qid->lock);
ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock,
blink);
@ -844,7 +842,7 @@ destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
static void
deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
isc_result_t result;
dns_qid_t *qid;
dns_qid_t *qid = DNS_QID(disp);
/*
* The dispatch must be locked.
@ -856,14 +854,16 @@ deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
}
INSIST(dispsock->portentry != NULL);
/* socket_search() tests and dereferences portentry. */
LOCK(&qid->lock);
deref_portentry(disp, &dispsock->portentry);
UNLOCK(&qid->lock);
if (disp->nsockets > DNS_DISPATCH_POOLSOCKS) {
destroy_dispsocket(disp, &dispsock);
} else {
result = isc_socket_close(dispsock->socket);
qid = DNS_QID(disp);
LOCK(&qid->lock);
ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock,
blink);