]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/worker pl_dns_stream_disconnected(): fix tasklist confusion
authorVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 24 Apr 2025 08:10:44 +0000 (10:10 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 24 Apr 2025 08:49:52 +0000 (10:49 +0200)
The tasks on the waitinglist are not present in the taskslist,
so let's not incorrectly attempt removal in this case.

We didn't check the return value here, and the disconnection event
won't even happen in the typical cases, so this has been unnoticed -
until the deletion actually did find a matching msgid (lucky!)
by a *different* task (of course) which triggered an assertion (crash).

NEWS
daemon/session2.h
daemon/worker.c

diff --git a/NEWS b/NEWS
index 5ff5a7b9042f6433a03e81aeb190e39a7401740d..4ff8bd37bb825123c924cd6a960808936f2e50c8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ Improvements
 - /local-data/rpz/*/watchdog: new configuration to enable watchdog for RPZ files (!1665)
 - daemon: fix rare crashes with either of the lines below
   [system] requirement "h && h->end > h->begin" failed in queue_pop_impl
+  [system] requirement "val == task" failed in session2_tasklist_del
 
 
 Knot Resolver 6.0.11 (2025-02-26)
index f94a82fa027a80723b65ad711a33145fe050df73..f0f1868b77fd59113005f2271405e6405c01ac0a 100644 (file)
@@ -828,7 +828,15 @@ struct session2 {
 
        uv_timer_t timer; /**< For session-wide timeout events. */
        enum protolayer_event_type timer_event; /**< The event fired on timeout. */
-       trie_t *tasks; /**< List of tasks associated with given session. */
+
+       /** List of tasks where an unreplied query has been sent over this session.
+        *
+        * Use session2_tasklist_*() functions to manipulate this.
+        *
+        * In outgoing sessions the tasks are organized by message ID of the unreplied query.
+        */
+       trie_t *tasks;
+
        queue_t(struct qr_task *) waiting; /**< List of tasks waiting for
                                            * sending to upstream. */
        struct wire_buf wire_buf;
index a58db0cafca03c31a182549fd8b48049a58748bc..6f6cda584196c74bce1308242bd72347c063b5d1 100644 (file)
@@ -2037,7 +2037,7 @@ static enum protolayer_event_cb_result pl_dns_stream_disconnected(
        while (!session2_waitinglist_is_empty(session)) {
                struct qr_task *task = session2_waitinglist_pop(session, false);
                kr_assert(task->refs > 1);
-               session2_tasklist_del(session, task);
+
                if (session->outgoing) {
                        if (task->ctx->req.options.FORWARD) {
                                /* We are in TCP_FORWARD mode.