isc_nmsocket_t *sock;
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 local;
isc_nm_opaquecb_t doreset; /* reset extra callback, external */
* or, for child sockets, 'sock->parent->active'.
*/
+void
+isc__nmsocket_clearcb(isc_nmsocket_t *sock);
+/*%<
+ * Clear the recv and accept callbacks in 'sock'.
+ */
+
void
isc__nm_async_closecb(isc__networker_t *worker, isc__netievent_t *ev0);
/*%<
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
isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
isc_nmsocket_t *sock = uv_handle_get_data(handle);
if (sock->rcb.recv != NULL) {
sock->rcb.recv(sock->tcphandle, ISC_R_TIMEDOUT, NULL,
sock->rcbarg);
+ isc__nmsocket_clearcb(sock);
}
}
isc__netievent_startread_t *ievent = NULL;
REQUIRE(VALID_NMSOCK(sock));
- REQUIRE(sock->rcb.recv != NULL);
+ if (sock->rcb.recv == NULL) {
+ return (ISC_R_CANCELED);
+ }
if (!atomic_load(&sock->readpaused)) {
return (ISC_R_SUCCESS);
if (sock->rcb.recv != NULL) {
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_RECVFAIL]);
sock->rcb.recv(sock->tcphandle, ISC_R_EOF, NULL, sock->rcbarg);
+ isc__nmsocket_clearcb(sock);
}
/*
{
sock->rcb.recv(sock->tcphandle, ISC_R_CANCELED, NULL,
sock->rcbarg);
+ isc__nmsocket_clearcb(sock);
}
}
{
sock->rcb.recv(sock->tcphandle, ISC_R_CANCELED, NULL,
sock->rcbarg);
+ isc__nmsocket_clearcb(sock);
}
}
if (dnssock->self != NULL) {
isc__nmsocket_detach(&dnssock->self);
}
+ isc__nmsocket_clearcb(dnssock);
+ if (dnssock->outerhandle != NULL) {
+ isc_nmhandle_unref(dnssock->outerhandle);
+ dnssock->outerhandle = NULL;
+ }
return;
}
atomic_store(&sock->listening, false);
atomic_store(&sock->closed, true);
- sock->rcb.recv = NULL;
- sock->rcbarg = NULL;
+ isc__nmsocket_clearcb(sock);
if (sock->outer != NULL) {
isc__nm_tcp_stoplistening(sock->outer);
}
isc_nmhandle_unref(handle);
} 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;
REQUIRE(sock->tid == isc_nm_tid());
/* 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,
* it will then call us again (via detach) so that we
sock->timer_initialized = false;
uv_timer_stop(&sock->timer);
uv_close((uv_handle_t *)&sock->timer, timer_close_cb);
- } else if (sock->self != NULL) {
- isc__nmsocket_detach(&sock->self);
} else {
/*
* At this point we're certain that there are no external
* references, we can close everything.
*/
if (sock->outerhandle != NULL) {
- sock->outerhandle->sock->rcb.recv = NULL;
+ isc__nmsocket_clearcb(sock->outerhandle->sock);
isc_nmhandle_unref(sock->outerhandle);
sock->outerhandle = NULL;
}