}
/*%
- * 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;
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);
}
}
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;
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.
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);
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.
}
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);