From 51611a5b702e6dbf2e5ac56cbcef211326414282 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Mon, 17 Mar 2025 14:49:45 +0100 Subject: [PATCH] BUG/MEDIUM: stream: Fix a possible freeze during a forced shut on a stream When a forced shutdown is performed on a stream, it is possible to freeze it infinitly because it is performed in an unexpected way from process_stream() point of view, especially when the stream is waiting for a server connection. The events sequence is a bit complex but at the end the stream remains blocked in turn-around state and no event are trriggered to unblock it. By trying to fix the issue, we considered it was safer to rethink the feature. The idea is to quickly shutdown a stream to release resources. For instance to be able to delete a server. So, instead of scheduling a shutdown, it is more efficient to trigger an error and detach the stream from the server, if neecessary. The same code than the one used to deal with connection errors in back_handle_st_cer() is used. This patch must be slowly backported as far as 2.6. --- src/stream.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/stream.c b/src/stream.c index 78a5b7e63..d6ebe7cad 100644 --- a/src/stream.c +++ b/src/stream.c @@ -2845,11 +2845,28 @@ void stream_shutdown_self(struct stream *stream, int why) if (stream->scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) return; - sc_schedule_shutdown(stream->scb); - sc_schedule_abort(stream->scb); stream->task->nice = 1024; if (!(stream->flags & SF_ERR_MASK)) stream->flags |= why; + + if (objt_server(stream->target)) { + if (stream->flags & SF_CURR_SESS) { + stream->flags &= ~SF_CURR_SESS; + _HA_ATOMIC_DEC(&__objt_server(stream->target)->cur_sess); + } + + sess_change_server(stream, NULL); + if (may_dequeue_tasks(objt_server(stream->target), stream->be)) + process_srv_queue(objt_server(stream->target)); + } + + /* shutw is enough to stop a connecting socket */ + stream->scb->flags |= SC_FL_ERROR | SC_FL_NOLINGER; + sc_shutdown(stream->scb); + + stream->scb->state = SC_ST_CLO; + if (stream->srv_error) + stream->srv_error(stream, stream->scb); } /* dumps an error message for type at ptr related to stream ,