Hi all,

With the very kind help from Cristian Ditoiu, I've just isolated a
very nasty bug introduced in 1.3.19 by the fix for the timer drift :

  
http://haproxy.1wt.eu/git?p=haproxy-1.3.git;a=commitdiff;h=4de2dea8076782d0685cd1f25edfb961d3a9d40c

If you are running a configuration with some missing timeouts, your
haproxy might crash a few minutes after it starts. In fact, it will
crash as soon as it find an unexpirable task in the wait queue, that
it will dequeue and reuse just as if it was queued.

I'll release 1.3.20 and 1.4-dev2 shortly so that we don't stay too
long with this bug. The simple workaround consists in ensuring that
you never have an instance running without timeouts (there are some
warnings emitted upon startup for this). And anyway you should never
do that as you will certainly observe some session leakage over the
time.

In the mean time, and specially for distro maintainers (as I have
noticed that at least Mandriva and Fedora maintainers have already
updated their packages, which is really kind of them), I'm attaching
the patch I'm going to merge (it's running fine right now). I suggest
you merge it into your own 1.3.19 packages for now.

I have another very minor thing to fix which can wait.

More on all of that with the release, which I hope will be out on
Sunday.

Thanks for your patience, and of course, to all the guys who help
chase bugs !

Willy

diff --git a/src/task.c b/src/task.c
index 3094fde..268f8d9 100644
--- a/src/task.c
+++ b/src/task.c
@@ -155,9 +155,13 @@ void wake_expired_tasks(int *next)
                 * to take care of this. Note that we might occasionally 
requeue it at
                 * the same place, before <eb>, so we have to check if this 
happens,
                 * and adjust <eb>, otherwise we may skip it which is not what 
we want.
+                * We may also not requeue the task (and not point eb at it) if 
its
+                * expiration time is not set.
                 */
                if (!tick_is_expired(task->expire, now_ms)) {
-                       task_queue(task);
+                       if (!tick_isset(task->expire))
+                               continue;
+                       __task_queue(task);
                        if (!eb || eb->key > task->wq.key)
                                eb = &task->wq;
                        continue;

Reply via email to