haproxy: Update HAProxy to v2.0.7lilik-openwrt-22.03
@ -1,34 +0,0 @@ | |||
commit be17bb8fc37db4e12ea24c9480ff6442017ff656 | |||
Author: Christopher Faulet <cfaulet@haproxy.com> | |||
Date: Fri Sep 13 15:15:56 2019 +0200 | |||
BUG/MEDIUM: stick-table: Properly handle "show table" with a data type argument | |||
Since the commit 1b8e68e8 ("MEDIUM: stick-table: Stop handling stick-tables as | |||
proxies."), the target field into the table context of the CLI applet was not | |||
anymore a pointer to a proxy. It was replaced by a pointer to a stktable. But, | |||
some parts of the code was not updated accordingly. the function | |||
table_prepare_data_request() still tries to cast it to a pointer to a proxy. The | |||
result is totally undefined. With a bit of luck, when the "show table" command | |||
is used with a data type, we failed to find a table and the error "Data type not | |||
stored in this table" is returned. But crashes may also be experienced. | |||
This patch fixes the issue #262. It must be backported to 2.0. | |||
(cherry picked from commit 4e9a83349a9b523830f79f9632ef777ab0bfcc9d) | |||
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com> | |||
diff --git a/src/stick_table.c b/src/stick_table.c | |||
index 4b04f18c..8528baa0 100644 | |||
--- a/src/stick_table.c | |||
+++ b/src/stick_table.c | |||
@@ -3601,8 +3601,7 @@ static int table_prepare_data_request(struct appctx *appctx, char **args) | |||
return 1; | |||
} | |||
- if (!((struct proxy *)appctx->ctx.table.target)->table || | |||
- !((struct proxy *)appctx->ctx.table.target)->table->data_ofs[appctx->ctx.table.data_type]) { | |||
+ if (!((struct stktable *)appctx->ctx.table.target)->data_ofs[appctx->ctx.table.data_type]) { | |||
appctx->ctx.cli.severity = LOG_ERR; | |||
appctx->ctx.cli.msg = "Data type not stored in this table\n"; | |||
appctx->st0 = CLI_ST_PRINT; |
@ -0,0 +1,27 @@ | |||
commit c0104fc33ccf7e843efd37cc033e4c3849a37844 | |||
Author: Christopher Faulet <cfaulet@haproxy.com> | |||
Date: Sat Sep 28 10:37:31 2019 +0200 | |||
BUG/MINOR: stats: Add a missing break in a switch statement | |||
A break is missing in the switch statement in the function | |||
stats_emit_json_data_field(). This bug was introduced in the commit 88a0db28a | |||
("MINOR: stats: Add the support of float fields in stats"). | |||
This patch fixes the issue #302 and #303. It must be backported to 2.0. | |||
(cherry picked from commit 52c91bb72ccf20e75f2f79da6ebe345cb2a768f4) | |||
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com> | |||
diff --git a/src/stats.c b/src/stats.c | |||
index 5819f459..9ec5066f 100644 | |||
--- a/src/stats.c | |||
+++ b/src/stats.c | |||
@@ -399,6 +399,7 @@ int stats_emit_json_data_field(struct buffer *out, const struct field *f) | |||
type = "\"u64\""; | |||
snprintf(buf, sizeof(buf), "%llu", | |||
(unsigned long long) f->u.u64); | |||
+ break; | |||
case FF_FLT: type = "\"flt\""; | |||
snprintf(buf, sizeof(buf), "%f", f->u.flt); | |||
break; |
@ -1,28 +0,0 @@ | |||
commit 0e01256a314a6f432ab9826dc9b862e8159dbc48 | |||
Author: Christopher Faulet <cfaulet@haproxy.com> | |||
Date: Wed Sep 18 11:07:20 2019 +0200 | |||
BUG/MINOR: mux-h2: Be sure to have a connection to unsubcribe | |||
When the mux is released, It must own the connection to unsubcribe. | |||
This patch must be backported to 2.0. | |||
(cherry picked from commit 21d849f52fc64c51e5abf5a8bd69f2aeff8b3125) | |||
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com> | |||
diff --git a/src/mux_h2.c b/src/mux_h2.c | |||
index 984a81bd..e6bfd03d 100644 | |||
--- a/src/mux_h2.c | |||
+++ b/src/mux_h2.c | |||
@@ -677,9 +677,9 @@ static void h2_release(struct h2c *h2c) | |||
} | |||
if (h2c->wait_event.tasklet) | |||
tasklet_free(h2c->wait_event.tasklet); | |||
- if (h2c->wait_event.events != 0) | |||
+ if (conn && h2c->wait_event.events != 0) | |||
conn->xprt->unsubscribe(conn, conn->xprt_ctx, h2c->wait_event.events, | |||
- &h2c->wait_event); | |||
+ &h2c->wait_event); | |||
pool_free(pool_head_h2c, h2c); | |||
} |
@ -1,83 +0,0 @@ | |||
commit 96b88f2e605e76f2a472cf9fa83398ff242d47bb | |||
Author: Christopher Faulet <cfaulet@haproxy.com> | |||
Date: Mon Sep 23 15:28:20 2019 +0200 | |||
BUG/MAJOR: mux-h2: Handle HEADERS frames received after a RST_STREAM frame | |||
As stated in the RFC7540#5.1, an endpoint that receives any frame other than | |||
PRIORITY after receiving a RST_STREAM MUST treat that as a stream error of type | |||
STREAM_CLOSED. However, frames carrying compression state must still be | |||
processed before being dropped to keep the HPACK decoder synchronized. This had | |||
to be the purpose of the commit 8d9ac3ed8b ("BUG/MEDIUM: mux-h2: do not abort | |||
HEADERS frame before decoding them"). But, the test on the frame type was | |||
inverted. | |||
This bug is major because desynchronizing the HPACK decoder leads to mixup | |||
indexed headers in messages. From the time an HEADERS frame is received and | |||
ignored for a closed stream, wrong headers may be sent to the following streams. | |||
This patch may fix several bugs reported on github (#116, #290, #292). It must | |||
be backported to 2.0 and 1.9. | |||
(cherry picked from commit 6884aa3eb00d1a5eb6f9c81a3a00288c13652938) | |||
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com> | |||
diff --git a/src/mux_h2.c b/src/mux_h2.c | |||
index e6bfd03d..eb773a26 100644 | |||
--- a/src/mux_h2.c | |||
+++ b/src/mux_h2.c | |||
@@ -2106,6 +2106,9 @@ static struct h2s *h2c_frt_handle_headers(struct h2c *h2c, struct h2s *h2s) | |||
*/ | |||
static struct h2s *h2c_bck_handle_headers(struct h2c *h2c, struct h2s *h2s) | |||
{ | |||
+ struct buffer rxbuf = BUF_NULL; | |||
+ unsigned long long body_len = 0; | |||
+ uint32_t flags = 0; | |||
int error; | |||
if (!b_size(&h2c->dbuf)) | |||
@@ -2114,7 +2117,18 @@ static struct h2s *h2c_bck_handle_headers(struct h2c *h2c, struct h2s *h2s) | |||
if (b_data(&h2c->dbuf) < h2c->dfl && !b_full(&h2c->dbuf)) | |||
return NULL; // incomplete frame | |||
- error = h2c_decode_headers(h2c, &h2s->rxbuf, &h2s->flags, &h2s->body_len); | |||
+ if (h2s->st != H2_SS_CLOSED) { | |||
+ error = h2c_decode_headers(h2c, &h2s->rxbuf, &h2s->flags, &h2s->body_len); | |||
+ } | |||
+ else { | |||
+ /* the connection was already killed by an RST, let's consume | |||
+ * the data and send another RST. | |||
+ */ | |||
+ error = h2c_decode_headers(h2c, &rxbuf, &flags, &body_len); | |||
+ h2s_error(h2s, H2_ERR_STREAM_CLOSED); | |||
+ h2c->st0 = H2_CS_FRAME_E; | |||
+ goto send_rst; | |||
+ } | |||
/* unrecoverable error ? */ | |||
if (h2c->st0 >= H2_CS_ERROR) | |||
@@ -2150,6 +2164,15 @@ static struct h2s *h2c_bck_handle_headers(struct h2c *h2c, struct h2s *h2s) | |||
} | |||
return h2s; | |||
+ | |||
+ send_rst: | |||
+ /* make the demux send an RST for the current stream. We may only | |||
+ * do this if we're certain that the HEADERS frame was properly | |||
+ * decompressed so that the HPACK decoder is still kept up to date. | |||
+ */ | |||
+ h2_release_buf(h2c, &rxbuf); | |||
+ h2c->st0 = H2_CS_FRAME_E; | |||
+ return h2s; | |||
} | |||
/* processes a DATA frame. Returns > 0 on success or zero on missing data. | |||
@@ -2459,7 +2482,7 @@ static void h2_process_demux(struct h2c *h2c) | |||
goto strm_err; | |||
} | |||
- if (h2s->flags & H2_SF_RST_RCVD && h2_ft_bit(h2c->dft) & H2_FT_HDR_MASK) { | |||
+ if (h2s->flags & H2_SF_RST_RCVD && !(h2_ft_bit(h2c->dft) & H2_FT_HDR_MASK)) { | |||
/* RFC7540#5.1:closed: an endpoint that | |||
* receives any frame other than PRIORITY after | |||
* receiving a RST_STREAM MUST treat that as a |
@ -1,53 +0,0 @@ | |||
commit b143711afe833f9824a7372b88ef9435ff240e9a | |||
Author: Willy Tarreau <w@1wt.eu> | |||
Date: Tue Sep 3 18:55:02 2019 +0200 | |||
BUG/MEDIUM: check/threads: make external checks run exclusively on thread 1 | |||
See GH issues #141 for all the context. In short, registered signal | |||
handlers are not inherited by other threads during startup, which is | |||
normally not a problem, except that we need that the same thread as | |||
the one doing the fork() cleans up the old process using waitpid() | |||
once its death is reported via SIGCHLD, as happens in external checks. | |||
The only simple solution to this at the moment is to make sure that | |||
external checks are exclusively run on the first thread, the one | |||
which registered the signal handlers on startup. It will be far more | |||
than enough anyway given that external checks must not require to be | |||
load balanced on multiple threads! A more complex solution could be | |||
designed over the long term to let each thread deal with all signals | |||
but it sounds overkill. | |||
This must be backported as far as 1.8. | |||
(cherry picked from commit 6dd4ac890b5810b0f0fe81725fda05ad3d052849) | |||
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com> | |||
diff --git a/src/checks.c b/src/checks.c | |||
index 7b55abda..b088da2e 100644 | |||
--- a/src/checks.c | |||
+++ b/src/checks.c | |||
@@ -2175,7 +2175,7 @@ static struct task *process_chk_proc(struct task *t, void *context, unsigned sho | |||
/* a success was detected */ | |||
check_notify_success(check); | |||
} | |||
- task_set_affinity(t, MAX_THREADS_MASK); | |||
+ task_set_affinity(t, 1); | |||
check->state &= ~CHK_ST_INPROGRESS; | |||
pid_list_del(check->curpid); | |||
@@ -2423,8 +2423,13 @@ static int start_check_task(struct check *check, int mininter, | |||
int nbcheck, int srvpos) | |||
{ | |||
struct task *t; | |||
+ unsigned long thread_mask = MAX_THREADS_MASK; | |||
+ | |||
+ if (check->type == PR_O2_EXT_CHK) | |||
+ thread_mask = 1; | |||
+ | |||
/* task for the check */ | |||
- if ((t = task_new(MAX_THREADS_MASK)) == NULL) { | |||
+ if ((t = task_new(thread_mask)) == NULL) { | |||
ha_alert("Starting [%s:%s] check: out of memory.\n", | |||
check->server->proxy->id, check->server->id); | |||
return 0; |
@ -1,43 +0,0 @@ | |||
commit cfdef9f428869f1570d51a5bd8975d8a42f31eab | |||
Author: Christopher Faulet <cfaulet@haproxy.com> | |||
Date: Mon Sep 23 15:57:29 2019 +0200 | |||
BUG/MINOR: stream-int: Process connection/CS errors first in si_cs_send() | |||
Errors on the connections or the conn-stream must always be processed in | |||
si_cs_send(), even if the stream-interface is already subscribed on | |||
sending. This patch does not fix any concrete bug per-se. But it is required by | |||
the following one to handle those errors during synchronous sends. | |||
This patch must be backported with the following one to 2.0 and probably to 1.9 | |||
too, but with caution because the code is really different. | |||
(cherry picked from commit 328ed220a8c5211aa8b6f37b982f319cf6b3f3d1) | |||
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com> | |||
diff --git a/src/stream_interface.c b/src/stream_interface.c | |||
index 7d89cc90..4130444e 100644 | |||
--- a/src/stream_interface.c | |||
+++ b/src/stream_interface.c | |||
@@ -652,10 +652,6 @@ int si_cs_send(struct conn_stream *cs) | |||
int ret; | |||
int did_send = 0; | |||
- /* We're already waiting to be able to send, give up */ | |||
- if (si->wait_event.events & SUB_RETRY_SEND) | |||
- return 0; | |||
- | |||
if (conn->flags & CO_FL_ERROR || cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) { | |||
/* We're probably there because the tasklet was woken up, | |||
* but process_stream() ran before, detected there were an | |||
@@ -669,6 +665,10 @@ int si_cs_send(struct conn_stream *cs) | |||
return 1; | |||
} | |||
+ /* We're already waiting to be able to send, give up */ | |||
+ if (si->wait_event.events & SUB_RETRY_SEND) | |||
+ return 0; | |||
+ | |||
/* we might have been called just after an asynchronous shutw */ | |||
if (conn->flags & CO_FL_SOCK_WR_SH || oc->flags & CF_SHUTW) | |||
return 1; |
@ -1,40 +0,0 @@ | |||
commit a80c11777b09ea494b5da76a5bcb096851fb6097 | |||
Author: Christopher Faulet <cfaulet@haproxy.com> | |||
Date: Mon Sep 23 16:11:57 2019 +0200 | |||
BUG/MEDIUM: stream-int: Process connection/CS errors during synchronous sends | |||
If an error occurred on the connection or the conn-stream, no syncrhonous send | |||
is performed. If the error was not already processed and there is no more I/O, | |||
it will never be processed and the stream will never be notified of this | |||
error. This may block the stream until a timeout is reached or infinitly if | |||
there is no timeout. | |||
Concretly, this bug can be triggered time to time with h2spec, running the test | |||
"http2/5.1.1/2". | |||
This patch depends on the commit 328ed220a "BUG/MINOR: stream-int: Process | |||
connection/CS errors first in si_cs_send()". Both must be backported to 2.0 and | |||
probably to 1.9. In 1.9, the code is totally different, so this patch would have | |||
to be adapted. | |||
(cherry picked from commit e55a5a41713b629d349ba020183744a38129b892) | |||
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com> | |||
diff --git a/src/stream_interface.c b/src/stream_interface.c | |||
index 4130444e..ef0fea7f 100644 | |||
--- a/src/stream_interface.c | |||
+++ b/src/stream_interface.c | |||
@@ -922,12 +922,6 @@ void si_sync_send(struct stream_interface *si) | |||
if (!cs) | |||
return; | |||
- if (cs->flags & (CS_FL_ERROR|CS_FL_ERR_PENDING)) | |||
- return; | |||
- | |||
- if (cs->conn->flags & CO_FL_ERROR) | |||
- return; | |||
- | |||
si_cs_send(cs); | |||
} | |||
@ -1,53 +0,0 @@ | |||
commit 489bbd321e46c110ab9d92fb91725870d7c40491 | |||
Author: Willy Tarreau <w@1wt.eu> | |||
Date: Tue Sep 24 10:43:03 2019 +0200 | |||
BUG/MEDIUM: checks: make sure the connection is ready before trying to recv | |||
As identified in issue #278, the backport of commit c594039225 ("BUG/MINOR: | |||
checks: do not uselessly poll for reads before the connection is up") | |||
introduced a regression in 2.0 when default checks are enabled (not | |||
"option tcp-check"), but it did not affect 2.1. | |||
What happens is that in 2.0 and earlier we have the fd cache which makes | |||
a speculative call to the I/O functions after an attempt to connect, and | |||
the __event_srv_chk_r() function was absolutely not designed to be called | |||
while a connection attempt is still pending. Thus what happens is that the | |||
test for success/failure expects the verdict to be final before waking up | |||
the check task, and since the connection is not yet validated, it fails. | |||
It will usually work over the loopback depending on scheduling, which is | |||
why it doesn't fail in reg tests. | |||
In 2.1 after the failed connect(), we subscribe to polling and usually come | |||
back with a validated connection, so the function is not expected to be | |||
called before it completes, except if it happens as a side effect of some | |||
spurious wake calls, which should not have any effect on such a check. | |||
The other check types are not impacted by this issue because they all | |||
check for a minimum data length in the buffer, and wait for more data | |||
until they are satisfied. | |||
This patch fixes the issue by explicitly checking that the connection | |||
is established before trying to read or to give a verdict. This way the | |||
function becomes safe to call regardless of the connection status (even | |||
if it's still totally ugly). | |||
This fix must be backported to 2.0. | |||
(cherry picked from commit 0f0393fc0d2badc5ea329844691f06ba28827f78) | |||
Signed-off-by: Willy Tarreau <w@1wt.eu> | |||
diff --git a/src/checks.c b/src/checks.c | |||
index b088da2e..06f47ad9 100644 | |||
--- a/src/checks.c | |||
+++ b/src/checks.c | |||
@@ -875,6 +875,9 @@ static void __event_srv_chk_r(struct conn_stream *cs) | |||
} | |||
} | |||
+ /* the rest of the code below expects the connection to be ready! */ | |||
+ if (!(conn->flags & CO_FL_CONNECTED) && !done) | |||
+ goto wait_more_data; | |||
/* Intermediate or complete response received. | |||
* Terminate string in b_head(&check->bi) buffer. |