Projects
openEuler:22.03:LTS:LoongArch
bind
_service:tar_scm_kernel_repo:backport-0041-Grac...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm_kernel_repo:backport-0041-Gracefully-handle-uv_read_start-failures.patch of Package bind
From 6cfab7e4f737803e0fc686ea7b7be0d9215489c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= <ondrej@isc.org> Date: Tue, 14 Jun 2022 09:17:08 +0200 Subject: [PATCH] Gracefully handle uv_read_start() failures Under specific rare timing circumstances the uv_read_start() could fail with UV_EINVAL when the connection is reset between the connect (or accept) and the uv_read_start() call on the nmworker loop. Handle such situation gracefully by propagating the errors from uv_read_start() into upper layers, so the socket can be internally closed(). (cherry picked from commit b432d5d3bcccf199141564b6a87d2cdac296ed7e) Conflict: adapt isc__nm_start_reading modify Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/6cfab7e4f737803e0fc686ea7b7be0d9215489c2 --- lib/isc/netmgr/netmgr-int.h | 4 ++-- lib/isc/netmgr/netmgr.c | 32 +++++++++++++++++++++----------- lib/isc/netmgr/tcp.c | 10 ++++++++-- lib/isc/netmgr/tcpdns.c | 25 +++++++++++++++++++------ lib/isc/netmgr/udp.c | 10 ++++++++-- 5 files changed, 58 insertions(+), 23 deletions(-) diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index e43bc9f..326535c 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -1560,11 +1560,11 @@ isc__nm_tcp_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); void isc__nm_tcpdns_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); -void +isc_result_t isc__nm_start_reading(isc_nmsocket_t *sock); void isc__nm_stop_reading(isc_nmsocket_t *sock); -void +isc_result_t isc__nm_process_sock_buffer(isc_nmsocket_t *sock); void isc__nm_resume_processing(void *arg); diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 701f9a9..71c6d62 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -2162,12 +2162,13 @@ isc__nm_alloc_cb(uv_handle_t *handle, size_t size, uv_buf_t *buf) { worker->recvbuf_inuse = true; } -void +isc_result_t isc__nm_start_reading(isc_nmsocket_t *sock) { + isc_result_t result = ISC_R_SUCCESS; int r; if (sock->reading) { - return; + return (ISC_R_SUCCESS); } switch (sock->type) { @@ -2187,8 +2188,14 @@ isc__nm_start_reading(isc_nmsocket_t *sock) { INSIST(0); ISC_UNREACHABLE(); } - RUNTIME_CHECK(r == 0); - sock->reading = true; + + if (r != 0) { + result = isc__nm_uverr2result(r); + } else { + sock->reading = true; + } + + return (result); } void @@ -2250,7 +2257,7 @@ processbuffer(isc_nmsocket_t *sock) { * limit. In this case we'll be called again by resume_processing() * later. */ -void +isc_result_t isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { for (;;) { int_fast32_t ah = atomic_load(&sock->ah); @@ -2261,7 +2268,10 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { * Don't reset the timer until we have a * full DNS message. */ - isc__nm_start_reading(sock); + result = isc__nm_start_reading(sock); + if (result != ISC_R_SUCCESS) { + return (result); + } /* * Start the timer only if there are no externally used * active handles, there's always one active handle @@ -2271,11 +2281,11 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { if (ah == 1) { isc__nmsocket_timer_start(sock); } - return; + goto done; case ISC_R_CANCELED: isc__nmsocket_timer_stop(sock); isc__nm_stop_reading(sock); - return; + goto done; case ISC_R_SUCCESS: /* * Stop the timer on the successful message read, this @@ -2289,13 +2299,15 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { ah >= STREAM_CLIENTS_PER_CONN) { isc__nm_stop_reading(sock); - return; + goto done; } break; default: INSIST(0); } } +done: + return (ISC_R_SUCCESS); } void diff --git a/lib/isc/netmgr/tcp.c b/lib/isc/netmgr/tcp.c index 009e431..735b29d 100644 --- a/lib/isc/netmgr/tcp.c +++ b/lib/isc/netmgr/tcp.c @@ -743,18 +743,24 @@ isc__nm_async_tcpstartread(isc__networker_t *worker, isc__netievent_t *ev0) { isc__netievent_tcpstartread_t *ievent = (isc__netievent_tcpstartread_t *)ev0; isc_nmsocket_t *sock = ievent->sock; + isc_result_t result; REQUIRE(VALID_NMSOCK(sock)); REQUIRE(sock->tid == isc_nm_tid()); UNUSED(worker); if (isc__nmsocket_closing(sock)) { + result = ISC_R_CANCELED; + } else { + result = isc__nm_start_reading(sock); + } + + if (result != ISC_R_SUCCESS) { sock->reading = true; - isc__nm_tcp_failed_read_cb(sock, ISC_R_CANCELED); + isc__nm_tcp_failed_read_cb(sock, result); return; } - isc__nm_start_reading(sock); isc__nmsocket_timer_start(sock); } diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c index 4689f56..3bc8e05 100644 --- a/lib/isc/netmgr/tcpdns.c +++ b/lib/isc/netmgr/tcpdns.c @@ -709,6 +709,7 @@ isc__nm_async_tcpdnsread(isc__networker_t *worker, isc__netievent_t *ev0) { isc__netievent_tcpdnsread_t *ievent = (isc__netievent_tcpdnsread_t *)ev0; isc_nmsocket_t *sock = ievent->sock; + isc_result_t result; UNUSED(worker); @@ -716,12 +717,15 @@ 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; - isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false); - return; + result = ISC_R_CANCELED; + } else { + result = isc__nm_process_sock_buffer(sock); } - isc__nm_process_sock_buffer(sock); + if (result != ISC_R_SUCCESS) { + sock->reading = true; + isc__nm_failed_read_cb(sock, result, false); + } } /* @@ -813,6 +817,7 @@ isc__nm_tcpdns_read_cb(uv_stream_t *stream, ssize_t nread, isc_nmsocket_t *sock = uv_handle_get_data((uv_handle_t *)stream); uint8_t *base = NULL; size_t len; + isc_result_t result; REQUIRE(VALID_NMSOCK(sock)); REQUIRE(sock->tid == isc_nm_tid()); @@ -856,7 +861,10 @@ isc__nm_tcpdns_read_cb(uv_stream_t *stream, ssize_t nread, sock->read_timeout = atomic_load(&sock->mgr->idle); } - isc__nm_process_sock_buffer(sock); + result = isc__nm_process_sock_buffer(sock); + if (result != ISC_R_SUCCESS) { + isc__nm_failed_read_cb(sock, result, true); + } free: isc__nm_free_uvbuf(sock, buf); } @@ -999,7 +1007,12 @@ accept_connection(isc_nmsocket_t *ssock, isc_quota_t *quota) { * prep_destroy()->tcpdns_close_direct(). */ isc_nmhandle_attach(handle, &csock->recv_handle); - isc__nm_process_sock_buffer(csock); + result = isc__nm_process_sock_buffer(csock); + if (result != ISC_R_SUCCESS) { + isc_nmhandle_detach(&csock->recv_handle); + isc_nmhandle_detach(&handle); + goto failure; + } /* * The initial timer has been set, update the read timeout for the next diff --git a/lib/isc/netmgr/udp.c b/lib/isc/netmgr/udp.c index 305ac29..1af63af 100644 --- a/lib/isc/netmgr/udp.c +++ b/lib/isc/netmgr/udp.c @@ -879,6 +879,7 @@ 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; UNUSED(worker); @@ -886,12 +887,17 @@ isc__nm_async_udpread(isc__networker_t *worker, isc__netievent_t *ev0) { REQUIRE(sock->tid == isc_nm_tid()); if (isc__nmsocket_closing(sock)) { + result = ISC_R_CANCELED; + } else { + result = isc__nm_start_reading(sock); + } + + if (result != ISC_R_SUCCESS) { sock->reading = true; - isc__nm_failed_read_cb(sock, ISC_R_CANCELED, false); + isc__nm_failed_read_cb(sock, result, false); return; } - isc__nm_start_reading(sock); isc__nmsocket_timer_start(sock); } -- 2.27.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.