diff --git a/lib/isc/netmgr/netmgr.c b/lib/isc/netmgr/netmgr.c index 01c770d56a..a42ca90e8d 100644 --- a/lib/isc/netmgr/netmgr.c +++ b/lib/isc/netmgr/netmgr.c @@ -2369,14 +2369,41 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { int_fast32_t ah = atomic_load(&sock->ah); isc_result_t result = processbuffer(sock); switch (result) { - case ISC_R_NOMORE: + case ISC_R_NOMORE: { /* * Don't reset the timer until we have a * full DNS message. */ - result = isc__nm_start_reading(sock); - if (result != ISC_R_SUCCESS) { - return (result); + + /* + * Restart reading if we have less data in the send + * queue than the send buffer size, this means that the + * TCP client has started reading some data again. + * Starting reading when we go under the limit instead + * of waiting for all data has been flushed allows + * faster recovery (in case there was a congestion and + * now there isn't). + */ + size_t write_queue_size = + uv_stream_get_write_queue_size( + &sock->uv_handle.stream); + if (write_queue_size < ISC_NETMGR_TCP_SENDBUF_SIZE) { + if (sock->reading_throttled) { + isc_log_write(isc_lctx, + ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_NETMGR, + ISC_LOG_DEBUG(3), + "resuming TCP " + "connection, the other " + "side is reading the " + "data again (%zu)", + write_queue_size); + sock->reading_throttled = false; + } + result = isc__nm_start_reading(sock); + if (result != ISC_R_SUCCESS) { + return (result); + } } /* * Start the timer only if there are no externally used @@ -2388,6 +2415,7 @@ isc__nm_process_sock_buffer(isc_nmsocket_t *sock) { isc__nmsocket_timer_start(sock); } goto done; + } case ISC_R_CANCELED: isc__nmsocket_timer_stop(sock); isc__nm_stop_reading(sock); diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c index d7ec755bec..4b5ee58b6a 100644 --- a/lib/isc/netmgr/tcpdns.c +++ b/lib/isc/netmgr/tcpdns.c @@ -1162,25 +1162,10 @@ tcpdns_maybe_restart_reading(isc_nmsocket_t *sock) { if (!sock->client && sock->reading_throttled && !uv_is_active(&sock->uv_handle.handle)) { - /* - * Restart reading if we have less data in the send queue than - * the send buffer size, this means that the TCP client has - * started reading some data again. Starting reading when we go - * under the limit instead of waiting for all data has been - * flushed allows faster recovery (in case there was a - * congestion and now there isn't). - */ - size_t write_queue_size = - uv_stream_get_write_queue_size(&sock->uv_handle.stream); - if (write_queue_size < ISC_NETMGR_TCP_SENDBUF_SIZE) { - isc_log_write( - isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_NETMGR, ISC_LOG_DEBUG(3), - "resuming TCP connection, the other side " - "is reading the data again (%zu)", - write_queue_size); - sock->reading_throttled = false; - isc__nm_start_reading(sock); + isc_result_t result = isc__nm_process_sock_buffer(sock); + if (result != ISC_R_SUCCESS) { + atomic_store(&sock->reading, true); + isc__nm_failed_read_cb(sock, result, false); } } } @@ -1284,6 +1269,13 @@ isc__nm_async_tcpdnssend(isc__networker_t *worker, isc__netievent_t *ev0) { goto fail; } + isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_NETMGR, + ISC_LOG_DEBUG(3), + "throttling TCP connection, the other side is not " + "reading the data, switching to uv_write()"); + sock->reading_throttled = true; + isc__nm_stop_reading(sock); + r = uv_write(&uvreq->uv_req.write, &sock->uv_handle.stream, bufs, nbufs, tcpdns_send_cb); if (r < 0) { diff --git a/lib/isc/netmgr/tlsdns.c b/lib/isc/netmgr/tlsdns.c index b41c353842..dcec05347f 100644 --- a/lib/isc/netmgr/tlsdns.c +++ b/lib/isc/netmgr/tlsdns.c @@ -1377,6 +1377,14 @@ tls_cycle_output(isc_nmsocket_t *sock) { break; } + isc_log_write( + isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_NETMGR, + ISC_LOG_DEBUG(3), + "throttling TCP connection, the other side is not " + "reading the data, switching to uv_write()"); + sock->reading_throttled = true; + isc__nm_stop_reading(sock); + r = uv_write(&req->uv_req.write, &sock->uv_handle.stream, &req->uvbuf, 1, tls_write_cb); if (r < 0) { @@ -1820,25 +1828,10 @@ tlsdns_maybe_restart_reading(isc_nmsocket_t *sock) { if (!sock->client && sock->reading_throttled && !uv_is_active(&sock->uv_handle.handle)) { - /* - * Restart reading if we have less data in the send queue than - * the send buffer size, this means that the TCP client has - * started reading some data again. Starting reading when we go - * under the limit instead of waiting for all data has been - * flushed allows faster recovery (in case there was a - * congestion and now there isn't). - */ - size_t write_queue_size = - uv_stream_get_write_queue_size(&sock->uv_handle.stream); - if (write_queue_size < ISC_NETMGR_TCP_SENDBUF_SIZE) { - isc_log_write( - isc_lctx, ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_NETMGR, ISC_LOG_DEBUG(3), - "resuming TCP connection, the other side " - "is reading the data again (%zu)", - write_queue_size); - sock->reading_throttled = false; - isc__nm_start_reading(sock); + isc_result_t result = isc__nm_process_sock_buffer(sock); + if (result != ISC_R_SUCCESS) { + atomic_store(&sock->reading, true); + isc__nm_failed_read_cb(sock, result, false); } } } diff --git a/lib/ns/client.c b/lib/ns/client.c index 002185d642..5d2ad0bdbf 100644 --- a/lib/ns/client.c +++ b/lib/ns/client.c @@ -333,6 +333,7 @@ client_senddone(isc_nmhandle_t *handle, isc_result_t result, void *cbarg) { NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), "send failed: %s", isc_result_totext(result)); + isc_nm_bad_request(handle); } }