|
From 912e8f18ef274fdda0a522b2aa8255bddd00fb7b Mon Sep 17 00:00:00 2001
|
|
From: Willy Tarreau <w@1wt.eu>
|
|
Date: Wed, 30 Aug 2017 07:35:35 +0200
|
|
Subject: [PATCH] BUG/MEDIUM: connection: remove useless flag CO_FL_DATA_RD_SH
|
|
|
|
This flag is both confusing and wrong. It is supposed to report the
|
|
fact that the data layer has received a shutdown, but in fact this is
|
|
reported by CO_FL_SOCK_RD_SH which is set by the transport layer after
|
|
this condition is detected. The only case where the flag above is set
|
|
is in the stream interface where CF_SHUTR is also set on the receiving
|
|
channel.
|
|
|
|
In addition, it was checked in the health checks code (while never set)
|
|
and was always test jointly with CO_FL_SOCK_RD_SH everywhere, except in
|
|
conn_data_read0_pending() which incorrectly doesn't match the second
|
|
time it's called and is fortunately protected by an extra check on
|
|
(ic->flags & CF_SHUTR).
|
|
|
|
This patch gets rid of the flag completely. Now conn_data_read0_pending()
|
|
accurately reports the fact that the transport layer has detected the end
|
|
of the stream, regardless of the fact that this state was already consumed,
|
|
and the stream interface watches ic->flags&CF_SHUTR to know if the channel
|
|
was already closed by the upper layer (which it already used to do).
|
|
|
|
The now unused conn_data_read0() function was removed.
|
|
(cherry picked from commit 54e917cfa1e7b0539550ae32c48c76da2f169041)
|
|
|
|
[wt: this happens to fix a real bug which occasionally strikes when
|
|
using http-reuse in the rare case where a server shuts down after
|
|
providing its response but before the connection is put back into
|
|
the idle pool, and it gets immediately recycled for another request,
|
|
without first passing through the idle handler, and the already
|
|
reported shutdown is never reported to the second transaction,
|
|
causing a loop to last for as long as the server timeout]
|
|
---
|
|
contrib/debug/flags.c | 1 -
|
|
include/proto/connection.h | 8 +-------
|
|
include/types/connection.h | 2 +-
|
|
src/checks.c | 4 ++--
|
|
src/stream_interface.c | 11 +++++------
|
|
5 files changed, 9 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/contrib/debug/flags.c b/contrib/debug/flags.c
|
|
index bc71bde9..19327f34 100644
|
|
--- a/contrib/debug/flags.c
|
|
+++ b/contrib/debug/flags.c
|
|
@@ -117,7 +117,6 @@ void show_conn_flags(unsigned int f)
|
|
SHOW_FLAG(f, CO_FL_SOCK_WR_SH);
|
|
SHOW_FLAG(f, CO_FL_SOCK_RD_SH);
|
|
SHOW_FLAG(f, CO_FL_DATA_WR_SH);
|
|
- SHOW_FLAG(f, CO_FL_DATA_RD_SH);
|
|
SHOW_FLAG(f, CO_FL_WAKE_DATA);
|
|
SHOW_FLAG(f, CO_FL_INIT_DATA);
|
|
SHOW_FLAG(f, CO_FL_ADDR_TO_SET);
|
|
diff --git a/include/proto/connection.h b/include/proto/connection.h
|
|
index fce60259..eb68322a 100644
|
|
--- a/include/proto/connection.h
|
|
+++ b/include/proto/connection.h
|
|
@@ -413,12 +413,6 @@ static inline void conn_sock_read0(struct connection *c)
|
|
fdtab[c->t.sock.fd].linger_risk = 0;
|
|
}
|
|
|
|
-static inline void conn_data_read0(struct connection *c)
|
|
-{
|
|
- c->flags |= CO_FL_DATA_RD_SH;
|
|
- __conn_data_stop_recv(c);
|
|
-}
|
|
-
|
|
static inline void conn_sock_shutw(struct connection *c)
|
|
{
|
|
c->flags |= CO_FL_SOCK_WR_SH;
|
|
@@ -450,7 +444,7 @@ static inline void conn_data_shutw_hard(struct connection *c)
|
|
/* detect sock->data read0 transition */
|
|
static inline int conn_data_read0_pending(struct connection *c)
|
|
{
|
|
- return (c->flags & (CO_FL_DATA_RD_SH | CO_FL_SOCK_RD_SH)) == CO_FL_SOCK_RD_SH;
|
|
+ return (c->flags & CO_FL_SOCK_RD_SH) != 0;
|
|
}
|
|
|
|
/* detect data->sock shutw transition */
|
|
diff --git a/include/types/connection.h b/include/types/connection.h
|
|
index 02eac932..90e8e073 100644
|
|
--- a/include/types/connection.h
|
|
+++ b/include/types/connection.h
|
|
@@ -90,7 +90,7 @@ enum {
|
|
CO_FL_WAKE_DATA = 0x00008000, /* wake-up data layer upon activity at the transport layer */
|
|
|
|
/* flags used to remember what shutdown have been performed/reported */
|
|
- CO_FL_DATA_RD_SH = 0x00010000, /* DATA layer was notified about shutr/read0 */
|
|
+ /* unused : 0x00010000 */
|
|
CO_FL_DATA_WR_SH = 0x00020000, /* DATA layer asked for shutw */
|
|
CO_FL_SOCK_RD_SH = 0x00040000, /* SOCK layer was notified about shutr/read0 */
|
|
CO_FL_SOCK_WR_SH = 0x00080000, /* SOCK layer asked for shutw */
|
|
diff --git a/src/checks.c b/src/checks.c
|
|
index ca3881a5..6c5e3cbc 100644
|
|
--- a/src/checks.c
|
|
+++ b/src/checks.c
|
|
@@ -839,7 +839,7 @@ static void event_srv_chk_r(struct connection *conn)
|
|
done = 0;
|
|
|
|
conn->xprt->rcv_buf(conn, check->bi, check->bi->size);
|
|
- if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_DATA_RD_SH)) {
|
|
+ if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH)) {
|
|
done = 1;
|
|
if ((conn->flags & CO_FL_ERROR) && !check->bi->i) {
|
|
/* Report network errors only if we got no other data. Otherwise
|
|
@@ -2892,7 +2892,7 @@ static void tcpcheck_main(struct connection *conn)
|
|
goto out_end_tcpcheck;
|
|
|
|
if (conn->xprt->rcv_buf(conn, check->bi, check->bi->size) <= 0) {
|
|
- if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_DATA_RD_SH)) {
|
|
+ if (conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH)) {
|
|
done = 1;
|
|
if ((conn->flags & CO_FL_ERROR) && !check->bi->i) {
|
|
/* Report network errors only if we got no other data. Otherwise
|
|
diff --git a/src/stream_interface.c b/src/stream_interface.c
|
|
index 836487bd..aba49c94 100644
|
|
--- a/src/stream_interface.c
|
|
+++ b/src/stream_interface.c
|
|
@@ -1060,14 +1060,14 @@ static void si_conn_recv_cb(struct connection *conn)
|
|
if (conn->flags & CO_FL_ERROR)
|
|
return;
|
|
|
|
- /* stop here if we reached the end of data */
|
|
- if (conn_data_read0_pending(conn))
|
|
- goto out_shutdown_r;
|
|
-
|
|
/* maybe we were called immediately after an asynchronous shutr */
|
|
if (ic->flags & CF_SHUTR)
|
|
return;
|
|
|
|
+ /* stop here if we reached the end of data */
|
|
+ if (conn_data_read0_pending(conn))
|
|
+ goto out_shutdown_r;
|
|
+
|
|
cur_read = 0;
|
|
|
|
if ((ic->flags & (CF_STREAMER | CF_STREAMER_FAST)) && !ic->buf->o &&
|
|
@@ -1153,7 +1153,7 @@ static void si_conn_recv_cb(struct connection *conn)
|
|
* that if such an event is not handled above in splice, it will be handled here by
|
|
* recv().
|
|
*/
|
|
- while (!(conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_DATA_RD_SH | CO_FL_WAIT_ROOM | CO_FL_HANDSHAKE))) {
|
|
+ while (!(conn->flags & (CO_FL_ERROR | CO_FL_SOCK_RD_SH | CO_FL_WAIT_ROOM | CO_FL_HANDSHAKE)) && !(ic->flags & CF_SHUTR)) {
|
|
max = channel_recv_max(ic);
|
|
|
|
if (!max) {
|
|
@@ -1267,7 +1267,6 @@ static void si_conn_recv_cb(struct connection *conn)
|
|
if (ic->flags & CF_AUTO_CLOSE)
|
|
channel_shutw_now(ic);
|
|
stream_sock_read0(si);
|
|
- conn_data_read0(conn);
|
|
return;
|
|
}
|
|
|
|
--
|
|
2.13.5
|
|
|