From 964891a7949715805e00ecedc1cb11b2703984ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Wed, 5 Jun 2024 09:15:39 +0200 Subject: [PATCH] Limit the number of DNS message processed from a single TCP read The single TCP read can create as much as 64k divided by the minimum size of the DNS message. This can clog the processing thread and trash the memory allocator because we need to do as much as ~20k allocations in a single UV loop tick. Limit the number of the DNS messages processed in a single UV loop tick to just single DNS message and limit the number of the outstanding DNS messages back to 23. This effectively limits the number of pipelined DNS messages to that number (this is the limit we already had before). This reverts commit 780a89012d8627b9284983702dced8a3f65688aa. --- lib/isc/netmgr/netmgr-int.h | 8 ++++++++ lib/isc/netmgr/netmgr.c | 9 ++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/isc/netmgr/netmgr-int.h b/lib/isc/netmgr/netmgr-int.h index 6d2bd9ad9f..4ceb182e7b 100644 --- a/lib/isc/netmgr/netmgr-int.h +++ b/lib/isc/netmgr/netmgr-int.h @@ -2262,6 +2262,14 @@ isc__nmsocket_readtimeout_cb(uv_timer_t *timer); void isc__nmsocket_writetimeout_cb(void *data, isc_result_t eresult); +/*%< + * + * Maximum number of simultaneous handles in flight supported for a single + * connected TCPDNS socket. This value was chosen arbitrarily, and may be + * changed in the future. + */ +#define STREAM_CLIENTS_PER_CONN 23 + #define UV_RUNTIME_CHECK(func, ret) \ if (ret != 0) { \ FATAL_ERROR("%s failed: %s\n", #func, uv_strerror(ret)); \ diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 7b09639440..336cad4e23 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -2343,8 +2343,10 @@ processbuffer(isc_nmsocket_t *sock) { * timers. If we do have a full message, reset the timer. * * Stop reading if this is a client socket, or if the server socket - * has been set to sequential mode. In this case we'll be called again - * later by isc__nm_resume_processing(). + * 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 later by + * isc__nm_resume_processing(). */ isc_result_t isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { @@ -2384,7 +2386,8 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { isc__nmsocket_timer_stop(sock); if (atomic_load(&sock->client) || - atomic_load(&sock->sequential)) + atomic_load(&sock->sequential) || + atomic_load(&sock->ah) >= STREAM_CLIENTS_PER_CONN) { isc__nm_stop_reading(sock); goto done;