]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/worker: fix a memory leak
authorVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 1 Jun 2021 14:26:04 +0000 (16:26 +0200)
committerTomas Krizek <tomas.krizek@nic.cz>
Fri, 18 Jun 2021 08:33:14 +0000 (10:33 +0200)
Discovered case: TCP write towards upstream fails due to ECONNRESET,
and on this place of code we "forget" the whole qr_task and thus its
corresponding kr_request, so it remains unanswered and using memory.

NEWS
daemon/worker.c

diff --git a/NEWS b/NEWS
index 8924e548a7fecf05e21323593338066329596350..ec47b974ca1dac305cba8d4a1b647b2e02c1ed74 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,7 @@ Improvements
 Bugfixes
 --------
 - trust_anchors.set_insecure: improve precision (#673, !1177)
+- plug memory leaks related to TCP (!1182)
 
 Incompatible changes
 --------------------
index f1ade4d25b9d30f612f58f5f99139bb8762e9a5e..b97a66c2645021bf395393d6ed5f702d63af25c2 100644 (file)
@@ -633,8 +633,22 @@ int qr_task_on_send(struct qr_task *task, const uv_handle_t *handle, int status)
        }
 
        if (handle->type == UV_TCP) {
-               if (status != 0)
-                       session_tasklist_del(s, task);
+               if (status != 0) { // session probably not usable anymore; typically: ECONNRESET
+                       if (VERBOSE_STATUS) {
+                               const char *peer_str = NULL;
+                               if (!session_flags(s)->outgoing) {
+                                       peer_str = "hidden"; // avoid logging downstream IPs
+                               } else if (task->transport) {
+                                       peer_str = kr_straddr(&task->transport->address.ip);
+                               }
+                               if (!peer_str)
+                                       peer_str = "unknown"; // probably shouldn't happen
+                               kr_log_verbose( "[wrkr]=> disconnected from '%s': %s\n",
+                                               peer_str, uv_strerror(status));
+                       }
+                       worker_end_tcp(s);
+                       return status;
+               }
 
                if (session_flags(s)->outgoing || session_flags(s)->closing)
                        return status;