- The read timer must always be stopped when reading stops.
- Read callbacks can now call isc_nm_read() again in TCP, TCPDNS and
TLSDNS; previously this caused an assertion.
- The wrong failure code could be sent after a UDP recv failure because
the if statements were in the wrong order. the check for a NULL
address needs to be after the check for an error code, otherwise the
result will always be set to ISC_R_EOF.
- When aborting a read or connect because the netmgr is shutting down,
use ISC_R_SHUTTINGDOWN. (ISC_R_CANCELED is now reserved for when the
read has been canceled by the caller.)
- A new function isc_nmhandle_timer_running() has been added enabling a
callback to check whether the timer has been reset after processing a
timeout.
- Incidental netmgr fix: always use isc__nm_closing() instead of
referencing sock->mgr->closing directly
- Corrected a few comments that used outdated function names.
return (!session->closed && !session->closing);
}
-static bool
-inactive(isc_nmsocket_t *sock) {
- return (!isc__nmsocket_active(sock) || atomic_load(&sock->closing) ||
- atomic_load(&sock->mgr->closing) ||
- (sock->server != NULL && !isc__nmsocket_active(sock->server)));
-}
-
static void *
http_malloc(size_t sz, isc_mem_t *mctx) {
return (isc_mem_allocate(mctx, sz));
}
isc__nmsocket_clearcb(sock);
- isc__nm_connectcb(sock, req, ISC_R_CANCELED, true);
+ isc__nm_connectcb(sock, req, ISC_R_SHUTTINGDOWN, true);
isc__nmsocket_prep_destroy(sock);
isc__nmsocket_detach(&sock);
return;
isc_result_t result = ISC_R_SUCCESS;
isc_nm_cb_t cb = req->cb.send;
void *cbarg = req->cbarg;
- if (inactive(sock) || !http_session_active(handle->httpsession)) {
+ if (isc__nmsocket_closing(sock) ||
+ !http_session_active(handle->httpsession)) {
failed_send_cb(sock, req, ISC_R_CANCELED);
return;
}
* function gets invoked, so we need to do extra sanity checks to
* detect this case.
*/
- if (inactive(handle->sock) || httpserver == NULL) {
+ if (isc__nmsocket_closing(handle->sock) || httpserver == NULL) {
return (ISC_R_CANCELED);
}
REQUIRE(VALID_NMSOCK(httplistensock));
INSIST(httplistensock == httpserver);
- if (inactive(httplistensock) ||
- !atomic_load(&httplistensock->listening)) {
+ if (isc__nmsocket_closing(httplistensock) ||
+ !atomic_load(&httplistensock->listening))
+ {
return (ISC_R_CANCELED);
}
REQUIRE(handle->sock->type == isc_nm_httpsocket);
sock = handle->sock;
- if (sock->h2.session != NULL && sock->h2.session->handle) {
+ if (sock->h2.session != NULL && sock->h2.session->handle != NULL) {
INSIST(VALID_HTTP2_SESSION(sock->h2.session));
INSIST(VALID_NMHANDLE(sock->h2.session->handle));
isc_nmhandle_cleartimeout(sock->h2.session->handle);
REQUIRE(handle->sock->type == isc_nm_httpsocket);
sock = handle->sock;
- if (sock->h2.session != NULL && sock->h2.session->handle) {
+ if (sock->h2.session != NULL && sock->h2.session->handle != NULL) {
INSIST(VALID_HTTP2_SESSION(sock->h2.session));
INSIST(VALID_NMHANDLE(sock->h2.session->handle));
isc_nmhandle_settimeout(sock->h2.session->handle, timeout);
atomic_bool listening;
atomic_bool connecting;
atomic_bool connected;
- bool accepting;
- bool reading;
+ atomic_bool accepting;
+ atomic_bool reading;
isc_refcount_t references;
/*%
void
isc__nm_failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult) {
- REQUIRE(sock->accepting);
+ REQUIRE(atomic_load(&sock->accepting));
REQUIRE(sock->server);
/*
isc__nmsocket_detach(&sock->server);
- sock->accepting = false;
+ atomic_store(&sock->accepting, false);
switch (eresult) {
case ISC_R_NOTCONNECTED:
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(sock->reading);
+ REQUIRE(atomic_load(&sock->reading));
if (atomic_load(&sock->client)) {
uv_timer_stop(timer);
+ sock->recv_read = false;
+
if (sock->recv_cb != NULL) {
isc__nm_uvreq_t *req = isc__nm_get_read_req(sock, NULL);
isc__nm_readcb(sock, req, ISC_R_TIMEDOUT);
isc__nm_start_reading(isc_nmsocket_t *sock) {
int r;
- if (sock->reading) {
+ if (atomic_load(&sock->reading)) {
return;
}
ISC_UNREACHABLE();
}
RUNTIME_CHECK(r == 0);
- sock->reading = true;
+ atomic_store(&sock->reading, true);
}
void
isc__nm_stop_reading(isc_nmsocket_t *sock) {
int r;
- if (!sock->reading) {
+ if (!atomic_load(&sock->reading)) {
return;
}
ISC_UNREACHABLE();
}
RUNTIME_CHECK(r == 0);
- sock->reading = false;
+ atomic_store(&sock->reading, false);
}
bool
bool
isc__nmsocket_closing(isc_nmsocket_t *sock) {
return (!isc__nmsocket_active(sock) || atomic_load(&sock->closing) ||
- atomic_load(&sock->mgr->closing) ||
+ isc__nm_closing(sock) ||
(sock->server != NULL && !isc__nmsocket_active(sock->server)));
}
* Stop reading if this is a client socket, or if the server socket
* has been set to sequential mode, or the number of queries we are
* processing simultaneously has reached the clients-per-connection
- * limit. In this case we'll be called again by resume_processing()
- * later.
+ * limit. In this case we'll be called again later by
+ * isc__nm_resume_processing().
*/
void
isc__nm_process_sock_buffer(isc_nmsocket_t *sock) {
return (ISC_R_NOTIMPLEMENTED);
}
+isc_result_t
+isc_nm_checkaddr(const isc_sockaddr_t *addr, isc_socktype_t type) {
+ int proto, pf, addrlen, fd, r;
+
+ REQUIRE(addr != NULL);
+
+ switch (type) {
+ case isc_socktype_tcp:
+ proto = SOCK_STREAM;
+ break;
+ case isc_socktype_udp:
+ proto = SOCK_DGRAM;
+ break;
+ default:
+ return (ISC_R_NOTIMPLEMENTED);
+ }
+
+ pf = isc_sockaddr_pf(addr);
+ if (pf == AF_INET) {
+ addrlen = sizeof(struct sockaddr_in);
+ } else {
+ addrlen = sizeof(struct sockaddr_in6);
+ }
+
+ fd = socket(pf, proto, 0);
+ if (fd < 0) {
+ return (isc_errno_toresult(errno));
+ }
+
+ r = bind(fd, (const struct sockaddr *)&addr->type.sa, addrlen);
+ if (r < 0) {
+ close(fd);
+ return (isc_errno_toresult(errno));
+ }
+
+ close(fd);
+ return (ISC_R_SUCCESS);
+}
+
#if defined(TCP_CONNECTIONTIMEOUT)
#define TIMEOUT_TYPE int
#define TIMEOUT_DIV 1000
* We don't want pipelining on this connection. That means
* that we need to pause after reading each request, and
* resume only after the request has been processed. This
- * is done in resume_processing(), which is the socket's
- * closehandle_cb callback, called whenever a handle
+ * is done in isc__nm_resume_processing(), which is the
+ * socket's closehandle_cb callback, called whenever a handle
* is released.
*/
-
isc__nmsocket_timer_stop(sock);
isc__nm_stop_reading(sock);
atomic_store(&sock->sequential, true);
atomic_load(&sock->closing) ? " closing" : "",
atomic_load(&sock->destroying) ? " destroying" : "",
atomic_load(&sock->connecting) ? " connecting" : "",
- sock->accepting ? " accepting" : "");
+ atomic_load(&sock->accepting) ? " accepting" : "");
fprintf(stderr, "Created by:\n");
isc_backtrace_symbols_fd(sock->backtrace, sock->backtrace_size,
STDERR_FILENO);
static void
failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult) {
- REQUIRE(sock->accepting);
+ REQUIRE(atomic_load(&sock->accepting));
REQUIRE(sock->server);
/*
isc__nmsocket_detach(&sock->server);
- sock->accepting = false;
+ atomic_store(&sock->accepting, false);
switch (eresult) {
case ISC_R_NOTCONNECTED:
isc__nm_uvreq_put(&req, sock);
return;
} else if (isc__nmsocket_closing(sock)) {
- /* Socket was closed midflight by isc__nm_tcp_shutdown() */
+ /* Network manager shutting down */
+ result = ISC_R_SHUTTINGDOWN;
+ goto error;
+ } else if (isc__nmsocket_closing(sock)) {
+ /* Connection canceled */
result = ISC_R_CANCELED;
goto error;
} else if (status == UV_ETIMEDOUT) {
REQUIRE(sock->type == isc_nm_tcpsocket);
REQUIRE(sock->statichandle == handle);
- REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(!sock->recv_read);
sock->recv_cb = cb;
sock->recv_cbarg = cbarg;
UNUSED(worker);
if (isc__nmsocket_closing(sock)) {
- sock->reading = true;
+ atomic_store(&sock->reading, true);
isc__nm_tcp_failed_read_cb(sock, ISC_R_CANCELED);
return;
}
}
if (!isc__nmsocket_active(sock)) {
- sock->reading = true;
+ atomic_store(&sock->reading, true);
isc__nm_tcp_failed_read_cb(sock, ISC_R_CANCELED);
return;
}
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(sock->reading);
+ REQUIRE(atomic_load(&sock->reading));
REQUIRE(buf != NULL);
if (isc__nmsocket_closing(sock)) {
isc__nm_readcb(sock, req, ISC_R_SUCCESS);
/* The readcb could have paused the reading */
- if (sock->reading) {
+ if (atomic_load(&sock->reading)) {
/* The timer will be updated */
isc__nmsocket_timer_restart(sock);
}
csock->recv_cb = ssock->recv_cb;
csock->recv_cbarg = ssock->recv_cbarg;
csock->quota = quota;
- csock->accepting = true;
+ atomic_init(&csock->accepting, true);
worker = &csock->mgr->workers[isc_nm_tid()];
goto failure;
}
- csock->accepting = false;
+ atomic_store(&csock->accepting, false);
isc__nm_incstats(csock->mgr, csock->statsindex[STATID_ACCEPT]);
return;
}
- if (sock->accepting) {
+ if (atomic_load(&sock->accepting)) {
return;
}
}
if (sock->statichandle != NULL) {
- isc__nm_tcp_failed_read_cb(sock, ISC_R_CANCELED);
+ if (isc__nm_closing(sock)) {
+ isc__nm_failed_read_cb(sock, ISC_R_SHUTTINGDOWN, false);
+ } else {
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
+ }
return;
}
RUNTIME_CHECK(r == 0);
if (isc__nm_closing(sock)) {
- result = ISC_R_CANCELED;
+ result = ISC_R_SHUTTINGDOWN;
goto error;
}
REQUIRE(VALID_NMHANDLE(req->handle));
if (isc__nmsocket_closing(sock)) {
- /* Socket was closed midflight by isc__nm_tcpdns_shutdown() */
+ /* Network manager shutting down */
+ result = ISC_R_SHUTTINGDOWN;
+ goto error;
+ } else if (isc__nmsocket_closing(sock)) {
+ /* Connection canceled */
result = ISC_R_CANCELED;
goto error;
} else if (status == UV_ETIMEDOUT) {
REQUIRE(sock->type == isc_nm_tcpdnssocket);
REQUIRE(sock->statichandle == handle);
- REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(!sock->recv_read);
sock->recv_cb = cb;
sock->recv_cbarg = cbarg;
REQUIRE(sock->tid == isc_nm_tid());
if (isc__nmsocket_closing(sock)) {
- sock->reading = true;
+ atomic_store(&sock->reading, true);
isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
return;
}
REQUIRE(VALID_UVREQ(req));
/*
- * We need to launch the resume_processing after the buffer has
- * been consumed, thus we need to delay the detaching the handle.
+ * We need to launch isc__nm_resume_processing() after the buffer
+ * has been consumed, thus we must delay detaching the handle.
*/
isc_nmhandle_attach(req->handle, &handle);
sock->recv_read = false;
/*
- * The assertion failure here means that there's a errnoneous extra
- * nmhandle detach happening in the callback and resume_processing gets
- * called while we are still processing the buffer.
+ * An assertion failure here means that there's an erroneous
+ * extra nmhandle detach happening in the callback and
+ * isc__nm_resume_processing() is called while we're
+ * processing the buffer.
*/
REQUIRE(sock->processing == false);
sock->processing = true;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(sock->reading);
+ REQUIRE(atomic_load(&sock->reading));
REQUIRE(buf != NULL);
if (isc__nmsocket_closing(sock)) {
csock->recv_cb = ssock->recv_cb;
csock->recv_cbarg = ssock->recv_cbarg;
csock->quota = quota;
- csock->accepting = true;
+ atomic_init(&csock->accepting, true);
worker = &csock->mgr->workers[csock->tid];
goto failure;
}
- csock->accepting = false;
+ atomic_store(&csock->accepting, false);
isc__nm_incstats(csock->mgr, csock->statsindex[STATID_ACCEPT]);
void
isc__nm_tcpdns_send(isc_nmhandle_t *handle, isc_region_t *region,
isc_nm_cb_t cb, void *cbarg) {
- REQUIRE(VALID_NMHANDLE(handle));
- REQUIRE(VALID_NMSOCK(handle->sock));
-
- isc_nmsocket_t *sock = handle->sock;
isc__netievent_tcpdnssend_t *ievent = NULL;
isc__nm_uvreq_t *uvreq = NULL;
+ isc_nmsocket_t *sock = NULL;
+
+ REQUIRE(VALID_NMHANDLE(handle));
+ sock = handle->sock;
+
+ REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->type == isc_nm_tcpdnssocket);
uvreq = isc__nm_uvreq_get(sock->mgr, sock);
*/
void
isc__nm_async_tcpdnssend(isc__networker_t *worker, isc__netievent_t *ev0) {
+ isc_result_t result;
isc__netievent_tcpdnssend_t *ievent =
(isc__netievent_tcpdnssend_t *)ev0;
+ isc_nmsocket_t *sock = NULL;
+ isc__nm_uvreq_t *uvreq = NULL;
+ int r, nbufs = 2;
+
+ UNUSED(worker);
REQUIRE(VALID_UVREQ(ievent->req));
REQUIRE(VALID_NMSOCK(ievent->sock));
REQUIRE(ievent->sock->type == isc_nm_tcpdnssocket);
REQUIRE(ievent->sock->tid == isc_nm_tid());
- isc_result_t result;
- isc_nmsocket_t *sock = ievent->sock;
- isc__nm_uvreq_t *uvreq = ievent->req;
+ sock = ievent->sock;
+ uvreq = ievent->req;
+
uv_buf_t bufs[2] = { { .base = uvreq->tcplen, .len = 2 },
{ .base = uvreq->uvbuf.base,
.len = uvreq->uvbuf.len } };
- int nbufs = 2;
- int r;
-
- UNUSED(worker);
if (isc__nmsocket_closing(sock)) {
result = ISC_R_CANCELED;
return;
}
- if (sock->accepting) {
+ if (atomic_load(&sock->accepting)) {
return;
}
}
if (sock->statichandle != NULL) {
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
+ if (isc__nm_closing(sock)) {
+ isc__nm_failed_read_cb(sock, ISC_R_SHUTTINGDOWN, false);
+ } else {
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
+ }
return;
}
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
if (isc__nm_closing(sock)) {
- result = ISC_R_CANCELED;
+ result = ISC_R_SHUTTINGDOWN;
goto error;
}
REQUIRE(VALID_NMHANDLE(req->handle));
if (isc__nmsocket_closing(sock)) {
- /* Socket was closed midflight by isc__nm_tlsdns_shutdown() */
+ /* Network manager shutting down */
+ result = ISC_R_SHUTTINGDOWN;
+ goto error;
+ } else if (isc__nmsocket_closing(sock)) {
+ /* Connection canceled */
result = ISC_R_CANCELED;
goto error;
} else if (status == UV_ETIMEDOUT) {
}
if (isc__nm_closing(sock)) {
+ result = ISC_R_SHUTTINGDOWN;
goto failure;
}
BROADCAST(&sock->scond);
UNLOCK(&sock->lock);
return;
+
failure:
if (isc__nm_in_netthread()) {
sock->tid = isc_nm_tid();
REQUIRE(sock->type == isc_nm_tlsdnssocket);
REQUIRE(sock->statichandle == handle);
- REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(!sock->recv_read);
sock->recv_cb = cb;
sock->recv_cbarg = cbarg;
REQUIRE(sock->tid == isc_nm_tid());
if (isc__nmsocket_closing(sock)) {
- sock->reading = true;
+ atomic_store(&sock->reading, true);
isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
return;
}
REQUIRE(VALID_UVREQ(req));
/*
- * We need to launch the resume_processing after the buffer has
- * been consumed, thus we need to delay the detaching the
- * handle.
+ * We need to launch isc__nm_resume_processing() after the buffer
+ * has been consumed, thus we must delay detaching the handle.
*/
isc_nmhandle_attach(req->handle, &handle);
sock->recv_read = false;
/*
- * The assertion failure here means that there's a errnoneous
+ * An assertion failure here means that there's an erroneous
* extra nmhandle detach happening in the callback and
- * resume_processing gets called while we are still processing
- * the buffer.
+ * isc__nm_resume_processing() is called while we're
+ * processing the buffer.
*/
REQUIRE(sock->processing == false);
sock->processing = true;
static void
async_tlsdns_cycle(isc_nmsocket_t *sock) {
+ isc__netievent_tlsdnscycle_t *ievent = NULL;
+
REQUIRE(VALID_NMSOCK(sock));
/* Socket was closed midflight by isc__nm_tlsdns_shutdown() */
return;
}
- isc__netievent_tlsdnscycle_t *ievent =
- isc__nm_get_netievent_tlsdnscycle(sock->mgr, sock);
+ ievent = isc__nm_get_netievent_tlsdnscycle(sock->mgr, sock);
isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
(isc__netievent_t *)ievent);
}
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(sock->reading);
+ REQUIRE(atomic_load(&sock->reading));
REQUIRE(buf != NULL);
if (isc__nmsocket_closing(sock)) {
csock->recv_cb = ssock->recv_cb;
csock->recv_cbarg = ssock->recv_cbarg;
csock->quota = quota;
- csock->accepting = true;
+ atomic_init(&csock->accepting, true);
worker = &csock->mgr->workers[csock->tid];
/* FIXME: Set SSL_MODE_RELEASE_BUFFERS */
- csock->accepting = false;
+ atomic_store(&csock->accepting, false);
isc__nm_incstats(csock->mgr, csock->statsindex[STATID_ACCEPT]);
void
isc__nm_tlsdns_send(isc_nmhandle_t *handle, isc_region_t *region,
isc_nm_cb_t cb, void *cbarg) {
- REQUIRE(VALID_NMHANDLE(handle));
- REQUIRE(VALID_NMSOCK(handle->sock));
-
- isc_nmsocket_t *sock = handle->sock;
isc__netievent_tlsdnssend_t *ievent = NULL;
isc__nm_uvreq_t *uvreq = NULL;
+ isc_nmsocket_t *sock = NULL;
+ REQUIRE(VALID_NMHANDLE(handle));
+
+ sock = handle->sock;
+
+ REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->type == isc_nm_tlsdnssocket);
uvreq = isc__nm_uvreq_get(sock->mgr, sock);
(void)SSL_shutdown(sock->tls.tls);
}
- if (sock->accepting) {
+ if (atomic_load(&sock->accepting)) {
return;
}
/* TLS handshake hasn't been completed yet */
if (atomic_load(&sock->connecting)) {
+ isc_nmsocket_t *tsock = NULL;
+
/*
* TCP connection has been established, now waiting on
* TLS handshake to complete
}
/* The TCP connection hasn't been established yet */
- isc_nmsocket_t *tsock = NULL;
isc__nmsocket_attach(sock, &tsock);
uv_close(&sock->uv_handle.handle, tlsdns_close_connect_cb);
return;
}
if (sock->statichandle != NULL) {
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
+ if (isc__nm_closing(sock)) {
+ isc__nm_failed_read_cb(sock, ISC_R_SHUTTINGDOWN, false);
+ } else {
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
+ }
return;
}
atomic_load(&sock->outerhandle->sock->closing) ||
(sock->listener != NULL &&
!isc__nmsocket_active(sock->listener)) ||
- atomic_load(&sock->mgr->closing));
+ isc__nm_closing(sock));
}
static void
tlssock->iface = handle->sock->iface;
tlssock->peer = handle->sock->peer;
if (isc__nm_closing(tlssock)) {
- result = ISC_R_CANCELED;
+ result = ISC_R_SHUTTINGDOWN;
goto error;
}
isc__nmsocket_init(csock, mgr, isc_nm_udpsocket, iface);
csock->parent = sock;
csock->iface = sock->iface;
- csock->reading = true;
+ atomic_init(&csock->reading, true);
csock->recv_cb = sock->recv_cb;
csock->recv_cbarg = sock->recv_cbarg;
csock->extrahandlesize = sock->extrahandlesize;
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- REQUIRE(sock->reading);
+ REQUIRE(atomic_load(&sock->reading));
#ifdef UV_UDP_MMSG_FREE
free_buf = ((flags & UV_UDP_MMSG_FREE) == UV_UDP_MMSG_FREE);
#endif
/*
- * Three possible reasons to return now without processing:
+ * Four possible reasons to return now without processing:
*/
/*
goto free;
}
+ /*
+ * - If there was a networking error.
+ */
+ if (nrecv < 0) {
+ isc__nm_failed_read_cb(sock, isc__nm_uverr2result(nrecv),
+ false);
+ goto free;
+ }
+
/*
* - If addr == NULL, in which case it's the end of stream;
* we can free the buffer and bail.
goto free;
}
- if (nrecv < 0) {
- isc__nm_failed_read_cb(sock, isc__nm_uverr2result(nrecv),
- false);
- goto free;
- }
-
result = isc_sockaddr_fromsockaddr(&sockaddr, addr);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
RUNTIME_CHECK(r == 0);
uv_handle_set_data((uv_handle_t *)&sock->timer, sock);
+ if (isc__nm_closing(sock)) {
+ result = ISC_R_SHUTTINGDOWN;
+ goto error;
+ }
+
r = uv_udp_open(&sock->uv_handle.udp, sock->fd);
if (r != 0) {
isc__nm_incstats(sock->mgr, sock->statsindex[STATID_OPENFAIL]);
done:
result = isc__nm_uverr2result(r);
+error:
LOCK(&sock->lock);
sock->result = result;
* does not.
*/
if (!sock->parent) {
+ isc__nmsocket_timer_stop(sock);
isc__nm_stop_reading(sock);
}
}
isc__nm_async_udpread(isc__networker_t *worker, isc__netievent_t *ev0) {
isc__netievent_udpread_t *ievent = (isc__netievent_udpread_t *)ev0;
isc_nmsocket_t *sock = ievent->sock;
+ isc_result_t result = ISC_R_SUCCESS;
UNUSED(worker);
REQUIRE(VALID_NMSOCK(sock));
REQUIRE(sock->tid == isc_nm_tid());
- if (isc__nmsocket_closing(sock)) {
- sock->reading = true;
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
+ if (isc__nm_closing(sock)) {
+ result = ISC_R_SHUTTINGDOWN;
+ } else if (isc__nmsocket_closing(sock)) {
+ result = ISC_R_CANCELED;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ atomic_store(&sock->reading, true);
+ isc__nm_failed_read_cb(sock, result, false);
return;
}
REQUIRE(sock->type == isc_nm_udpsocket);
REQUIRE(sock->statichandle == handle);
- REQUIRE(sock->tid == isc_nm_tid());
REQUIRE(!sock->recv_read);
sock->recv_cb = cb;
sock->recv_cbarg = cbarg;
sock->recv_read = true;
- if (!sock->reading && sock->tid == isc_nm_tid()) {
+ if (!atomic_load(&sock->reading) && sock->tid == isc_nm_tid()) {
isc__netievent_udpread_t ievent = { .sock = sock };
isc__nm_async_udpread(NULL, (isc__netievent_t *)&ievent);
} else {
* interested in the callback.
*/
if (sock->statichandle != NULL) {
- isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
+ if (isc__nm_closing(sock)) {
+ isc__nm_failed_read_cb(sock, ISC_R_SHUTTINGDOWN, false);
+ } else {
+ isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false);
+ }
return;
}