From 0b9e8e6063e0369008f34d039d158edef517258c Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Wed, 12 Feb 2025 22:58:42 +0200 Subject: [PATCH] DoH: Fix missing send callback calls When handling outgoing data, there were a couple of rarely executed code paths that would not take into account that the callback MUST be called. It could lead to potential memory leaks and consequent shutdown hangs. (cherry picked from commit 8b8f4d500d9c1d41d95d34a79c8935823978114c) --- lib/isc/netmgr/http.c | 53 +++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/lib/isc/netmgr/http.c b/lib/isc/netmgr/http.c index 1006581d48..2df182edbc 100644 --- a/lib/isc/netmgr/http.c +++ b/lib/isc/netmgr/http.c @@ -1361,6 +1361,23 @@ move_pending_send_callbacks(isc_nm_http_session_t *session, ISC_LIST_INIT(session->pending_write_callbacks); } +static inline void +http_append_pending_send_request(isc_nm_http_session_t *session, + isc_nmhandle_t *httphandle, isc_nm_cb_t cb, + void *cbarg) { + REQUIRE(VALID_HTTP2_SESSION(session)); + REQUIRE(VALID_NMHANDLE(httphandle)); + REQUIRE(cb != NULL); + + isc__nm_uvreq_t *newcb = isc__nm_uvreq_get(httphandle->sock->mgr, + httphandle->sock); + + newcb->cb.send = cb; + newcb->cbarg = cbarg; + isc_nmhandle_attach(httphandle, &newcb->handle); + ISC_LIST_APPEND(session->pending_write_callbacks, newcb, link); +} + static bool http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle, isc_nm_cb_t cb, void *cbarg) { @@ -1372,10 +1389,25 @@ http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle, size_t max_total_write_size = 0; #endif /* ENABLE_HTTP_WRITE_BUFFERING */ - if (!http_session_active(session) || - (!nghttp2_session_want_write(session->ngsession) && - session->pending_write_data == NULL)) + if (!http_session_active(session)) { + if (cb != NULL) { + isc__nm_uvreq_t *req = isc__nm_uvreq_get( + httphandle->sock->mgr, httphandle->sock); + + req->cb.send = cb; + req->cbarg = cbarg; + isc_nmhandle_attach(httphandle, &req->handle); + isc__nm_sendcb(httphandle->sock, req, ISC_R_CANCELED, + true); + } + return false; + } else if (!nghttp2_session_want_write(session->ngsession) && + session->pending_write_data == NULL) { + if (cb != NULL) { + http_append_pending_send_request(session, httphandle, + cb, cbarg); + } return false; } @@ -1435,15 +1467,8 @@ http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle, * FLUSH_HTTP_WRITE_BUFFER_AFTER bytes in the write buffer, we * will flush the buffer. */ if (cb != NULL) { - isc__nm_uvreq_t *newcb = isc__nm_uvreq_get( - httphandle->sock->mgr, httphandle->sock); - - INSIST(VALID_NMHANDLE(httphandle)); - newcb->cb.send = cb; - newcb->cbarg = cbarg; - isc_nmhandle_attach(httphandle, &newcb->handle); - ISC_LIST_APPEND(session->pending_write_callbacks, newcb, - link); + http_append_pending_send_request(session, httphandle, + cb, cbarg); } goto nothing_to_send; } else if (session->sending == 0 && total == 0 && @@ -1480,6 +1505,10 @@ http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle, if (total == 0) { /* No data returned */ + if (cb != NULL) { + http_append_pending_send_request(session, httphandle, + cb, cbarg); + } goto nothing_to_send; }