]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: tasks: only requeue a task if it was already in the queue
authorWilly Tarreau <w@1wt.eu>
Wed, 11 Dec 2019 08:11:58 +0000 (09:11 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 11 Dec 2019 08:21:36 +0000 (09:21 +0100)
Commit 0742c314c3 ("BUG/MEDIUM: tasks: Make sure we switch wait queues
in task_set_affinity().") had a slight side effect on expired timeouts,
which is that when used before a timeout is updated, it will cause an
existing task to be requeued earlier than its expected timeout when done
before being updated, resulting in the next poll wakup timeout too early
or even instantly if the previous wake up was done on a timeout. This is
visible in strace when health checks are enabled because there are two
poll calls, one of which has a short or zero delay. The correct solution
is to only requeue a task if it was already in the queue.

This can be backported to all branches having the fix above.

include/proto/task.h

index a828cd71f19a28ae90f4cb3810dc8686f23657e5..714adc96977f518843cb87136e75112b31f2af1e 100644 (file)
@@ -155,11 +155,13 @@ static inline void task_wakeup(struct task *t, unsigned int f)
 /* change the thread affinity of a task to <thread_mask> */
 static inline void task_set_affinity(struct task *t, unsigned long thread_mask)
 {
-       if (task_in_wq(t))
+       if (unlikely(task_in_wq(t))) {
                task_unlink_wq(t);
-       t->thread_mask = thread_mask;
-       if (t->expire != TICK_ETERNITY)
+               t->thread_mask = thread_mask;
                task_queue(t);
+       }
+       else
+               t->thread_mask = thread_mask;
 }
 
 /*