]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: stream: ensure the SI_FL_DONT_WAKE flag is properly cleared
authorWilly Tarreau <w@1wt.eu>
Wed, 4 May 2016 08:18:37 +0000 (10:18 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 4 May 2016 08:18:37 +0000 (10:18 +0200)
The previous buffer space bug has revealed an issue causing some stalled
connections to remain orphaned forever, preventing an old process from
dying. The issue is that once in a while a task may be woken up because
a disabled expiration timer has been reached despite no timeout being
reached. In this case we exit very early but the SI_FL_DONT_WAKE flag
wasn't cleared, resulting in new events not waking the task up. It may
be one of the reasons why a few people have already observed some peers
connections stuck in CLOSE_WAIT state.

This bug was introduced in 1.5-dev13 by commit 798f432 ("OPTIM: session:
don't process the whole session when only timers need a refresh"), so
the fix must be backported to 1.6 and 1.5.

src/stream.c

index f6e1dc48f1dbc42d95cd1e392037a455e6207ef1..da707550b95cce6d620bd8f840b974ce06faf935 100644 (file)
@@ -1589,8 +1589,11 @@ struct task *process_stream(struct task *t)
                      (CF_SHUTR|CF_READ_ACTIVITY|CF_READ_TIMEOUT|CF_SHUTW|
                       CF_WRITE_ACTIVITY|CF_WRITE_TIMEOUT|CF_ANA_TIMEOUT)) &&
                    !((si_f->flags | si_b->flags) & (SI_FL_EXP|SI_FL_ERR)) &&
-                   ((t->state & TASK_WOKEN_ANY) == TASK_WOKEN_TIMER))
+                   ((t->state & TASK_WOKEN_ANY) == TASK_WOKEN_TIMER)) {
+                       si_f->flags &= ~SI_FL_DONT_WAKE;
+                       si_b->flags &= ~SI_FL_DONT_WAKE;
                        goto update_exp_and_leave;
+               }
        }
 
        /* below we may emit error messages so we have to ensure that we have
@@ -1600,6 +1603,8 @@ struct task *process_stream(struct task *t)
                /* No buffer available, we've been subscribed to the list of
                 * buffer waiters, let's wait for our turn.
                 */
+               si_f->flags &= ~SI_FL_DONT_WAKE;
+               si_b->flags &= ~SI_FL_DONT_WAKE;
                goto update_exp_and_leave;
        }
 
@@ -2473,6 +2478,7 @@ struct task *process_stream(struct task *t)
                }
 
        update_exp_and_leave:
+               /* Note: please ensure that if you branch here you disable SI_FL_DONT_WAKE */
                t->expire = tick_first(tick_first(req->rex, req->wex),
                                       tick_first(res->rex, res->wex));
                if (req->analysers)