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).
- /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)
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;
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.