From 5fb04711f081860526b1a0043778b5590c54d9c3 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 4 May 2016 10:18:37 +0200 Subject: [PATCH] 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. --- src/stream.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/stream.c b/src/stream.c index f6e1dc48f..da707550b 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) -- 2.47.3