From: Willy Tarreau Date: Wed, 4 May 2016 08:18:37 +0000 (+0200) Subject: BUG/MEDIUM: stream: ensure the SI_FL_DONT_WAKE flag is properly cleared X-Git-Tag: v1.7-dev3~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5fb04711f081860526b1a0043778b5590c54d9c3;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: stream: ensure the SI_FL_DONT_WAKE flag is properly cleared 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. --- diff --git a/src/stream.c b/src/stream.c index f6e1dc48f1..da707550b9 100644 --- a/src/stream.c +++ b/src/stream.c @@ -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)