The attached experimental patch tries to send a 504 back to the sender
whenever ((rpf_last & CF_SHUTW) && (rpf_last & CF_AUTO_CLOSE)). This
is the condition that we were seeing in the rep flags that resulted in
no http responses being sent to the clients.
I am pretty new to haproxy.  Is this on the right track?
From 7b862d66c760c8e4cb2cfdde373190cd306e042d Mon Sep 17 00:00:00 2001
From: Shayan Pooya <[email protected]>
Date: Tue, 18 Nov 2014 22:20:32 -0500
Subject: [PATCH] MINOR: send a 504 back to the client if there has been a read
 timeout

---
 include/proto/proto_http.h |  1 +
 src/proto_http.c           | 19 +++++++++++++++++++
 src/session.c              |  4 ++++
 3 files changed, 24 insertions(+)

diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h
index 945d49c..ef5212c 100644
--- a/include/proto/proto_http.h
+++ b/include/proto/proto_http.h
@@ -76,6 +76,7 @@ int http_wait_for_response(struct session *s, struct channel *rep, int an_bit);
 int http_process_res_common(struct session *s, struct channel *rep, int an_bit, struct proxy *px);
 int http_request_forward_body(struct session *s, struct channel *req, int an_bit);
 int http_response_forward_body(struct session *s, struct channel *res, int an_bit);
+int http_notify_timeout(struct session *s, struct channel *rep);
 
 void debug_hdr(const char *dir, struct session *s, const char *start, const char *end);
 void get_srv_from_appsession(struct session *s, const char *begin, int len);
diff --git a/src/proto_http.c b/src/proto_http.c
index 3a3aa80..99081fc 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -5625,6 +5625,25 @@ int http_request_forward_body(struct session *s, struct channel *req, int an_bit
 	return 0;
 }
 
+int http_notify_timeout(struct session *s, struct channel *rep)
+{
+	struct http_txn *txn = &s->txn;
+
+	channel_auto_close(rep);
+	rep->analysers = 0;
+	txn->status = 504;
+	rep->prod->flags |= SI_FL_NOLINGER;
+	bi_erase(rep);
+	stream_int_retnclose(rep->cons, http_error_message(s, HTTP_ERR_504));
+
+	if (!(s->flags & SN_ERR_MASK))
+		s->flags |= SN_ERR_SRVTO;
+	if (!(s->flags & SN_FINST_MASK))
+		s->flags |= SN_FINST_H;
+
+	return 0;
+}
+
 /* This stream analyser waits for a complete HTTP response. It returns 1 if the
  * processing can continue on next analysers, or zero if it either needs more
  * data or wants to immediately abort the response (eg: timeout, error, ...). It
diff --git a/src/session.c b/src/session.c
index aeaa7e1..1a582cc 100644
--- a/src/session.c
+++ b/src/session.c
@@ -2386,6 +2386,10 @@ struct task *process_session(struct task *t)
 	 * FIXME: this is probably where we should produce error responses.
 	 */
 
+	if ((rpf_last & CF_SHUTW) && (rpf_last & CF_AUTO_CLOSE)) {
+		http_notify_timeout(s, s->rep);
+	}
+
 	/* first, let's check if the response buffer needs to shutdown(write) */
 	if (unlikely((s->rep->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_AUTO_CLOSE|CF_SHUTR)) ==
 		     (CF_AUTO_CLOSE|CF_SHUTR))) {
-- 
1.9.3

Reply via email to