mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 14:35:26 +00:00
clean up outerhandle when a tcpdns socket is disconnected
this prevents a crash when some non-netmgr thread, such as a recursive lookup, times out after the TCP socket is already disconnected.
This commit is contained in:
@@ -98,14 +98,6 @@ struct isc_nmhandle {
|
|||||||
isc_nmsocket_t *sock;
|
isc_nmsocket_t *sock;
|
||||||
size_t ah_pos; /* Position in the socket's 'active handles' array */
|
size_t ah_pos; /* Position in the socket's 'active handles' array */
|
||||||
|
|
||||||
/*
|
|
||||||
* The handle is 'inflight' if netmgr is not currently processing
|
|
||||||
* it in any way - it might mean that e.g. a recursive resolution
|
|
||||||
* is happening. For an inflight handle we must wait for the
|
|
||||||
* calling code to finish before we can free it.
|
|
||||||
*/
|
|
||||||
atomic_bool inflight;
|
|
||||||
|
|
||||||
isc_sockaddr_t peer;
|
isc_sockaddr_t peer;
|
||||||
isc_sockaddr_t local;
|
isc_sockaddr_t local;
|
||||||
isc_nm_opaquecb_t doreset; /* reset extra callback, external */
|
isc_nm_opaquecb_t doreset; /* reset extra callback, external */
|
||||||
@@ -650,6 +642,12 @@ isc__nmsocket_active(isc_nmsocket_t *sock);
|
|||||||
* or, for child sockets, 'sock->parent->active'.
|
* or, for child sockets, 'sock->parent->active'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nmsocket_clearcb(isc_nmsocket_t *sock);
|
||||||
|
/*%<
|
||||||
|
* Clear the recv and accept callbacks in 'sock'.
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_async_closecb(isc__networker_t *worker, isc__netievent_t *ev0);
|
isc__nm_async_closecb(isc__networker_t *worker, isc__netievent_t *ev0);
|
||||||
/*%<
|
/*%<
|
||||||
|
@@ -987,6 +987,16 @@ isc__nmsocket_init(isc_nmsocket_t *sock, isc_nm_t *mgr, isc_nmsocket_type type,
|
|||||||
sock->magic = NMSOCK_MAGIC;
|
sock->magic = NMSOCK_MAGIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
isc__nmsocket_clearcb(isc_nmsocket_t *sock) {
|
||||||
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
|
|
||||||
|
sock->rcb.recv = NULL;
|
||||||
|
sock->rcbarg = NULL;
|
||||||
|
sock->accept_cb.accept = NULL;
|
||||||
|
sock->accept_cbarg = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
|
isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
|
||||||
isc_nmsocket_t *sock = uv_handle_get_data(handle);
|
isc_nmsocket_t *sock = uv_handle_get_data(handle);
|
||||||
|
@@ -584,6 +584,7 @@ readtimeout_cb(uv_timer_t *handle) {
|
|||||||
if (sock->rcb.recv != NULL) {
|
if (sock->rcb.recv != NULL) {
|
||||||
sock->rcb.recv(sock->tcphandle, ISC_R_TIMEDOUT, NULL,
|
sock->rcb.recv(sock->tcphandle, ISC_R_TIMEDOUT, NULL,
|
||||||
sock->rcbarg);
|
sock->rcbarg);
|
||||||
|
isc__nmsocket_clearcb(sock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,7 +683,9 @@ isc__nm_tcp_resumeread(isc_nmsocket_t *sock) {
|
|||||||
isc__netievent_startread_t *ievent = NULL;
|
isc__netievent_startread_t *ievent = NULL;
|
||||||
|
|
||||||
REQUIRE(VALID_NMSOCK(sock));
|
REQUIRE(VALID_NMSOCK(sock));
|
||||||
REQUIRE(sock->rcb.recv != NULL);
|
if (sock->rcb.recv == NULL) {
|
||||||
|
return (ISC_R_CANCELED);
|
||||||
|
}
|
||||||
|
|
||||||
if (!atomic_load(&sock->readpaused)) {
|
if (!atomic_load(&sock->readpaused)) {
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
@@ -744,6 +747,7 @@ read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {
|
|||||||
if (sock->rcb.recv != NULL) {
|
if (sock->rcb.recv != NULL) {
|
||||||
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_RECVFAIL]);
|
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_RECVFAIL]);
|
||||||
sock->rcb.recv(sock->tcphandle, ISC_R_EOF, NULL, sock->rcbarg);
|
sock->rcb.recv(sock->tcphandle, ISC_R_EOF, NULL, sock->rcbarg);
|
||||||
|
isc__nmsocket_clearcb(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1080,6 +1084,7 @@ isc__nm_tcp_shutdown(isc_nmsocket_t *sock) {
|
|||||||
{
|
{
|
||||||
sock->rcb.recv(sock->tcphandle, ISC_R_CANCELED, NULL,
|
sock->rcb.recv(sock->tcphandle, ISC_R_CANCELED, NULL,
|
||||||
sock->rcbarg);
|
sock->rcbarg);
|
||||||
|
isc__nmsocket_clearcb(sock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1092,5 +1097,6 @@ isc__nm_tcp_cancelread(isc_nmsocket_t *sock) {
|
|||||||
{
|
{
|
||||||
sock->rcb.recv(sock->tcphandle, ISC_R_CANCELED, NULL,
|
sock->rcb.recv(sock->tcphandle, ISC_R_CANCELED, NULL,
|
||||||
sock->rcbarg);
|
sock->rcbarg);
|
||||||
|
isc__nmsocket_clearcb(sock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -231,6 +231,11 @@ dnslisten_readcb(isc_nmhandle_t *handle, isc_result_t eresult,
|
|||||||
if (dnssock->self != NULL) {
|
if (dnssock->self != NULL) {
|
||||||
isc__nmsocket_detach(&dnssock->self);
|
isc__nmsocket_detach(&dnssock->self);
|
||||||
}
|
}
|
||||||
|
isc__nmsocket_clearcb(dnssock);
|
||||||
|
if (dnssock->outerhandle != NULL) {
|
||||||
|
isc_nmhandle_unref(dnssock->outerhandle);
|
||||||
|
dnssock->outerhandle = NULL;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,8 +345,7 @@ isc__nm_tcpdns_stoplistening(isc_nmsocket_t *sock) {
|
|||||||
|
|
||||||
atomic_store(&sock->listening, false);
|
atomic_store(&sock->listening, false);
|
||||||
atomic_store(&sock->closed, true);
|
atomic_store(&sock->closed, true);
|
||||||
sock->rcb.recv = NULL;
|
isc__nmsocket_clearcb(sock);
|
||||||
sock->rcbarg = NULL;
|
|
||||||
|
|
||||||
if (sock->outer != NULL) {
|
if (sock->outer != NULL) {
|
||||||
isc__nm_tcp_stoplistening(sock->outer);
|
isc__nm_tcp_stoplistening(sock->outer);
|
||||||
@@ -431,7 +435,11 @@ resume_processing(void *arg) {
|
|||||||
}
|
}
|
||||||
isc_nmhandle_unref(handle);
|
isc_nmhandle_unref(handle);
|
||||||
} else if (sock->outerhandle != NULL) {
|
} else if (sock->outerhandle != NULL) {
|
||||||
isc_nm_resumeread(sock->outerhandle->sock);
|
result = isc_nm_resumeread(sock->outerhandle->sock);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
isc_nmhandle_unref(sock->outerhandle);
|
||||||
|
sock->outerhandle = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -524,7 +532,9 @@ tcpdns_close_direct(isc_nmsocket_t *sock) {
|
|||||||
REQUIRE(sock->tid == isc_nm_tid());
|
REQUIRE(sock->tid == isc_nm_tid());
|
||||||
|
|
||||||
/* We don't need atomics here, it's all in single network thread */
|
/* We don't need atomics here, it's all in single network thread */
|
||||||
if (sock->timer_initialized) {
|
if (sock->self != NULL) {
|
||||||
|
isc__nmsocket_detach(&sock->self);
|
||||||
|
} else if (sock->timer_initialized) {
|
||||||
/*
|
/*
|
||||||
* We need to fire the timer callback to clean it up,
|
* We need to fire the timer callback to clean it up,
|
||||||
* it will then call us again (via detach) so that we
|
* it will then call us again (via detach) so that we
|
||||||
@@ -533,15 +543,13 @@ tcpdns_close_direct(isc_nmsocket_t *sock) {
|
|||||||
sock->timer_initialized = false;
|
sock->timer_initialized = false;
|
||||||
uv_timer_stop(&sock->timer);
|
uv_timer_stop(&sock->timer);
|
||||||
uv_close((uv_handle_t *)&sock->timer, timer_close_cb);
|
uv_close((uv_handle_t *)&sock->timer, timer_close_cb);
|
||||||
} else if (sock->self != NULL) {
|
|
||||||
isc__nmsocket_detach(&sock->self);
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* At this point we're certain that there are no external
|
* At this point we're certain that there are no external
|
||||||
* references, we can close everything.
|
* references, we can close everything.
|
||||||
*/
|
*/
|
||||||
if (sock->outerhandle != NULL) {
|
if (sock->outerhandle != NULL) {
|
||||||
sock->outerhandle->sock->rcb.recv = NULL;
|
isc__nmsocket_clearcb(sock->outerhandle->sock);
|
||||||
isc_nmhandle_unref(sock->outerhandle);
|
isc_nmhandle_unref(sock->outerhandle);
|
||||||
sock->outerhandle = NULL;
|
sock->outerhandle = NULL;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user