From 1b8ca663a46a1927affcbb0a4fcca9272860a3a7 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 8 Mar 2009 00:26:28 +0100 Subject: [PATCH] [BUG] task: fix handling of duplicate keys A bug was introduced with the ebtree-based scheduler. It seldom causes some timeouts to last longer than required if they hit an expiration date which is the same as the last queued date, is also part of a duplicate tree without being the top of the tree. In this case, the task will not be expired until after the duplicate tree has been flushed. It is easier to reproduce by setting a very short client timeout (1s) and sending connections and waiting for them to expire with the 408 status. Then in parallel, inject at about 1kh/s. The bug causes the connections to sometimes wait longer than 1s before timing out. The cause was the use of eb_insert_dup() on wrong nodes, as this function is designed to work only on the top of the dup tree. The solution consists in updating last_timer only when its bit is -1, and using it only if its bit is still -1 (top of a dup tree). The fix has not reduced performance because it only fixes the case where this bug could fire, which is extremely rare. --- src/task.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/task.c b/src/task.c index 98967c55e4..25d702d797 100644 --- a/src/task.c +++ b/src/task.c @@ -180,15 +180,18 @@ struct task *task_queue(struct task *task) if (likely(last_timer && last_timer->eb.key == task->eb.key && - last_timer->eb.node.node_p)) { + last_timer->eb.node.node_p && + last_timer->eb.node.bit == -1)) { /* Most often, last queued timer has the same expiration date, so * if it's not queued at the root, let's queue a dup directly there. + * Note that we can only use dups at the dup tree's root (bit==-1). */ eb_insert_dup(&last_timer->eb.node, &task->eb.node); return task; } eb32_insert(&timers[ticks_to_tree(task->eb.key)], &task->eb); - last_timer = task; + if (task->eb.node.bit == -1) + last_timer = task; /* we only want dup a tree's root */ return task; } -- 2.47.2