diff --git a/lib/isc/netmgr/http.c b/lib/isc/netmgr/http.c index abca92731c..faba79a803 100644 --- a/lib/isc/netmgr/http.c +++ b/lib/isc/netmgr/http.c @@ -222,13 +222,6 @@ http_session_active(isc_nm_http_session_t *session) { 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)); @@ -1461,7 +1454,7 @@ isc_nm_httpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, } 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; @@ -2154,7 +2147,8 @@ server_httpsend(isc_nmhandle_t *handle, isc_nmsocket_t *sock, 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; } @@ -2381,7 +2375,7 @@ httplisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { * 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); } @@ -2393,8 +2387,9 @@ httplisten_acceptcb(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { 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); } @@ -3041,7 +3036,7 @@ isc__nm_http_cleartimeout(isc_nmhandle_t *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_cleartimeout(sock->h2.session->handle); @@ -3057,7 +3052,7 @@ isc__nm_http_settimeout(isc_nmhandle_t *handle, uint32_t timeout) { 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); diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 60d6b83c51..e5a02343b8 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -976,8 +976,8 @@ struct isc_nmsocket { atomic_bool listening; atomic_bool connecting; atomic_bool connected; - bool accepting; - bool reading; + atomic_bool accepting; + atomic_bool reading; isc_refcount_t references; /*% diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index c5f24e5150..d79a4cbeb8 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -1915,7 +1915,7 @@ isc__nm_failed_send_cb(isc_nmsocket_t *sock, isc__nm_uvreq_t *req, 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); /* @@ -1929,7 +1929,7 @@ isc__nm_failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult) { isc__nmsocket_detach(&sock->server); - sock->accepting = false; + atomic_store(&sock->accepting, false); switch (eresult) { case ISC_R_NOTCONNECTED: @@ -2024,11 +2024,13 @@ isc__nmsocket_readtimeout_cb(uv_timer_t *timer) { 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); @@ -2172,7 +2174,7 @@ void isc__nm_start_reading(isc_nmsocket_t *sock) { int r; - if (sock->reading) { + if (atomic_load(&sock->reading)) { return; } @@ -2198,14 +2200,14 @@ isc__nm_start_reading(isc_nmsocket_t *sock) { 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; } @@ -2223,7 +2225,7 @@ isc__nm_stop_reading(isc_nmsocket_t *sock) { ISC_UNREACHABLE(); } RUNTIME_CHECK(r == 0); - sock->reading = false; + atomic_store(&sock->reading, false); } bool @@ -2234,7 +2236,7 @@ isc__nm_closing(isc_nmsocket_t *sock) { 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))); } @@ -2260,8 +2262,8 @@ processbuffer(isc_nmsocket_t *sock) { * 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) { @@ -3123,6 +3125,45 @@ isc__nm_socket_disable_pmtud(uv_os_sock_t fd, sa_family_t sa_family) { 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 @@ -3304,11 +3345,10 @@ isc_nm_sequential(isc_nmhandle_t *handle) { * 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); @@ -3414,7 +3454,7 @@ nmsocket_dump(isc_nmsocket_t *sock) { 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); diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index 382a8360c9..e5bbd1822b 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -86,7 +86,7 @@ stop_tcp_child(isc_nmsocket_t *sock); static void failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult) { - REQUIRE(sock->accepting); + REQUIRE(atomic_load(&sock->accepting)); REQUIRE(sock->server); /* @@ -100,7 +100,7 @@ failed_accept_cb(isc_nmsocket_t *sock, isc_result_t eresult) { isc__nmsocket_detach(&sock->server); - sock->accepting = false; + atomic_store(&sock->accepting, false); switch (eresult) { case ISC_R_NOTCONNECTED: @@ -250,7 +250,11 @@ tcp_connect_cb(uv_connect_t *uvreq, int status) { 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) { @@ -732,8 +736,6 @@ isc__nm_tcp_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { 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; @@ -770,7 +772,7 @@ isc__nm_async_tcpstartread(isc__networker_t *worker, isc__netievent_t *ev0) { 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; } @@ -833,7 +835,7 @@ isc__nm_tcp_resumeread(isc_nmhandle_t *handle) { } if (!isc__nmsocket_active(sock)) { - sock->reading = true; + atomic_store(&sock->reading, true); isc__nm_tcp_failed_read_cb(sock, ISC_R_CANCELED); return; } @@ -856,7 +858,7 @@ isc__nm_tcp_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { 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)) { @@ -895,7 +897,7 @@ isc__nm_tcp_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { 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); } @@ -973,7 +975,7 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { 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()]; @@ -1024,7 +1026,7 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { goto failure; } - csock->accepting = false; + atomic_store(&csock->accepting, false); isc__nm_incstats(csock->mgr, csock->statsindex[STATID_ACCEPT]); @@ -1354,7 +1356,7 @@ isc__nm_tcp_shutdown(isc_nmsocket_t *sock) { return; } - if (sock->accepting) { + if (atomic_load(&sock->accepting)) { return; } @@ -1366,7 +1368,11 @@ isc__nm_tcp_shutdown(isc_nmsocket_t *sock) { } 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; } diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c index b5d2d248ce..9f4a7fc595 100644 --- a/lib/isc/netmgr/tcpdns.c +++ b/lib/isc/netmgr/tcpdns.c @@ -107,7 +107,7 @@ tcpdns_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { RUNTIME_CHECK(r == 0); if (isc__nm_closing(sock)) { - result = ISC_R_CANCELED; + result = ISC_R_SHUTTINGDOWN; goto error; } @@ -217,7 +217,11 @@ tcpdns_connect_cb(uv_connect_t *uvreq, int status) { 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) { @@ -690,8 +694,6 @@ isc__nm_tcpdns_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { 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; @@ -729,7 +731,7 @@ isc__nm_async_tcpdnsread(isc__networker_t *worker, isc__netievent_t *ev0) { 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; } @@ -780,8 +782,8 @@ isc__nm_tcpdns_processbuffer(isc_nmsocket_t *sock) { 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); @@ -800,9 +802,10 @@ isc__nm_tcpdns_processbuffer(isc_nmsocket_t *sock) { 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; @@ -829,7 +832,7 @@ isc__nm_tcpdns_read_cb(uv_stream_t *stream, ssize_t nread, 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)) { @@ -949,7 +952,7 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { 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]; @@ -1007,7 +1010,7 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { goto failure; } - csock->accepting = false; + atomic_store(&csock->accepting, false); isc__nm_incstats(csock->mgr, csock->statsindex[STATID_ACCEPT]); @@ -1056,13 +1059,15 @@ failure: 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); @@ -1107,24 +1112,26 @@ tcpdns_send_cb(uv_write_t *req, int status) { */ 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; @@ -1380,7 +1387,7 @@ isc__nm_tcpdns_shutdown(isc_nmsocket_t *sock) { return; } - if (sock->accepting) { + if (atomic_load(&sock->accepting)) { return; } @@ -1392,7 +1399,11 @@ isc__nm_tcpdns_shutdown(isc_nmsocket_t *sock) { } 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; } diff --git a/lib/isc/netmgr/tlsdns.c b/lib/isc/netmgr/tlsdns.c index 72fe096f5c..0b3b43703a 100644 --- a/lib/isc/netmgr/tlsdns.c +++ b/lib/isc/netmgr/tlsdns.c @@ -124,7 +124,7 @@ tlsdns_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { 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; } @@ -233,7 +233,11 @@ tlsdns_connect_cb(uv_connect_t *uvreq, int status) { 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) { @@ -344,6 +348,7 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, } if (isc__nm_closing(sock)) { + result = ISC_R_SHUTTINGDOWN; goto failure; } @@ -373,6 +378,7 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer, BROADCAST(&sock->scond); UNLOCK(&sock->lock); return; + failure: if (isc__nm_in_netthread()) { sock->tid = isc_nm_tid(); @@ -843,8 +849,6 @@ isc__nm_tlsdns_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { 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; @@ -884,7 +888,7 @@ isc__nm_async_tlsdnsread(isc__networker_t *worker, isc__netievent_t *ev0) { 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; } @@ -938,9 +942,8 @@ isc__nm_tlsdns_processbuffer(isc_nmsocket_t *sock) { 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); @@ -959,10 +962,10 @@ isc__nm_tlsdns_processbuffer(isc_nmsocket_t *sock) { 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; @@ -1278,6 +1281,8 @@ done: 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() */ @@ -1285,8 +1290,7 @@ async_tlsdns_cycle(isc_nmsocket_t *sock) { 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); } @@ -1321,7 +1325,7 @@ isc__nm_tlsdns_read_cb(uv_stream_t *stream, ssize_t nread, 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)) { @@ -1441,7 +1445,7 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { 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]; @@ -1530,7 +1534,7 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { /* FIXME: Set SSL_MODE_RELEASE_BUFFERS */ - csock->accepting = false; + atomic_store(&csock->accepting, false); isc__nm_incstats(csock->mgr, csock->statsindex[STATID_ACCEPT]); @@ -1579,13 +1583,15 @@ failure: 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); @@ -1936,12 +1942,14 @@ isc__nm_tlsdns_shutdown(isc_nmsocket_t *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 @@ -1956,14 +1964,17 @@ isc__nm_tlsdns_shutdown(isc_nmsocket_t *sock) { } /* 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; } diff --git a/lib/isc/netmgr/tlsstream.c b/lib/isc/netmgr/tlsstream.c index 8321b74f3b..49edb68191 100644 --- a/lib/isc/netmgr/tlsstream.c +++ b/lib/isc/netmgr/tlsstream.c @@ -83,7 +83,7 @@ inactive(isc_nmsocket_t *sock) { 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 @@ -913,7 +913,7 @@ tcp_connected(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { 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; } diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index fbf9345592..f4de7d3e73 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -89,7 +89,7 @@ start_udp_child(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nmsocket_t *sock, 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; @@ -344,7 +344,7 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf, 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); @@ -356,7 +356,7 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf, #endif /* - * Three possible reasons to return now without processing: + * Four possible reasons to return now without processing: */ /* @@ -373,6 +373,15 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf, 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. @@ -390,12 +399,6 @@ udp_recv_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf, 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); @@ -612,6 +615,11 @@ udp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { 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]); @@ -653,6 +661,7 @@ udp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) { done: result = isc__nm_uverr2result(r); +error: LOCK(&sock->lock); sock->result = result; @@ -800,6 +809,7 @@ isc__nm_udp_read_cb(uv_udp_t *handle, ssize_t nrecv, const uv_buf_t *buf, * does not. */ if (!sock->parent) { + isc__nmsocket_timer_stop(sock); isc__nm_stop_reading(sock); } } @@ -856,15 +866,22 @@ void 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; } @@ -881,14 +898,13 @@ isc__nm_udp_read(isc_nmhandle_t *handle, isc_nm_recv_cb_t cb, void *cbarg) { 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 { @@ -1079,7 +1095,11 @@ isc__nm_udp_shutdown(isc_nmsocket_t *sock) { * 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; }