From: Willy Tarreau Date: Wed, 19 Dec 2018 10:00:00 +0000 (+0100) Subject: BUG/MEDIUM: stream-int: also wake the stream up on end of transfer X-Git-Tag: v1.9.0~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=78f5ff86da1f60c71f3bd2ddc4eaed838aa76ed5;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: stream-int: also wake the stream up on end of transfer There is an issue with some medium sized transfers occasionally not shutting down at the end. Olivier tracked this to being caused by a missing wakeup of process_stream(). What happens is that one of the analysers sets CF_WAKE_WRITE to be woken up at the end of the transfer to take note of the end of transaction, but a failed si_cs_send() at the end of process_stream causes the call to be attempted again, with CF_WAKE_WRITE lost. Then stream_int_notify() doesn't find any valid condition to wake up process_stream(), and the stream stays there, idling till the timeout. In fact, CF_WAKE_WRITE has been designed for calling the analysers to complete an operation without closing (keep-alive HTTP transfer for instance). It only applies once the buffer is empty and there is nothing left to be forwarded. In case the channel is closed, the wakeup is already granted. So what we need here is to make sure to wake process_stream() up in case the channel will not be closed and it doesn't have anything left to be transferred. This is detected by the lack of CF_AUTO_CLOSE and the emptiness of the buffer + to_forward after a write activity. So now we take care of always waking the stream up on end of transfers even if the analysers didn't subscribe to this or if their subscription was lost. CF_WAKE_WRITE should probably be killed now, though this first requires careful inspection. No backport is needed. Cc: Olivier Houchard Cc: Christopher Faulet --- diff --git a/src/stream_interface.c b/src/stream_interface.c index 6eb03be185..5283ed583e 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -520,7 +520,8 @@ void stream_int_notify(struct stream_interface *si) (oc->flags & (CF_WRITE_NULL|CF_WRITE_ERROR)) || ((oc->flags & CF_WRITE_ACTIVITY) && ((oc->flags & CF_SHUTW) || - ((oc->flags & CF_WAKE_WRITE) && + (((oc->flags & CF_WAKE_WRITE) || + !(oc->flags & (CF_AUTO_CLOSE|CF_SHUTW_NOW|CF_SHUTW))) && (sio->state != SI_ST_EST || (channel_is_empty(oc) && !oc->to_forward)))))) { task_wakeup(si_task(si), TASK_WOKEN_IO);