package: haproxy
- add missing patches - add patch number to version git-svn-id: svn://svn.openwrt.org/openwrt/packages@35091 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
8c176b0c41
commit
240ad98e89
@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=haproxy
|
||||
PKG_VERSION:=1.4.22
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=23
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=http://haproxy.1wt.eu/download/1.4/src
|
||||
@ -44,6 +44,7 @@ define Build/Compile
|
||||
LD="$(TARGET_CC)" \
|
||||
LDFLAGS="$(TARGET_LDFLAGS)" \
|
||||
SMALL_OPTS="-DBUFSIZE=16384 -DMAXREWRITE=8192 -DSYSTEM_MAXCONN=65530" USE_LINUX_TPROXY=1 USE_LINUX_SPLICE=1 \
|
||||
VERSION="$(PKG_VERSION)-patch$(PKG_RELEASE)" \
|
||||
all install
|
||||
endef
|
||||
|
||||
|
@ -0,0 +1,75 @@
|
||||
From 60f05a8eae1afda44d62066445a0c072659a1aa1 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Thu, 4 Oct 2012 08:01:43 +0200
|
||||
Subject: BUG/MINOR: config: use a copy of the file name in proxy configurations
|
||||
|
||||
Each proxy contains a reference to the original config file and line
|
||||
number where it was declared. The pointer used is just a reference to
|
||||
the one passed to the function instead of being duplicated. The effect
|
||||
is that it is not valid anymore at the end of the parsing and that all
|
||||
proxies will be enumerated as coming from the same file on some late
|
||||
configuration errors. This may happen for exmaple when reporting SSL
|
||||
certificate issues.
|
||||
|
||||
By copying using strdup(), we avoid this issue.
|
||||
|
||||
1.4 has the same issue, though no report of the proxy file name is done
|
||||
out of the config section. Anyway a backport is recommended to ease
|
||||
post-mortem analysis.
|
||||
(cherry picked from commit 8113a5d78f2d2abe942f88a3a4df9f8bb5e535ba)
|
||||
---
|
||||
include/types/proxy.h | 2 +-
|
||||
src/cfgparse.c | 4 ++--
|
||||
src/haproxy.c | 1 +
|
||||
3 files changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/include/types/proxy.h b/include/types/proxy.h
|
||||
index 1773658..a06078a 100644
|
||||
--- a/include/types/proxy.h
|
||||
+++ b/include/types/proxy.h
|
||||
@@ -320,7 +320,7 @@ struct proxy {
|
||||
int no_options2; /* PR_O2_* */
|
||||
|
||||
struct {
|
||||
- const char *file; /* file where the section appears */
|
||||
+ char *file; /* file where the section appears */
|
||||
int line; /* line where the section appears */
|
||||
struct eb32_node id; /* place in the tree of used IDs */
|
||||
struct eb_root used_listener_id;/* list of listener IDs in use */
|
||||
diff --git a/src/cfgparse.c b/src/cfgparse.c
|
||||
index 643f065..90fdbff 100644
|
||||
--- a/src/cfgparse.c
|
||||
+++ b/src/cfgparse.c
|
||||
@@ -1136,7 +1136,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||
init_new_proxy(curproxy);
|
||||
curproxy->next = proxy;
|
||||
proxy = curproxy;
|
||||
- curproxy->conf.file = file;
|
||||
+ curproxy->conf.file = strdup(file);
|
||||
curproxy->conf.line = linenum;
|
||||
curproxy->last_change = now.tv_sec;
|
||||
curproxy->id = strdup(args[1]);
|
||||
@@ -3425,7 +3425,7 @@ stats_error_parsing:
|
||||
newsrv->next = curproxy->srv;
|
||||
curproxy->srv = newsrv;
|
||||
newsrv->proxy = curproxy;
|
||||
- newsrv->conf.file = file;
|
||||
+ newsrv->conf.file = strdup(file);
|
||||
newsrv->conf.line = linenum;
|
||||
|
||||
LIST_INIT(&newsrv->pendconns);
|
||||
diff --git a/src/haproxy.c b/src/haproxy.c
|
||||
index 6141a5b..2944462 100644
|
||||
--- a/src/haproxy.c
|
||||
+++ b/src/haproxy.c
|
||||
@@ -732,6 +732,7 @@ void deinit(void)
|
||||
int i;
|
||||
|
||||
while (p) {
|
||||
+ free(p->conf.file);
|
||||
free(p->id);
|
||||
free(p->check_req);
|
||||
free(p->cookie_name);
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,53 @@
|
||||
From 72ce4c8f4e0531c50b3a0914d77858440d16d914 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Thu, 4 Oct 2012 21:54:41 +0200
|
||||
Subject: BUG/MINOR: epoll: correctly disable FD polling in fd_rem()
|
||||
|
||||
When calling fd_rem(), the polling was not correctly disabled because the
|
||||
->prev state was set to zero instead of the previous value. fd_rem() is
|
||||
very rarely used, only just before closing a socket.
|
||||
|
||||
The effect is that upon an error reported at the connection level, if the
|
||||
task assigned to the connection was too slow to be woken up because of too
|
||||
many other tasks in the run queue, the FD was still not disabled and caused
|
||||
the connection handler to be called again with the same event until the task
|
||||
was finally executed to close the fd.
|
||||
|
||||
This issue only affects the epoll poller, not the sepoll variant nor any of
|
||||
the other ones.
|
||||
|
||||
It was already present in 1.4 and even 1.3 with the same almost unnoticeable
|
||||
effects. The bug can in fact only be discovered during development where it
|
||||
emphasizes other bugs.
|
||||
|
||||
It should be backported anyway.
|
||||
(cherry picked from commit f8cfa447c676849e1d1b007353d4ea2f7231e4a0)
|
||||
---
|
||||
src/ev_epoll.c | 8 ++++++--
|
||||
1 files changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/ev_epoll.c b/src/ev_epoll.c
|
||||
index b976868..0b22da6 100644
|
||||
--- a/src/ev_epoll.c
|
||||
+++ b/src/ev_epoll.c
|
||||
@@ -194,11 +194,15 @@ REGPRM2 static int __fd_clr(const int fd, int dir)
|
||||
REGPRM1 static void __fd_rem(int fd)
|
||||
{
|
||||
uint32_t ofs = FD2OFS(fd);
|
||||
+ uint32_t old_evt;
|
||||
|
||||
- if (unlikely(!((fd_evts[ofs] >> FD2BIT(fd)) & 3)))
|
||||
+ old_evt = fd_evts[ofs] >> FD2BIT(fd);
|
||||
+ old_evt &= 3;
|
||||
+
|
||||
+ if (unlikely(!old_evt))
|
||||
return;
|
||||
|
||||
- alloc_chg_list(fd, 0);
|
||||
+ alloc_chg_list(fd, old_evt);
|
||||
fd_evts[ofs] &= ~FD2MSK(fd);
|
||||
return;
|
||||
}
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,191 @@
|
||||
From 69eeb17615cd032ec7b3a9496ddb811095e92cb4 Mon Sep 17 00:00:00 2001
|
||||
From: Baptiste <bedis9@gmail.com>
|
||||
Date: Sat, 8 Sep 2012 23:10:03 +0200
|
||||
Subject: CONTRIB: halog: sort URLs by avg bytes_read or total bytes_read
|
||||
|
||||
The patch attached to this mail brings ability to sort URLs by
|
||||
averaged bytes read and total bytes read in HALog tool.
|
||||
In most cases, bytes read is also the object size.
|
||||
The purpose of this patch is to know which URL consume the most
|
||||
bandwith, in average or in total.
|
||||
It may be interesting as well to know the standard deviation (ecart
|
||||
type in french) for some counters (like bytes_read).
|
||||
|
||||
The results:
|
||||
- Sorting by average bytes read per URL:
|
||||
./halog -uba <~/tmp/haproxy.log | column -t | head
|
||||
2246 lines in, 302 lines out, 194 parsing errors
|
||||
18 0 5101 283 5101 283 126573 2278327 /lib/exe/js.php
|
||||
1 0 1 1 1 1 106734 106734 /wp-admin/images/screenshots/theme-customizer.png
|
||||
2 0 2 1 2 1 106511 213022 /wp-admin/css/wp-admin.css
|
||||
1 0 1 1 1 1 96698 96698 /wp-admin/images/screenshots/captions-1.png
|
||||
1 0 1 1 1 1 73165 73165 /wp-admin/images/screenshots/flex-header-1.png
|
||||
4 0 0 0 0 0 64832 259328 /cuisine/wp-content/plugins/stats/open-flash-chart.swf
|
||||
1 0 0 0 0 0 48647 48647 /wp-admin/images/screenshots/flex-header-3.png
|
||||
1 0 0 0 0 0 44046 44046 /wp-admin/images/screenshots/captions-2.png
|
||||
1 0 1 1 1 1 38830 38830 /wp-admin/images/screenshots/flex-header-2.png
|
||||
|
||||
- Sorting by total bytes read per URL:
|
||||
./halog -ubt <~/tmp/haproxy.log | column -t | head
|
||||
2246 lines in, 302 lines out, 194 parsing errors
|
||||
18 0 5101 283 5101 283 126573 2278327 /lib/exe/js.php
|
||||
60 0 14387 239 14387 239 10081 604865 /lib/exe/css.php
|
||||
64 2 8820 137 8819 142 7742 495524 /doku.php
|
||||
14 0 250 17 250 17 24045 336632 /wp-admin/load-scripts.php
|
||||
71 0 6422 90 6422 90 4048 287419 /wp-admin/
|
||||
4 0 0 0 0 0 64832 259328 /cuisine/wp-content/plugins/stats/open-flash-chart.swf
|
||||
2 0 2 1 2 1 106511 213022 /wp-admin/css/wp-admin.css
|
||||
31 3 5423 174 5040 180 6804 210931 /index
|
||||
10 0 429 42 429 42 18009 180093 /cuisine/files/2011/10/tarte_figue_amande-e1318281546905-225x300.jpg
|
||||
(cherry picked from commit 61aaad06e85ae7f46cf5589bce8bc7f9331e7962)
|
||||
---
|
||||
contrib/halog/halog.c | 39 ++++++++++++++++++++++++++++++++-------
|
||||
1 files changed, 32 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/contrib/halog/halog.c b/contrib/halog/halog.c
|
||||
index f19be0b..274b7f3 100644
|
||||
--- a/contrib/halog/halog.c
|
||||
+++ b/contrib/halog/halog.c
|
||||
@@ -29,6 +29,7 @@
|
||||
#define SERVER_FIELD 8
|
||||
#define TIME_FIELD 9
|
||||
#define STATUS_FIELD 10
|
||||
+#define BYTES_SENT_FIELD 11
|
||||
#define TERM_CODES_FIELD 14
|
||||
#define CONN_FIELD 15
|
||||
#define QUEUE_LEN_FIELD 16
|
||||
@@ -67,6 +68,7 @@ struct url_stat {
|
||||
char *url;
|
||||
unsigned long long total_time; /* sum(all reqs' times) */
|
||||
unsigned long long total_time_ok; /* sum(all OK reqs' times) */
|
||||
+ unsigned long long total_bytes_sent; /* sum(all bytes sent) */
|
||||
unsigned int nb_err, nb_req;
|
||||
};
|
||||
|
||||
@@ -94,8 +96,6 @@ struct url_stat {
|
||||
#define FILT_COUNT_URL_TAVG 0x040000
|
||||
#define FILT_COUNT_URL_TTOTO 0x080000
|
||||
#define FILT_COUNT_URL_TAVGO 0x100000
|
||||
-#define FILT_COUNT_URL_ANY (FILT_COUNT_URL_ONLY|FILT_COUNT_URL_COUNT|FILT_COUNT_URL_ERR| \
|
||||
- FILT_COUNT_URL_TTOT|FILT_COUNT_URL_TAVG|FILT_COUNT_URL_TTOTO|FILT_COUNT_URL_TAVGO)
|
||||
|
||||
#define FILT_HTTP_ONLY 0x200000
|
||||
#define FILT_TERM_CODE_NAME 0x400000
|
||||
@@ -106,6 +106,13 @@ struct url_stat {
|
||||
#define FILT_QUEUE_ONLY 0x4000000
|
||||
#define FILT_QUEUE_SRV_ONLY 0x8000000
|
||||
|
||||
+#define FILT_COUNT_URL_BAVG 0x10000000
|
||||
+#define FILT_COUNT_URL_BTOT 0x20000000
|
||||
+
|
||||
+#define FILT_COUNT_URL_ANY (FILT_COUNT_URL_ONLY|FILT_COUNT_URL_COUNT|FILT_COUNT_URL_ERR| \
|
||||
+ FILT_COUNT_URL_TTOT|FILT_COUNT_URL_TAVG|FILT_COUNT_URL_TTOTO|FILT_COUNT_URL_TAVGO| \
|
||||
+ FILT_COUNT_URL_BAVG|FILT_COUNT_URL_BTOT)
|
||||
+
|
||||
unsigned int filter = 0;
|
||||
unsigned int filter_invert = 0;
|
||||
const char *line;
|
||||
@@ -128,9 +135,10 @@ void usage(FILE *output, const char *msg)
|
||||
fprintf(output,
|
||||
"%s"
|
||||
"Usage: halog [-h|--help] for long help\n"
|
||||
- " halog [-q] [-c] [-v] {-gt|-pct|-st|-tc|-srv|-u|-uc|-ue|-ua|-ut|-uao|-uto}\n"
|
||||
+ " halog [-q] [-c]\n"
|
||||
+ " {-gt|-pct|-st|-tc|-srv|-u|-uc|-ue|-ua|-ut|-uao|-uto|-uba|-ubt}\n"
|
||||
" [-s <skip>] [-e|-E] [-H] [-rt|-RT <time>] [-ad <delay>] [-ac <count>]\n"
|
||||
- " [-Q|-QS] [-tcn|-TCN <termcode>] [ -hs|-HS [min][:[max]] ] < log\n"
|
||||
+ " [-v] [-Q|-QS] [-tcn|-TCN <termcode>] [ -hs|-HS [min][:[max]] ] < log\n"
|
||||
"\n",
|
||||
msg ? msg : ""
|
||||
);
|
||||
@@ -171,6 +179,7 @@ void help()
|
||||
" -u : by URL, -uc : request count, -ue : error count\n"
|
||||
" -ua : average response time, -uto : average total time\n"
|
||||
" -uao, -uto: average times computed on valid ('OK') requests\n"
|
||||
+ " -uba, -ubt: average bytes returned, total bytes returned\n"
|
||||
);
|
||||
exit(0);
|
||||
}
|
||||
@@ -632,6 +641,10 @@ int main(int argc, char **argv)
|
||||
filter |= FILT_COUNT_URL_TAVGO;
|
||||
else if (strcmp(argv[0], "-uto") == 0)
|
||||
filter |= FILT_COUNT_URL_TTOTO;
|
||||
+ else if (strcmp(argv[0], "-uba") == 0)
|
||||
+ filter |= FILT_COUNT_URL_BAVG;
|
||||
+ else if (strcmp(argv[0], "-ubt") == 0)
|
||||
+ filter |= FILT_COUNT_URL_BTOT;
|
||||
else if (strcmp(argv[0], "-o") == 0) {
|
||||
if (output_file)
|
||||
die("Fatal: output file name already specified.\n");
|
||||
@@ -1029,6 +1042,10 @@ int main(int argc, char **argv)
|
||||
ustat->node.val.key = ustat->total_time_ok;
|
||||
else if (filter & FILT_COUNT_URL_TAVGO)
|
||||
ustat->node.val.key = (ustat->nb_req - ustat->nb_err) ? ustat->total_time_ok / (ustat->nb_req - ustat->nb_err) : 0;
|
||||
+ else if (filter & FILT_COUNT_URL_BAVG)
|
||||
+ ustat->node.val.key = ustat->nb_req ? ustat->total_bytes_sent / ustat->nb_req : 0;
|
||||
+ else if (filter & FILT_COUNT_URL_BTOT)
|
||||
+ ustat->node.val.key = ustat->total_bytes_sent;
|
||||
else
|
||||
ustat->node.val.key = 0;
|
||||
|
||||
@@ -1038,19 +1055,21 @@ int main(int argc, char **argv)
|
||||
timers[0] = timers[1];
|
||||
}
|
||||
|
||||
- printf("#req err ttot tavg oktot okavg url\n");
|
||||
+ printf("#req err ttot tavg oktot okavg bavg btot url\n");
|
||||
|
||||
/* scan the tree in its reverse sorting order */
|
||||
node = eb_last(&timers[0]);
|
||||
while (node) {
|
||||
ustat = container_of(node, struct url_stat, node.url.node);
|
||||
- printf("%d %d %Ld %Ld %Ld %Ld %s\n",
|
||||
+ printf("%d %d %Ld %Ld %Ld %Ld %Ld %Ld %s\n",
|
||||
ustat->nb_req,
|
||||
ustat->nb_err,
|
||||
ustat->total_time,
|
||||
ustat->nb_req ? ustat->total_time / ustat->nb_req : 0,
|
||||
ustat->total_time_ok,
|
||||
(ustat->nb_req - ustat->nb_err) ? ustat->total_time_ok / (ustat->nb_req - ustat->nb_err) : 0,
|
||||
+ ustat->nb_req ? ustat->total_bytes_sent / ustat->nb_req : 0,
|
||||
+ ustat->total_bytes_sent,
|
||||
ustat->url);
|
||||
|
||||
node = eb_prev(node);
|
||||
@@ -1233,6 +1252,7 @@ void filter_count_url(const char *accept_field, const char *time_field, struct t
|
||||
struct ebpt_node *ebpt_old;
|
||||
const char *b, *e;
|
||||
int f, err, array[5];
|
||||
+ int val;
|
||||
|
||||
/* let's collect the response time */
|
||||
if (!time_field) {
|
||||
@@ -1276,12 +1296,16 @@ void filter_count_url(const char *accept_field, const char *time_field, struct t
|
||||
ustat->total_time = (array[3] >= 0) ? array[3] : array[4];
|
||||
ustat->total_time_ok = (array[3] >= 0) ? array[3] : 0;
|
||||
|
||||
+ e = field_start(e, BYTES_SENT_FIELD - TIME_FIELD + 1);
|
||||
+ val = str2ic(e);
|
||||
+ ustat->total_bytes_sent = val;
|
||||
+
|
||||
/* the line may be truncated because of a bad request or anything like this,
|
||||
* without a method. Also, if it does not begin with an quote, let's skip to
|
||||
* the next field because it's a capture. Let's fall back to the "method" itself
|
||||
* if there's nothing else.
|
||||
*/
|
||||
- e = field_start(e, METH_FIELD - TIME_FIELD + 1); // avg 100 ns per line
|
||||
+ e = field_start(e, METH_FIELD - BYTES_SENT_FIELD + 1);
|
||||
while (*e != '"' && *e) {
|
||||
/* Note: some syslog servers escape quotes ! */
|
||||
if (*e == '\\' && e[1] == '"')
|
||||
@@ -1324,6 +1348,7 @@ void filter_count_url(const char *accept_field, const char *time_field, struct t
|
||||
ustat_old->nb_err += ustat->nb_err;
|
||||
ustat_old->total_time += ustat->total_time;
|
||||
ustat_old->total_time_ok += ustat->total_time_ok;
|
||||
+ ustat_old->total_bytes_sent += ustat->total_bytes_sent;
|
||||
} else {
|
||||
ustat->url = ustat->node.url.key = strdup(ustat->node.url.key);
|
||||
ustat = NULL; /* node was used */
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,118 @@
|
||||
From b4d12bdacf6ff4cc96abaffb8c3e801f94a84de2 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Wed, 10 Oct 2012 10:26:22 +0200
|
||||
Subject: MINOR: halog: sort output by cookie code
|
||||
|
||||
It's sometimes useful to have the output sorted by cookie code to see
|
||||
the ratios of NI vs VN for example. This is now possible with -cc.
|
||||
(cherry picked from commit 8a09b663a829f7012c50743adaf3d29cc81700c5)
|
||||
---
|
||||
contrib/halog/halog.c | 36 +++++++++++++++++++++++++++++++++---
|
||||
1 files changed, 33 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/contrib/halog/halog.c b/contrib/halog/halog.c
|
||||
index 274b7f3..e4d62e9 100644
|
||||
--- a/contrib/halog/halog.c
|
||||
+++ b/contrib/halog/halog.c
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* haproxy log statistics reporter
|
||||
*
|
||||
- * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
|
||||
+ * Copyright 2000-2012 Willy Tarreau <w@1wt.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -113,6 +113,8 @@ struct url_stat {
|
||||
FILT_COUNT_URL_TTOT|FILT_COUNT_URL_TAVG|FILT_COUNT_URL_TTOTO|FILT_COUNT_URL_TAVGO| \
|
||||
FILT_COUNT_URL_BAVG|FILT_COUNT_URL_BTOT)
|
||||
|
||||
+#define FILT_COUNT_COOK_CODES 0x40000000
|
||||
+
|
||||
unsigned int filter = 0;
|
||||
unsigned int filter_invert = 0;
|
||||
const char *line;
|
||||
@@ -124,6 +126,7 @@ const char *fgets2(FILE *stream);
|
||||
|
||||
void filter_count_url(const char *accept_field, const char *time_field, struct timer **tptr);
|
||||
void filter_count_srv_status(const char *accept_field, const char *time_field, struct timer **tptr);
|
||||
+void filter_count_cook_codes(const char *accept_field, const char *time_field, struct timer **tptr);
|
||||
void filter_count_term_codes(const char *accept_field, const char *time_field, struct timer **tptr);
|
||||
void filter_count_status(const char *accept_field, const char *time_field, struct timer **tptr);
|
||||
void filter_graphs(const char *accept_field, const char *time_field, struct timer **tptr);
|
||||
@@ -136,7 +139,7 @@ void usage(FILE *output, const char *msg)
|
||||
"%s"
|
||||
"Usage: halog [-h|--help] for long help\n"
|
||||
" halog [-q] [-c]\n"
|
||||
- " {-gt|-pct|-st|-tc|-srv|-u|-uc|-ue|-ua|-ut|-uao|-uto|-uba|-ubt}\n"
|
||||
+ " {-cc|-gt|-pct|-st|-tc|-srv|-u|-uc|-ue|-ua|-ut|-uao|-uto|-uba|-ubt}\n"
|
||||
" [-s <skip>] [-e|-E] [-H] [-rt|-RT <time>] [-ad <delay>] [-ac <count>]\n"
|
||||
" [-v] [-Q|-QS] [-tcn|-TCN <termcode>] [ -hs|-HS [min][:[max]] ] < log\n"
|
||||
"\n",
|
||||
@@ -172,6 +175,7 @@ void help()
|
||||
" -c only report the number of lines that would have been printed\n"
|
||||
" -pct output connect and response times percentiles\n"
|
||||
" -st output number of requests per HTTP status code\n"
|
||||
+ " -cc output number of requests per cookie code (2 chars)\n"
|
||||
" -tc output number of requests per termination code (2 chars)\n"
|
||||
" -srv output statistics per server (time, requests, errors)\n"
|
||||
" -u* output statistics per URL (time, requests, errors)\n"
|
||||
@@ -595,6 +599,8 @@ int main(int argc, char **argv)
|
||||
filter |= FILT_COUNT_STATUS;
|
||||
else if (strcmp(argv[0], "-srv") == 0)
|
||||
filter |= FILT_COUNT_SRV_STATUS;
|
||||
+ else if (strcmp(argv[0], "-cc") == 0)
|
||||
+ filter |= FILT_COUNT_COOK_CODES;
|
||||
else if (strcmp(argv[0], "-tc") == 0)
|
||||
filter |= FILT_COUNT_TERM_CODES;
|
||||
else if (strcmp(argv[0], "-tcn") == 0) {
|
||||
@@ -676,6 +682,8 @@ int main(int argc, char **argv)
|
||||
line_filter = filter_graphs;
|
||||
else if (filter & FILT_COUNT_STATUS)
|
||||
line_filter = filter_count_status;
|
||||
+ else if (filter & FILT_COUNT_COOK_CODES)
|
||||
+ line_filter = filter_count_cook_codes;
|
||||
else if (filter & FILT_COUNT_TERM_CODES)
|
||||
line_filter = filter_count_term_codes;
|
||||
else if (filter & FILT_COUNT_SRV_STATUS)
|
||||
@@ -1005,7 +1013,7 @@ int main(int argc, char **argv)
|
||||
lines_out++;
|
||||
}
|
||||
}
|
||||
- else if (filter & FILT_COUNT_TERM_CODES) {
|
||||
+ else if (filter & (FILT_COUNT_TERM_CODES|FILT_COUNT_COOK_CODES)) {
|
||||
/* output all statuses in the form of <code> <occurrences> */
|
||||
n = eb32_first(&timers[0]);
|
||||
while (n) {
|
||||
@@ -1129,6 +1137,28 @@ void filter_count_status(const char *accept_field, const char *time_field, struc
|
||||
t2->count++;
|
||||
}
|
||||
|
||||
+void filter_count_cook_codes(const char *accept_field, const char *time_field, struct timer **tptr)
|
||||
+{
|
||||
+ struct timer *t2;
|
||||
+ const char *b;
|
||||
+ int val;
|
||||
+
|
||||
+ if (time_field)
|
||||
+ b = field_start(time_field, TERM_CODES_FIELD - TIME_FIELD + 1);
|
||||
+ else
|
||||
+ b = field_start(accept_field, TERM_CODES_FIELD - ACCEPT_FIELD + 1);
|
||||
+
|
||||
+ if (unlikely(!*b)) {
|
||||
+ truncated_line(linenum, line);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ val = 256 * b[2] + b[3];
|
||||
+
|
||||
+ t2 = insert_value(&timers[0], tptr, val);
|
||||
+ t2->count++;
|
||||
+}
|
||||
+
|
||||
void filter_count_term_codes(const char *accept_field, const char *time_field, struct timer **tptr)
|
||||
{
|
||||
struct timer *t2;
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,29 @@
|
||||
From 113e6626ca26de31e2523a5b197a5bac4ca73dcc Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Wed, 10 Oct 2012 13:41:52 +0200
|
||||
Subject: BUG/MINOR: halog: -ad/-ac report the correct number of output lines
|
||||
|
||||
There was a lines_out++ left from earlier code, causing each input
|
||||
line to be counted as an output line.
|
||||
|
||||
This fix also affects 1.4 and should be backported.
|
||||
(cherry picked from commit 0a706880160167f872247723c6a041eb31a20c29)
|
||||
---
|
||||
contrib/halog/halog.c | 1 -
|
||||
1 files changed, 0 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/contrib/halog/halog.c b/contrib/halog/halog.c
|
||||
index e4d62e9..8f7f04a 100644
|
||||
--- a/contrib/halog/halog.c
|
||||
+++ b/contrib/halog/halog.c
|
||||
@@ -1111,7 +1111,6 @@ void filter_accept_holes(const char *accept_field, const char *time_field, struc
|
||||
|
||||
t2 = insert_value(&timers[0], tptr, val);
|
||||
t2->count++;
|
||||
- lines_out++;
|
||||
return;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,27 @@
|
||||
From 1fd5d70b52a1d3b3f12e577cc158d0988e103f0d Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Wed, 10 Oct 2012 14:57:35 +0200
|
||||
Subject: BUG/MINOR: halog: fix help message for -ut/-uto
|
||||
|
||||
Erroneous copy-paste suggesting wrong option.
|
||||
(cherry picked from commit 4201df77df34492be89e9c720397ff66bc5775d9)
|
||||
---
|
||||
contrib/halog/halog.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/contrib/halog/halog.c b/contrib/halog/halog.c
|
||||
index 8f7f04a..4e3cfc4 100644
|
||||
--- a/contrib/halog/halog.c
|
||||
+++ b/contrib/halog/halog.c
|
||||
@@ -181,7 +181,7 @@ void help()
|
||||
" -u* output statistics per URL (time, requests, errors)\n"
|
||||
" Additional characters indicate the output sorting key :\n"
|
||||
" -u : by URL, -uc : request count, -ue : error count\n"
|
||||
- " -ua : average response time, -uto : average total time\n"
|
||||
+ " -ua : average response time, -ut : average total time\n"
|
||||
" -uao, -uto: average times computed on valid ('OK') requests\n"
|
||||
" -uba, -ubt: average bytes returned, total bytes returned\n"
|
||||
);
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,75 @@
|
||||
From 7a883f8542dffb7299a903eb9a82fed3980337fa Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Sat, 20 Oct 2012 10:38:09 +0200
|
||||
Subject: BUG/MEDIUM: http: set DONTWAIT on data when switching to tunnel mode
|
||||
|
||||
Jaroslaw Bojar diagnosed an issue when haproxy switches to tunnel mode
|
||||
after a transfer. The response data are sent with the MSG_MORE flag,
|
||||
causing them to be needlessly queued in the kernel. In order to fix this,
|
||||
we set the CF_NEVER_WAIT flag on the channels when switching to tunnel
|
||||
mode.
|
||||
|
||||
One issue remained with client-side keep-alive : if the response is sent
|
||||
before the end of the request, it suffers the same issue for the same
|
||||
reason. This is easily addressed by setting the CF_SEND_DONTWAIT flag
|
||||
on the channel when the response has been parsed and we're waiting for
|
||||
the other side.
|
||||
|
||||
The same issue is present in 1.4 so the fix must be backported.
|
||||
(cherry picked from commit fc47f91c9cc66e3652d98deab82d6e5fe3a59711)
|
||||
---
|
||||
src/proto_http.c | 10 ++++++++++
|
||||
1 files changed, 10 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/src/proto_http.c b/src/proto_http.c
|
||||
index dc65cbd..2ba38f1 100644
|
||||
--- a/src/proto_http.c
|
||||
+++ b/src/proto_http.c
|
||||
@@ -4178,6 +4178,7 @@ int http_sync_req_state(struct session *s)
|
||||
/* if any side switches to tunnel mode, the other one does too */
|
||||
buffer_auto_read(buf);
|
||||
txn->req.msg_state = HTTP_MSG_TUNNEL;
|
||||
+ buf->flags |= BF_NEVER_WAIT;
|
||||
goto wait_other_side;
|
||||
}
|
||||
|
||||
@@ -4211,6 +4212,7 @@ int http_sync_req_state(struct session *s)
|
||||
*/
|
||||
buffer_auto_read(buf);
|
||||
txn->req.msg_state = HTTP_MSG_TUNNEL;
|
||||
+ buf->flags |= BF_NEVER_WAIT;
|
||||
}
|
||||
|
||||
if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW)) {
|
||||
@@ -4297,6 +4299,7 @@ int http_sync_res_state(struct session *s)
|
||||
/* if any side switches to tunnel mode, the other one does too */
|
||||
buffer_auto_read(buf);
|
||||
txn->rsp.msg_state = HTTP_MSG_TUNNEL;
|
||||
+ buf->flags |= BF_NEVER_WAIT;
|
||||
goto wait_other_side;
|
||||
}
|
||||
|
||||
@@ -4334,6 +4337,7 @@ int http_sync_res_state(struct session *s)
|
||||
*/
|
||||
buffer_auto_read(buf);
|
||||
txn->rsp.msg_state = HTTP_MSG_TUNNEL;
|
||||
+ buf->flags |= BF_NEVER_WAIT;
|
||||
}
|
||||
|
||||
if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW)) {
|
||||
@@ -4379,6 +4383,12 @@ int http_sync_res_state(struct session *s)
|
||||
|
||||
wait_other_side:
|
||||
http_silent_debug(__LINE__, s);
|
||||
+
|
||||
+ /* We force the response to leave immediately if we're waiting for the
|
||||
+ * other side, since there is no pending shutdown to push it out.
|
||||
+ */
|
||||
+ if (!(buf->flags & BF_OUT_EMPTY))
|
||||
+ buf->flags |= BF_SEND_DONTWAIT;
|
||||
return txn->rsp.msg_state != old_state || buf->flags != old_flags;
|
||||
}
|
||||
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,42 @@
|
||||
From ce64f84c174fc65ea02f3f1cba2b3295c0b34198 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Fri, 26 Oct 2012 16:04:28 +0200
|
||||
Subject: BUG/MEDIUM: command-line option -D must have precedence over "debug"
|
||||
|
||||
From the beginning it has been said that -D must always be used on the
|
||||
command line from startup scripts so that haproxy does not accidentally
|
||||
stay in foreground when loaded from init script... Except that this has
|
||||
not been true for a long time now.
|
||||
|
||||
The fix is easy and must be backported to 1.4 too which is affected.
|
||||
(cherry picked from commit 772f0dd545eb3837e2bc794f4c4863663be3742c)
|
||||
---
|
||||
src/haproxy.c | 11 +++++++++--
|
||||
1 files changed, 9 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/haproxy.c b/src/haproxy.c
|
||||
index 2944462..ec481aa 100644
|
||||
--- a/src/haproxy.c
|
||||
+++ b/src/haproxy.c
|
||||
@@ -649,9 +649,16 @@ void init(int argc, char **argv)
|
||||
if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
|
||||
/* command line debug mode inhibits configuration mode */
|
||||
global.mode &= ~(MODE_DAEMON | MODE_QUIET);
|
||||
+ global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
|
||||
}
|
||||
- global.mode |= (arg_mode & (MODE_DAEMON | MODE_FOREGROUND | MODE_QUIET |
|
||||
- MODE_VERBOSE | MODE_DEBUG ));
|
||||
+
|
||||
+ if (arg_mode & MODE_DAEMON) {
|
||||
+ /* command line daemon mode inhibits foreground and debug modes mode */
|
||||
+ global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
|
||||
+ global.mode |= (arg_mode & MODE_DAEMON);
|
||||
+ }
|
||||
+
|
||||
+ global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
|
||||
|
||||
if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
|
||||
Warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,49 @@
|
||||
From 5b4d0775f0afd10c80e63842dca85a69281c9433 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Cyril=20Bont=C3=A9?= <cyril.bonte@free.fr>
|
||||
Date: Thu, 1 Nov 2012 18:48:23 +0100
|
||||
Subject: BUG: fix garbage data when http-send-name-header replaces an existing header
|
||||
|
||||
This patch is an attempt to prevent sending garbage data when
|
||||
http-send-name-header replaced existing headers in the request.
|
||||
|
||||
http-send-name-header is applied late in the request processing. The buffer is
|
||||
already ready to be sent to the backend server. When headers are removed, the
|
||||
data length is not modified, resulting in sending more data than required. By
|
||||
reducing the data length to send after removing them, this should fix the
|
||||
issue.
|
||||
|
||||
This patch doesn't need to be ported to haproxy-1.5, which already readjust the
|
||||
amount of data to be forwarded.
|
||||
|
||||
This issue was reported by Michael Seiferle at BaseX, who also tested and
|
||||
confirmed the fix.
|
||||
---
|
||||
src/proto_http.c | 5 +++++
|
||||
1 files changed, 5 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/src/proto_http.c b/src/proto_http.c
|
||||
index 2ba38f1..1ad838b 100644
|
||||
--- a/src/proto_http.c
|
||||
+++ b/src/proto_http.c
|
||||
@@ -3981,6 +3981,7 @@ int http_send_name_header(struct http_txn *txn, struct http_msg *msg, struct buf
|
||||
|
||||
char *hdr_val;
|
||||
|
||||
+ int delta = txn->req.eoh;
|
||||
while (http_find_header2(hdr_name, hdr_name_len, msg->sol, &txn->hdr_idx, &ctx)) {
|
||||
/* remove any existing values from the header */
|
||||
http_remove_header2(msg, buf, &txn->hdr_idx, &ctx);
|
||||
@@ -3994,6 +3995,10 @@ int http_send_name_header(struct http_txn *txn, struct http_msg *msg, struct buf
|
||||
*hdr_val++ = ' ';
|
||||
hdr_val += strlcpy2(hdr_val, srv_name, trash + trashlen - hdr_val);
|
||||
http_header_add_tail2(buf, msg, &txn->hdr_idx, trash, hdr_val - trash);
|
||||
+ delta -= txn->req.eoh;
|
||||
+
|
||||
+ /* Adjust buffer data length to send */
|
||||
+ buf->send_max -= delta;
|
||||
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
1.7.1
|
||||
|
@ -1,6 +1,6 @@
|
||||
--- a/doc/configuration.txt
|
||||
+++ b/doc/configuration.txt
|
||||
@@ -1337,6 +1337,7 @@ bind [<address>]:<port_range> [, ...] tr
|
||||
@@ -1339,6 +1339,7 @@ bind [<address>]:<port_range> [, ...] tr
|
||||
bind [<address>]:<port_range> [, ...] id <id>
|
||||
bind [<address>]:<port_range> [, ...] name <name>
|
||||
bind [<address>]:<port_range> [, ...] defer-accept
|
||||
@ -8,7 +8,7 @@
|
||||
Define one or several listening addresses and/or ports in a frontend.
|
||||
May be used in sections : defaults | frontend | listen | backend
|
||||
no | yes | yes | no
|
||||
@@ -1417,6 +1418,19 @@ bind [<address>]:<port_range> [, ...] de
|
||||
@@ -1419,6 +1420,19 @@ bind [<address>]:<port_range> [, ...] de
|
||||
with front firewalls which would see an established
|
||||
connection while the proxy will only see it in SYN_RECV.
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
It is possible to specify a list of address:port combinations delimited by
|
||||
commas. The frontend will then listen on all of these addresses. There is no
|
||||
fixed limit to the number of addresses and ports which can be listened on in
|
||||
@@ -1427,8 +1441,10 @@ bind [<address>]:<port_range> [, ...] de
|
||||
@@ -1429,8 +1443,10 @@ bind [<address>]:<port_range> [, ...] de
|
||||
listen http_proxy
|
||||
bind :80,:443
|
||||
bind 10.0.0.1:10080,10.0.0.1:10443
|
||||
@ -40,7 +40,7 @@
|
||||
|
||||
|
||||
bind-process [ all | odd | even | <number 1-32> ] ...
|
||||
@@ -7215,7 +7231,9 @@ marked with a star ('*') after the field
|
||||
@@ -7231,7 +7247,9 @@ marked with a star ('*') after the field
|
||||
|
||||
Detailed fields description :
|
||||
- "client_ip" is the IP address of the client which initiated the TCP
|
||||
@ -51,7 +51,7 @@
|
||||
|
||||
- "client_port" is the TCP port of the client which initiated the connection.
|
||||
|
||||
@@ -7388,7 +7406,9 @@ with a star ('*') after the field name b
|
||||
@@ -7404,7 +7422,9 @@ with a star ('*') after the field name b
|
||||
|
||||
Detailed fields description :
|
||||
- "client_ip" is the IP address of the client which initiated the TCP
|
||||
@ -152,7 +152,7 @@
|
||||
* socket. The listener provides the protocol-specific accept() function to
|
||||
--- a/src/cfgparse.c
|
||||
+++ b/src/cfgparse.c
|
||||
@@ -1466,6 +1466,16 @@ int cfg_parse_listen(const char *file, i
|
||||
@@ -1467,6 +1467,16 @@ int cfg_parse_listen(const char *file, i
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@
|
||||
if (!strcmp(args[cur_arg], "name")) {
|
||||
struct listener *l;
|
||||
|
||||
@@ -1518,7 +1528,7 @@ int cfg_parse_listen(const char *file, i
|
||||
@@ -1519,7 +1529,7 @@ int cfg_parse_listen(const char *file, i
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -178,7 +178,7 @@
|
||||
file, linenum, args[0]);
|
||||
err_code |= ERR_ALERT | ERR_FATAL;
|
||||
goto out;
|
||||
@@ -5731,6 +5741,9 @@ out_uri_auth_compat:
|
||||
@@ -5732,6 +5742,9 @@ out_uri_auth_compat:
|
||||
listener->handler = process_session;
|
||||
listener->analysers |= curproxy->fe_req_ana;
|
||||
|
||||
@ -392,7 +392,7 @@
|
||||
*/
|
||||
--- a/src/proto_http.c
|
||||
+++ b/src/proto_http.c
|
||||
@@ -4087,7 +4087,8 @@ void http_end_txn_clean_session(struct s
|
||||
@@ -4127,7 +4127,8 @@ void http_end_txn_clean_session(struct s
|
||||
if (s->rep->lr >= s->rep->data + s->rep->size)
|
||||
s->rep->lr -= s->req->size;
|
||||
|
||||
@ -402,7 +402,7 @@
|
||||
s->rep->analysers = 0;
|
||||
|
||||
http_silent_debug(__LINE__, s);
|
||||
@@ -7624,7 +7625,6 @@ void http_reset_txn(struct session *s)
|
||||
@@ -7670,7 +7671,6 @@ void http_reset_txn(struct session *s)
|
||||
http_init_txn(s);
|
||||
|
||||
s->be = s->fe;
|
||||
|
@ -0,0 +1,54 @@
|
||||
From c998e6347e6e6940263157fb341a8444d789aa5f Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Tue, 3 Jan 2012 09:23:03 +0100
|
||||
Subject: OPTIM: halog: keep a fast path for the lines-count only
|
||||
|
||||
[ note: this backport is not absolutely required for 1.4 but it eases
|
||||
further backports ]
|
||||
|
||||
Using "halog -c" is still something quite common to perform on logs,
|
||||
but unfortunately since the recent added controls, it was sensibly
|
||||
slowed down due to the parsing of the accept date field.
|
||||
|
||||
Now we use a specific loop for the case where nothing is needed from
|
||||
the input, and this sped up the line counting by 2.5x. A 2.4 GHz Xeon
|
||||
now counts lines at a rate of 2 GB of logs per second.
|
||||
|
||||
(cherry picked from commit e1a908c369ab988448c6672066ad1d09b6919d02)
|
||||
---
|
||||
contrib/halog/halog.c | 12 +++++++++++-
|
||||
1 files changed, 11 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/contrib/halog/halog.c b/contrib/halog/halog.c
|
||||
index 4e3cfc4..3912807 100644
|
||||
--- a/contrib/halog/halog.c
|
||||
+++ b/contrib/halog/halog.c
|
||||
@@ -702,6 +702,16 @@ int main(int argc, char **argv)
|
||||
posix_fadvise(0, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
#endif
|
||||
|
||||
+ if (!line_filter &&
|
||||
+ !(filter & (FILT_HTTP_ONLY|FILT_TIME_RESP|FILT_ERRORS_ONLY|FILT_HTTP_STATUS|FILT_QUEUE_ONLY|FILT_QUEUE_SRV_ONLY|FILT_TERM_CODE_NAME))) {
|
||||
+ /* read the whole file at once first */
|
||||
+ if (!filter_invert)
|
||||
+ while (fgets2(stdin) != NULL)
|
||||
+ lines_out++;
|
||||
+
|
||||
+ goto skip_filters;
|
||||
+ }
|
||||
+
|
||||
while ((line = fgets2(stdin)) != NULL) {
|
||||
linenum++;
|
||||
time_field = NULL; accept_field = NULL;
|
||||
@@ -859,7 +869,7 @@ int main(int argc, char **argv)
|
||||
lines_out++; /* we're just counting lines */
|
||||
}
|
||||
|
||||
-
|
||||
+ skip_filters:
|
||||
/*****************************************************
|
||||
* Here we've finished reading all input. Depending on the
|
||||
* filters, we may still have some analysis to run on the
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,134 @@
|
||||
From 9f03ab8e3ec603f2aed944a7887bcdf7be52009a Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Wed, 10 Oct 2012 16:49:28 +0200
|
||||
Subject: MINOR: halog: add a parameter to limit output line count
|
||||
|
||||
Sometimes it's useful to limit the output to a number of lines, for
|
||||
example when output is already sorted (eg: 10 slowest URLs, ...). Now
|
||||
we can use -m for this.
|
||||
(cherry picked from commit 667c905fe5153a8754bd8177c80dd9e6c245a0b0)
|
||||
[ this patch introduces a but that is fixed by commit a1629a59 ]
|
||||
---
|
||||
contrib/halog/halog.c | 28 ++++++++++++++++++++++++----
|
||||
1 files changed, 24 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/contrib/halog/halog.c b/contrib/halog/halog.c
|
||||
index 3912807..7e16cd5 100644
|
||||
--- a/contrib/halog/halog.c
|
||||
+++ b/contrib/halog/halog.c
|
||||
@@ -121,6 +121,7 @@ const char *line;
|
||||
int linenum = 0;
|
||||
int parse_err = 0;
|
||||
int lines_out = 0;
|
||||
+int lines_max = -1;
|
||||
|
||||
const char *fgets2(FILE *stream);
|
||||
|
||||
@@ -138,7 +139,7 @@ void usage(FILE *output, const char *msg)
|
||||
fprintf(output,
|
||||
"%s"
|
||||
"Usage: halog [-h|--help] for long help\n"
|
||||
- " halog [-q] [-c]\n"
|
||||
+ " halog [-q] [-c] [-m <lines>]\n"
|
||||
" {-cc|-gt|-pct|-st|-tc|-srv|-u|-uc|-ue|-ua|-ut|-uao|-uto|-uba|-ubt}\n"
|
||||
" [-s <skip>] [-e|-E] [-H] [-rt|-RT <time>] [-ad <delay>] [-ac <count>]\n"
|
||||
" [-v] [-Q|-QS] [-tcn|-TCN <termcode>] [ -hs|-HS [min][:[max]] ] < log\n"
|
||||
@@ -170,7 +171,7 @@ void help()
|
||||
"Modifiers\n"
|
||||
" -v invert the input filtering condition\n"
|
||||
" -q don't report errors/warnings\n"
|
||||
- "\n"
|
||||
+ " -m <lines> limit output to the first <lines> lines\n"
|
||||
"Output filters - only one may be used at a time\n"
|
||||
" -c only report the number of lines that would have been printed\n"
|
||||
" -pct output connect and response times percentiles\n"
|
||||
@@ -575,6 +576,11 @@ int main(int argc, char **argv)
|
||||
argc--; argv++;
|
||||
skip_fields = atol(*argv);
|
||||
}
|
||||
+ else if (strcmp(argv[0], "-m") == 0) {
|
||||
+ if (argc < 2) die("missing option for -m");
|
||||
+ argc--; argv++;
|
||||
+ lines_max = atol(*argv);
|
||||
+ }
|
||||
else if (strcmp(argv[0], "-e") == 0)
|
||||
filter |= FILT_ERRORS_ONLY;
|
||||
else if (strcmp(argv[0], "-E") == 0)
|
||||
@@ -702,7 +708,7 @@ int main(int argc, char **argv)
|
||||
posix_fadvise(0, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
#endif
|
||||
|
||||
- if (!line_filter &&
|
||||
+ if (!line_filter && lines_max >= 0 &&
|
||||
!(filter & (FILT_HTTP_ONLY|FILT_TIME_RESP|FILT_ERRORS_ONLY|FILT_HTTP_STATUS|FILT_QUEUE_ONLY|FILT_QUEUE_SRV_ONLY|FILT_TERM_CODE_NAME))) {
|
||||
/* read the whole file at once first */
|
||||
if (!filter_invert)
|
||||
@@ -867,6 +873,8 @@ int main(int argc, char **argv)
|
||||
line_filter(accept_field, time_field, &t);
|
||||
else
|
||||
lines_out++; /* we're just counting lines */
|
||||
+ if (lines_out >= lines_max)
|
||||
+ break;
|
||||
}
|
||||
|
||||
skip_filters:
|
||||
@@ -904,8 +912,10 @@ int main(int argc, char **argv)
|
||||
ms = h % 1000; h = h / 1000;
|
||||
s = h % 60; h = h / 60;
|
||||
m = h % 60; h = h / 60;
|
||||
- lines_out++;
|
||||
printf("%02d:%02d:%02d.%03d %d %d %d\n", h, m, s, ms, last, d, t->count);
|
||||
+ lines_out++;
|
||||
+ if (lines_out >= lines_max)
|
||||
+ break;
|
||||
}
|
||||
n = eb32_next(n);
|
||||
}
|
||||
@@ -937,6 +947,8 @@ int main(int argc, char **argv)
|
||||
if (d > 0.0) {
|
||||
printf("%d %d %f\n", f, last, d+1.0);
|
||||
lines_out++;
|
||||
+ if (lines_out >= lines_max)
|
||||
+ break;
|
||||
}
|
||||
|
||||
n = eb32_next(n);
|
||||
@@ -994,6 +1006,8 @@ int main(int argc, char **argv)
|
||||
t = container_of(n, struct timer, node);
|
||||
printf("%d %d\n", n->key, t->count);
|
||||
lines_out++;
|
||||
+ if (lines_out >= lines_max)
|
||||
+ break;
|
||||
n = eb32_next(n);
|
||||
}
|
||||
}
|
||||
@@ -1021,6 +1035,8 @@ int main(int argc, char **argv)
|
||||
(int)(srv->cum_ct / (srv->nb_ct?srv->nb_ct:1)), (int)(srv->cum_rt / (srv->nb_rt?srv->nb_rt:1)));
|
||||
srv_node = ebmb_next(srv_node);
|
||||
lines_out++;
|
||||
+ if (lines_out >= lines_max)
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
else if (filter & (FILT_COUNT_TERM_CODES|FILT_COUNT_COOK_CODES)) {
|
||||
@@ -1030,6 +1046,8 @@ int main(int argc, char **argv)
|
||||
t = container_of(n, struct timer, node);
|
||||
printf("%c%c %d\n", (n->key >> 8), (n->key) & 255, t->count);
|
||||
lines_out++;
|
||||
+ if (lines_out >= lines_max)
|
||||
+ break;
|
||||
n = eb32_next(n);
|
||||
}
|
||||
}
|
||||
@@ -1092,6 +1110,8 @@ int main(int argc, char **argv)
|
||||
|
||||
node = eb_prev(node);
|
||||
lines_out++;
|
||||
+ if (lines_out >= lines_max)
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,110 @@
|
||||
From e1e14b5d2a0ff3097c93f4605f33b38df1e3e266 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Tue, 13 Nov 2012 20:48:15 +0100
|
||||
Subject: BUG: halog: fix broken output limitation
|
||||
|
||||
Commit 667c905f introduced parameter -m to halog which limits the size
|
||||
of the output. Unfortunately it is completely broken in that it doesn't
|
||||
check that the limit was previously set or not, and also prevents a
|
||||
simple counting operation from returning anything if a limit is not set.
|
||||
|
||||
Note that the -gt and -pct outputs behave differently in face of this
|
||||
limit, since they count the valid output lines BEFORE actually producing
|
||||
the data, so the limit really applies to valid input lines.
|
||||
(cherry picked from commit a1629a59d17208897622d4e0d8ecddf157d55074)
|
||||
---
|
||||
contrib/halog/halog.c | 26 +++++++++++---------------
|
||||
1 files changed, 11 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/contrib/halog/halog.c b/contrib/halog/halog.c
|
||||
index 7e16cd5..61034ec 100644
|
||||
--- a/contrib/halog/halog.c
|
||||
+++ b/contrib/halog/halog.c
|
||||
@@ -708,11 +708,11 @@ int main(int argc, char **argv)
|
||||
posix_fadvise(0, 0, 0, POSIX_FADV_SEQUENTIAL);
|
||||
#endif
|
||||
|
||||
- if (!line_filter && lines_max >= 0 &&
|
||||
+ if (!line_filter && /* FILT_COUNT_ONLY ( see above), and no input filter (see below) */
|
||||
!(filter & (FILT_HTTP_ONLY|FILT_TIME_RESP|FILT_ERRORS_ONLY|FILT_HTTP_STATUS|FILT_QUEUE_ONLY|FILT_QUEUE_SRV_ONLY|FILT_TERM_CODE_NAME))) {
|
||||
- /* read the whole file at once first */
|
||||
+ /* read the whole file at once first, ignore it if inverted output */
|
||||
if (!filter_invert)
|
||||
- while (fgets2(stdin) != NULL)
|
||||
+ while ((lines_max < 0 || lines_out < lines_max) && fgets2(stdin) != NULL)
|
||||
lines_out++;
|
||||
|
||||
goto skip_filters;
|
||||
@@ -872,8 +872,8 @@ int main(int argc, char **argv)
|
||||
if (line_filter)
|
||||
line_filter(accept_field, time_field, &t);
|
||||
else
|
||||
- lines_out++; /* we're just counting lines */
|
||||
- if (lines_out >= lines_max)
|
||||
+ lines_out++; /* FILT_COUNT_ONLY was used, so we're just counting lines */
|
||||
+ if (lines_max >= 0 && lines_out >= lines_max)
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -914,7 +914,7 @@ int main(int argc, char **argv)
|
||||
m = h % 60; h = h / 60;
|
||||
printf("%02d:%02d:%02d.%03d %d %d %d\n", h, m, s, ms, last, d, t->count);
|
||||
lines_out++;
|
||||
- if (lines_out >= lines_max)
|
||||
+ if (lines_max >= 0 && lines_out >= lines_max)
|
||||
break;
|
||||
}
|
||||
n = eb32_next(n);
|
||||
@@ -944,12 +944,8 @@ int main(int argc, char **argv)
|
||||
else
|
||||
d = val;
|
||||
|
||||
- if (d > 0.0) {
|
||||
+ if (d > 0.0)
|
||||
printf("%d %d %f\n", f, last, d+1.0);
|
||||
- lines_out++;
|
||||
- if (lines_out >= lines_max)
|
||||
- break;
|
||||
- }
|
||||
|
||||
n = eb32_next(n);
|
||||
}
|
||||
@@ -1006,7 +1002,7 @@ int main(int argc, char **argv)
|
||||
t = container_of(n, struct timer, node);
|
||||
printf("%d %d\n", n->key, t->count);
|
||||
lines_out++;
|
||||
- if (lines_out >= lines_max)
|
||||
+ if (lines_max >= 0 && lines_out >= lines_max)
|
||||
break;
|
||||
n = eb32_next(n);
|
||||
}
|
||||
@@ -1035,7 +1031,7 @@ int main(int argc, char **argv)
|
||||
(int)(srv->cum_ct / (srv->nb_ct?srv->nb_ct:1)), (int)(srv->cum_rt / (srv->nb_rt?srv->nb_rt:1)));
|
||||
srv_node = ebmb_next(srv_node);
|
||||
lines_out++;
|
||||
- if (lines_out >= lines_max)
|
||||
+ if (lines_max >= 0 && lines_out >= lines_max)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1046,7 +1042,7 @@ int main(int argc, char **argv)
|
||||
t = container_of(n, struct timer, node);
|
||||
printf("%c%c %d\n", (n->key >> 8), (n->key) & 255, t->count);
|
||||
lines_out++;
|
||||
- if (lines_out >= lines_max)
|
||||
+ if (lines_max >= 0 && lines_out >= lines_max)
|
||||
break;
|
||||
n = eb32_next(n);
|
||||
}
|
||||
@@ -1110,7 +1106,7 @@ int main(int argc, char **argv)
|
||||
|
||||
node = eb_prev(node);
|
||||
lines_out++;
|
||||
- if (lines_out >= lines_max)
|
||||
+ if (lines_max >= 0 && lines_out >= lines_max)
|
||||
break;
|
||||
}
|
||||
}
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,91 @@
|
||||
From 2f61455a647d9539a49392d475e7f2aeef7dcfce Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Sat, 29 Dec 2012 22:23:02 +0100
|
||||
Subject: MEDIUM: checks: avoid accumulating TIME_WAITs during checks
|
||||
|
||||
Some checks which do not induce a close from the server accumulate
|
||||
local TIME_WAIT sockets because they're cleanly shut down. Typically
|
||||
TCP probes cause this. This is very problematic when there are many
|
||||
servers, when the checks are fast or when local source ports are rare.
|
||||
|
||||
So now we'll disable lingering on the socket instead of sending a
|
||||
shutdown. Before doing this we try to drain any possibly pending data.
|
||||
That way we avoid sending an RST when the server has closed first.
|
||||
|
||||
This change means that some servers will see more RSTs, but this is
|
||||
needed to avoid local source port starvation.
|
||||
(cherry picked from commit fd29cc537b8511db6e256529ded625c8e7f856d0)
|
||||
---
|
||||
src/checks.c | 22 +++++++++++++++++-----
|
||||
1 files changed, 17 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/src/checks.c b/src/checks.c
|
||||
index 0aa65c0..3d01282 100644
|
||||
--- a/src/checks.c
|
||||
+++ b/src/checks.c
|
||||
@@ -833,6 +833,10 @@ static int event_srv_chk_w(int fd)
|
||||
|
||||
/* good TCP connection is enough */
|
||||
set_server_check_status(s, HCHK_STATUS_L4OK, NULL);
|
||||
+
|
||||
+ /* avoid accumulating TIME_WAIT on connect-only checks */
|
||||
+ setsockopt(fd, SOL_SOCKET, SO_LINGER,
|
||||
+ (struct linger *) &nolinger, sizeof(struct linger));
|
||||
goto out_wakeup;
|
||||
}
|
||||
}
|
||||
@@ -877,7 +881,7 @@ static int event_srv_chk_r(int fd)
|
||||
struct task *t = fdtab[fd].owner;
|
||||
struct server *s = t->context;
|
||||
char *desc;
|
||||
- int done;
|
||||
+ int done, shutr;
|
||||
unsigned short msglen;
|
||||
|
||||
if (unlikely((s->result & SRV_CHK_ERROR) || (fdtab[fd].state == FD_STERROR))) {
|
||||
@@ -898,7 +902,7 @@ static int event_srv_chk_r(int fd)
|
||||
* with running the checks without attempting another socket read.
|
||||
*/
|
||||
|
||||
- done = 0;
|
||||
+ done = shutr = 0;
|
||||
for (len = 0; s->check_data_len < global.tune.chksize; s->check_data_len += len) {
|
||||
len = recv(fd, s->check_data + s->check_data_len, global.tune.chksize - s->check_data_len, 0);
|
||||
if (len <= 0)
|
||||
@@ -906,14 +910,14 @@ static int event_srv_chk_r(int fd)
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
- done = 1; /* connection hangup received */
|
||||
+ done = shutr = 1; /* connection hangup received */
|
||||
else if (len < 0 && errno != EAGAIN) {
|
||||
/* Report network errors only if we got no other data. Otherwise
|
||||
* we'll let the upper layers decide whether the response is OK
|
||||
* or not. It is very common that an RST sent by the server is
|
||||
* reported as an error just after the last data chunk.
|
||||
*/
|
||||
- done = 1;
|
||||
+ done = shutr = 1;
|
||||
if (!s->check_data_len) {
|
||||
if (!(s->result & SRV_CHK_ERROR))
|
||||
set_server_check_status(s, HCHK_STATUS_SOCKERR, NULL);
|
||||
@@ -1162,7 +1166,15 @@ static int event_srv_chk_r(int fd)
|
||||
*s->check_data = '\0';
|
||||
s->check_data_len = 0;
|
||||
|
||||
- /* Close the connection... */
|
||||
+ /* Close the connection... We absolutely want to perform a hard close
|
||||
+ * and reset the connection if some data are pending, otherwise we end
|
||||
+ * up with many TIME_WAITs and eat all the source port range quickly.
|
||||
+ * To avoid sending RSTs all the time, we first try to drain pending
|
||||
+ * data.
|
||||
+ */
|
||||
+ if (!shutr && recv(fd, trash, trashlen, MSG_NOSIGNAL|MSG_DONTWAIT) > 0)
|
||||
+ setsockopt(fd, SOL_SOCKET, SO_LINGER,
|
||||
+ (struct linger *) &nolinger, sizeof(struct linger));
|
||||
shutdown(fd, SHUT_RDWR);
|
||||
EV_FD_CLR(fd, DIR_RD);
|
||||
task_wakeup(t, TASK_WOKEN_IO);
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,29 @@
|
||||
From 4ee19c30abdd962fbc10f65c45a5f1615cda3059 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Fri, 23 Nov 2012 17:35:59 +0100
|
||||
Subject: MEDIUM: checks: prevent TIME_WAITs from appearing also on timeouts
|
||||
|
||||
We need to disable lingering before closing on timeout too, otherwise
|
||||
we accumulate TIME_WAITs.
|
||||
(cherry picked from commit cfd97c6f043fb64980529a0ce26b10fecd0e8fe2)
|
||||
---
|
||||
src/checks.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/src/checks.c b/src/checks.c
|
||||
index 3d01282..201900a 100644
|
||||
--- a/src/checks.c
|
||||
+++ b/src/checks.c
|
||||
@@ -1527,6 +1527,9 @@ struct task *process_chk(struct task *t)
|
||||
else
|
||||
set_server_down(s);
|
||||
s->curfd = -1;
|
||||
+ /* avoid accumulating TIME_WAIT on timeouts */
|
||||
+ setsockopt(fd, SOL_SOCKET, SO_LINGER,
|
||||
+ (struct linger *) &nolinger, sizeof(struct linger));
|
||||
fd_delete(fd);
|
||||
|
||||
rv = 0;
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,55 @@
|
||||
From 475b5ec3be8e022bd0f96331efc14c7b7b137d60 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Mon, 26 Nov 2012 02:22:40 +0100
|
||||
Subject: BUG/MAJOR: cli: show sess <id> may randomly corrupt the back-ref list
|
||||
|
||||
show sess <id> puts a backref into the session it's dumping. If the output
|
||||
is interrupted, the backref cannot always be removed because it's only done
|
||||
in the I/O handler. This can randomly corrupt the backref list when the
|
||||
session closes, because it passes the pointer to the next session which
|
||||
itself might be watched.
|
||||
|
||||
The case is hard to reproduce (hundreds of attempts) but monitoring systems
|
||||
might encounter it frequently.
|
||||
|
||||
Thus we have to add a release handler which does the cleanup even when the
|
||||
I/O handler is not called.
|
||||
|
||||
This issue should also be present in 1.4 so the patch should be backported.
|
||||
(cherry picked from commit 5f9a8779b3d4fb324dacc1daacfb478bd12963d1)
|
||||
|
||||
NOTE: In 1.4 there is no release function so we have to hard-code the
|
||||
release in session.c when the condition is encountered.
|
||||
---
|
||||
src/session.c | 15 +++++++++++++++
|
||||
1 files changed, 15 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/src/session.c b/src/session.c
|
||||
index 0f6a1cf..239d4f5 100644
|
||||
--- a/src/session.c
|
||||
+++ b/src/session.c
|
||||
@@ -989,6 +989,21 @@ resync_stream_interface:
|
||||
if (may_dequeue_tasks(s->srv, s->be))
|
||||
process_srv_queue(s->srv);
|
||||
}
|
||||
+
|
||||
+ if (s->req->cons->iohandler == stats_io_handler &&
|
||||
+ s->req->cons->st0 == STAT_CLI_O_SESS && s->data_state == DATA_ST_LIST) {
|
||||
+ /* This is a fix for a design bug in the stats I/O handler :
|
||||
+ * "show sess $sess" may corrupt the struct session if not
|
||||
+ * properly detached. Unfortunately, in 1.4 there is no way
|
||||
+ * to ensure we always cleanly unregister an I/O handler upon
|
||||
+ * error. So we're doing the cleanup here if we can detect the
|
||||
+ * situation.
|
||||
+ */
|
||||
+ if (!LIST_ISEMPTY(&s->data_ctx.sess.bref.users)) {
|
||||
+ LIST_DEL(&s->data_ctx.sess.bref.users);
|
||||
+ LIST_INIT(&s->data_ctx.sess.bref.users);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,86 @@
|
||||
From 46169a35f95f2128bbf185c06eb535d9acb7ee61 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Mon, 26 Nov 2012 13:35:37 +0100
|
||||
Subject: BUG/MINOR: http: don't report client aborts as server errors
|
||||
|
||||
If a client aborts with an abortonclose flag, the close is forwarded
|
||||
to the server and when server response is processed, the analyser thinks
|
||||
it's the server who has closed first, and logs flags "SD" or "SH" and
|
||||
counts a server error. In order to avoid this, we now first detect that
|
||||
the client has closed and log a client abort instead.
|
||||
|
||||
This likely is the reason why many people have been observing a small rate
|
||||
of SD/SH flags without being able to find what the error was.
|
||||
|
||||
This fix should probably be backported to 1.4.
|
||||
(cherry picked from commit f003d375ec5190e7d99cfa14a9b09e7ca6c55daf)
|
||||
---
|
||||
src/proto_http.c | 37 +++++++++++++++++++++++++++++++++----
|
||||
1 files changed, 33 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/proto_http.c b/src/proto_http.c
|
||||
index 1ad838b..ae37035 100644
|
||||
--- a/src/proto_http.c
|
||||
+++ b/src/proto_http.c
|
||||
@@ -4919,6 +4919,28 @@ int http_wait_for_response(struct session *s, struct buffer *rep, int an_bit)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ /* client abort with an abortonclose */
|
||||
+ else if ((rep->flags & BF_SHUTR) && ((s->req->flags & (BF_SHUTR|BF_SHUTW)) == (BF_SHUTR|BF_SHUTW))) {
|
||||
+ s->fe->counters.cli_aborts++;
|
||||
+ if (s->fe != s->be)
|
||||
+ s->be->counters.cli_aborts++;
|
||||
+ if (s->srv)
|
||||
+ s->srv->counters.cli_aborts++;
|
||||
+
|
||||
+ buffer_auto_close(rep);
|
||||
+ rep->analysers = 0;
|
||||
+ txn->status = 400;
|
||||
+ buffer_ignore(rep, rep->l - rep->send_max);
|
||||
+ stream_int_retnclose(rep->cons, error_message(s, HTTP_ERR_400));
|
||||
+
|
||||
+ if (!(s->flags & SN_ERR_MASK))
|
||||
+ s->flags |= SN_ERR_CLICL;
|
||||
+ if (!(s->flags & SN_FINST_MASK))
|
||||
+ s->flags |= SN_FINST_H;
|
||||
+ /* process_session() will take care of the error */
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
/* close from server, capture the response if the server has started to respond */
|
||||
else if (rep->flags & BF_SHUTR) {
|
||||
if (msg->msg_state >= HTTP_MSG_RPVER || msg->err_pos >= 0)
|
||||
@@ -5666,8 +5688,18 @@ int http_response_forward_body(struct session *s, struct buffer *res, int an_bit
|
||||
}
|
||||
|
||||
missing_data:
|
||||
- /* stop waiting for data if the input is closed before the end */
|
||||
+
|
||||
+ if (res->flags & BF_SHUTW)
|
||||
+ goto aborted_xfer;
|
||||
+
|
||||
+ /* stop waiting for data if the input is closed before the end. If the
|
||||
+ * client side was already closed, it means that the client has aborted,
|
||||
+ * so we don't want to count this as a server abort. Otherwise it's a
|
||||
+ * server abort.
|
||||
+ */
|
||||
if (res->flags & BF_SHUTR) {
|
||||
+ if ((res->flags & BF_SHUTW_NOW) || (s->req->flags & BF_SHUTR))
|
||||
+ goto aborted_xfer;
|
||||
if (!(s->flags & SN_ERR_MASK))
|
||||
s->flags |= SN_ERR_SRVCL;
|
||||
s->be->counters.srv_aborts++;
|
||||
@@ -5676,9 +5708,6 @@ int http_response_forward_body(struct session *s, struct buffer *res, int an_bit
|
||||
goto return_bad_res_stats_ok;
|
||||
}
|
||||
|
||||
- if (res->flags & BF_SHUTW)
|
||||
- goto aborted_xfer;
|
||||
-
|
||||
/* we need to obey the req analyser, so if it leaves, we must too */
|
||||
if (!s->req->analysers)
|
||||
goto return_bad_res;
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,31 @@
|
||||
From e856a82ac64d2fea6d2117627a9c857aca738bb0 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Tue, 4 Dec 2012 10:39:01 +0100
|
||||
Subject: BUG/MINOR: http: don't log a 503 on client errors while waiting for requests
|
||||
|
||||
If a client aborts a request with an error (typically a TCP reset), we must
|
||||
log a 400. Till now we did not set the status nor close the stream interface,
|
||||
causing the request to attempt to be forwarded and logging a 503.
|
||||
|
||||
Should be backported to 1.4 which is affected as well.
|
||||
(cherry picked from commit dc979f24929ad5352832730954c83ba47afe24cc)
|
||||
---
|
||||
src/proto_http.c | 2 ++
|
||||
1 files changed, 2 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/src/proto_http.c b/src/proto_http.c
|
||||
index ae37035..7a8872b 100644
|
||||
--- a/src/proto_http.c
|
||||
+++ b/src/proto_http.c
|
||||
@@ -2506,6 +2506,8 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit)
|
||||
if (msg->err_pos >= 0)
|
||||
http_capture_bad_message(&s->fe->invalid_req, s, req, msg, msg->msg_state, s->fe);
|
||||
|
||||
+ txn->status = 400;
|
||||
+ stream_int_retnclose(req->prod, NULL);
|
||||
msg->msg_state = HTTP_MSG_ERROR;
|
||||
req->analysers = 0;
|
||||
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,58 @@
|
||||
From 307227061df9938e9db5c0880254d71f2b9f5e83 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Sat, 8 Dec 2012 23:03:28 +0100
|
||||
Subject: BUG/MEDIUM: tcp: process could theorically crash on lack of source ports
|
||||
|
||||
When connect() fails with EAGAIN or EADDRINUSE, an error message is
|
||||
sent to logs and uses srv->id to indicate the server name (this is
|
||||
very old code). Since version 1.4, it is possible to have srv == NULL,
|
||||
so the message could cause a crash when connect() returns EAGAIN or
|
||||
EADDRINUSE. However in practice this does not happen because on lack
|
||||
of source ports, EADDRNOTAVAIL is returned instead, so this code is
|
||||
never called.
|
||||
|
||||
This fix consists in not displaying the server name anymore, and in
|
||||
adding the test for EADDRNOTAVAIL.
|
||||
|
||||
Also, the log level was lowered from LOG_EMERG to LOG_ERR in order
|
||||
not to spam all consoles when source ports are missing for a given
|
||||
target.
|
||||
|
||||
This fix should be backported to 1.4.
|
||||
(cherry picked from commit b1719517b754aa0a098ee0f9c59e8babaf8df384)
|
||||
---
|
||||
src/proto_tcp.c | 10 ++++------
|
||||
1 files changed, 4 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
|
||||
index 84fda20..e876d71 100644
|
||||
--- a/src/proto_tcp.c
|
||||
+++ b/src/proto_tcp.c
|
||||
@@ -376,20 +376,18 @@ int tcpv4_connect_server(struct stream_interface *si,
|
||||
if ((connect(fd, (struct sockaddr *)srv_addr, sizeof(struct sockaddr_in)) == -1) &&
|
||||
(errno != EINPROGRESS) && (errno != EALREADY) && (errno != EISCONN)) {
|
||||
|
||||
- if (errno == EAGAIN || errno == EADDRINUSE) {
|
||||
+ if (errno == EAGAIN || errno == EADDRINUSE || errno == EADDRNOTAVAIL) {
|
||||
char *msg;
|
||||
- if (errno == EAGAIN) /* no free ports left, try again later */
|
||||
+ if (errno == EAGAIN || errno == EADDRNOTAVAIL)
|
||||
msg = "no free ports";
|
||||
else
|
||||
msg = "local address already in use";
|
||||
|
||||
- qfprintf(stderr,"Cannot connect: %s.\n",msg);
|
||||
+ qfprintf(stderr,"Connect() failed for backend %s: %s.\n", be->id, msg);
|
||||
port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port);
|
||||
fdinfo[fd].port_range = NULL;
|
||||
close(fd);
|
||||
- send_log(be, LOG_EMERG,
|
||||
- "Connect() failed for server %s/%s: %s.\n",
|
||||
- be->id, srv->id, msg);
|
||||
+ send_log(be, LOG_ERR, "Connect() failed for backend %s: %s.\n", be->id, msg);
|
||||
return SN_ERR_RESOURCE;
|
||||
} else if (errno == ETIMEDOUT) {
|
||||
//qfprintf(stderr,"Connect(): ETIMEDOUT");
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,45 @@
|
||||
From dc624fd282caae163b11c197b36851e0ecf373eb Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Thu, 20 Dec 2012 12:10:09 +0100
|
||||
Subject: BUG/MINOR: http: don't abort client connection on premature responses
|
||||
|
||||
When a server responds prematurely to a POST request, haproxy used to
|
||||
cause the transfer to be aborted before the end. This is problematic
|
||||
because this causes the client to receive a TCP reset when it tries to
|
||||
push more data, generally preventing it from receiving the response
|
||||
which contain the reason for the premature reponse (eg: "entity too
|
||||
large" or an authentication request).
|
||||
|
||||
From now on we take care of allowing the upload traffic to flow to the
|
||||
server even when the response has been received, since the server is
|
||||
supposed to drain it. That way the client receives the server response.
|
||||
|
||||
This bug has been present since 1.4 and the fix should probably be
|
||||
backported there.
|
||||
(cherry picked from commit 40f151aa79bcdf8b517c4e5666edbc7a47ea7fdc)
|
||||
|
||||
Note: 1.4 does not have SI_FL_NOHALF but this is not important.
|
||||
---
|
||||
src/proto_http.c | 5 +++--
|
||||
1 files changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/proto_http.c b/src/proto_http.c
|
||||
index 7a8872b..e4cec6d 100644
|
||||
--- a/src/proto_http.c
|
||||
+++ b/src/proto_http.c
|
||||
@@ -4443,9 +4443,10 @@ int http_resync_states(struct session *s)
|
||||
buffer_auto_close(s->rep);
|
||||
buffer_auto_read(s->rep);
|
||||
}
|
||||
- else if (txn->rsp.msg_state == HTTP_MSG_CLOSED ||
|
||||
+ else if ((txn->req.msg_state >= HTTP_MSG_DONE &&
|
||||
+ (txn->rsp.msg_state == HTTP_MSG_CLOSED || (s->rep->flags & BF_SHUTW))) ||
|
||||
txn->rsp.msg_state == HTTP_MSG_ERROR ||
|
||||
- (s->rep->flags & BF_SHUTW)) {
|
||||
+ txn->req.msg_state == HTTP_MSG_ERROR) {
|
||||
s->rep->analysers = 0;
|
||||
buffer_auto_close(s->rep);
|
||||
buffer_auto_read(s->rep);
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,28 @@
|
||||
From 24a528b3f5f09cdd9aebeb9531d7e76623329070 Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Thu, 20 Dec 2012 15:00:44 +0100
|
||||
Subject: BUILD: no need to clean up when making git-tar
|
||||
|
||||
git-tar uses the repository, not the working dir, so it's useless to
|
||||
run "make clean" first.
|
||||
(cherry picked from commit 05ed29cf6ef1eb6268c95c5d38af849c487eeedd)
|
||||
---
|
||||
Makefile | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 9350d54..7633588 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -584,7 +584,7 @@ tar: clean
|
||||
-cf - haproxy-$(VERSION)/* | gzip -c9 >haproxy-$(VERSION).tar.gz
|
||||
rm -f haproxy-$(VERSION)
|
||||
|
||||
-git-tar: clean
|
||||
+git-tar:
|
||||
git archive --format=tar --prefix="haproxy-$(VERSION)/" HEAD | gzip -9 > haproxy-$(VERSION)$(SUBVERS).tar.gz
|
||||
|
||||
version:
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,30 @@
|
||||
From 528595f5989ef3af64c3e480ae15363677812aaa Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Sun, 30 Dec 2012 00:27:36 +0100
|
||||
Subject: MINOR: http: always report PR-- flags for redirect rules
|
||||
|
||||
Mainline commit 71241abf fixed a minor issue by which keep-alive requests
|
||||
causing a redirect did not have the PR-- flags while close requests did
|
||||
have it. This patch merges this part of the change which fixes the flags.
|
||||
---
|
||||
src/proto_http.c | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/src/proto_http.c b/src/proto_http.c
|
||||
index e4cec6d..ffa2224 100644
|
||||
--- a/src/proto_http.c
|
||||
+++ b/src/proto_http.c
|
||||
@@ -3476,6 +3476,10 @@ int http_process_req_common(struct session *s, struct buffer *req, int an_bit, s
|
||||
s->rep->analysers = AN_RES_HTTP_XFER_BODY;
|
||||
txn->req.msg_state = HTTP_MSG_CLOSED;
|
||||
txn->rsp.msg_state = HTTP_MSG_DONE;
|
||||
+ if (!(s->flags & SN_ERR_MASK))
|
||||
+ s->flags |= SN_ERR_PRXCOND;
|
||||
+ if (!(s->flags & SN_FINST_MASK))
|
||||
+ s->flags |= SN_FINST_R;
|
||||
break;
|
||||
} else {
|
||||
/* keep-alive not possible */
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,124 @@
|
||||
From 44db294666f9dfb68667f998532781e898f14c4f Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Sat, 29 Dec 2012 21:50:07 +0100
|
||||
Subject: BUG/MINOR: time: frequency counters are not totally accurate
|
||||
|
||||
When a frontend is rate-limited to 1000 connections per second, the
|
||||
effective rate measured from the client is 999/s, and connections
|
||||
experience an average response time of 99.5 ms with a standard
|
||||
deviation of 2 ms.
|
||||
|
||||
The reason for this inaccuracy is that when computing frequency
|
||||
counters, we use one part of the previous value proportional to the
|
||||
number of milliseconds remaining in the current second. But even the
|
||||
last millisecond still uses a part of the past value, which is wrong :
|
||||
since we have a 1ms resolution, the last millisecond must be dedicated
|
||||
only to filling the current second.
|
||||
|
||||
So we slightly adjust the algorithm to use 999/1000 of the past value
|
||||
during the first millisecond, and 0/1000 of the past value during the
|
||||
last millisecond. We also slightly improve the computation by computing
|
||||
the remaining time instead of the current time in tv_update_date(), so
|
||||
that we don't have to negate the value in each frequency counter.
|
||||
|
||||
Now with the fix, the connection rate measured by both the client and
|
||||
haproxy is a steady 1000/s, the average response time measured is 99.2ms
|
||||
and more importantly, the standard deviation has been divided by 3 to
|
||||
0.6 millisecond.
|
||||
|
||||
This fix should also be backported to 1.4 which has the same issue.
|
||||
(cherry picked from commit eab777c32eff7ee55a6ea12dd2f15fa14d66f233)
|
||||
---
|
||||
include/common/time.h | 1 +
|
||||
src/freq_ctr.c | 7 +++----
|
||||
src/time.c | 16 +++++++++++++---
|
||||
3 files changed, 17 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/include/common/time.h b/include/common/time.h
|
||||
index abc1ccf..c9e3641 100644
|
||||
--- a/include/common/time.h
|
||||
+++ b/include/common/time.h
|
||||
@@ -55,6 +55,7 @@
|
||||
#define SETNOW(a) (*a=now)
|
||||
|
||||
extern unsigned int curr_sec_ms; /* millisecond of current second (0..999) */
|
||||
+extern unsigned int ms_left_scaled; /* milliseconds left for current second (0..2^32-1) */
|
||||
extern unsigned int curr_sec_ms_scaled; /* millisecond of current second (0..2^32-1) */
|
||||
extern unsigned int now_ms; /* internal date in milliseconds (may wrap) */
|
||||
extern struct timeval now; /* internal date is a monotonic function of real clock */
|
||||
diff --git a/src/freq_ctr.c b/src/freq_ctr.c
|
||||
index 3df930f..8718b60 100644
|
||||
--- a/src/freq_ctr.c
|
||||
+++ b/src/freq_ctr.c
|
||||
@@ -47,7 +47,7 @@ unsigned int read_freq_ctr(struct freq_ctr *ctr)
|
||||
if (past <= 1 && !curr)
|
||||
return past; /* very low rate, avoid flapping */
|
||||
|
||||
- return curr + mul32hi(past, ~curr_sec_ms_scaled);
|
||||
+ return curr + mul32hi(past, ms_left_scaled);
|
||||
}
|
||||
|
||||
/* returns the number of remaining events that can occur on this freq counter
|
||||
@@ -59,7 +59,6 @@ unsigned int freq_ctr_remain(struct freq_ctr *ctr, unsigned int freq, unsigned i
|
||||
unsigned int curr, past;
|
||||
unsigned int age;
|
||||
|
||||
- past = 0;
|
||||
curr = 0;
|
||||
age = now.tv_sec - ctr->curr_sec;
|
||||
|
||||
@@ -69,7 +68,7 @@ unsigned int freq_ctr_remain(struct freq_ctr *ctr, unsigned int freq, unsigned i
|
||||
curr = past;
|
||||
past = ctr->prev_ctr;
|
||||
}
|
||||
- curr += mul32hi(past, ~curr_sec_ms_scaled);
|
||||
+ curr += mul32hi(past, ms_left_scaled);
|
||||
}
|
||||
curr += pend;
|
||||
|
||||
@@ -99,7 +98,7 @@ unsigned int next_event_delay(struct freq_ctr *ctr, unsigned int freq, unsigned
|
||||
curr = past;
|
||||
past = ctr->prev_ctr;
|
||||
}
|
||||
- curr += mul32hi(past, ~curr_sec_ms_scaled);
|
||||
+ curr += mul32hi(past, ms_left_scaled);
|
||||
}
|
||||
curr += pend;
|
||||
|
||||
diff --git a/src/time.c b/src/time.c
|
||||
index 1b0f72c..342be9d 100644
|
||||
--- a/src/time.c
|
||||
+++ b/src/time.c
|
||||
@@ -16,8 +16,8 @@
|
||||
#include <common/standard.h>
|
||||
#include <common/time.h>
|
||||
|
||||
-unsigned int curr_sec_ms; /* millisecond of current second (0..999) */
|
||||
-unsigned int curr_sec_ms_scaled; /* millisecond of current second (0..2^32-1) */
|
||||
+unsigned int curr_sec_ms; /* millisecond of current second (0..999) */
|
||||
+unsigned int ms_left_scaled; /* milliseconds left for current second (0..2^32-1) */
|
||||
unsigned int now_ms; /* internal date in milliseconds (may wrap) */
|
||||
struct timeval now; /* internal date is a monotonic function of real clock */
|
||||
struct timeval date; /* the real current date */
|
||||
@@ -195,7 +195,17 @@ REGPRM2 void tv_update_date(int max_wait, int interrupted)
|
||||
to_ms:
|
||||
now = adjusted;
|
||||
curr_sec_ms = now.tv_usec / 1000; /* ms of current second */
|
||||
- curr_sec_ms_scaled = curr_sec_ms * 4294971; /* ms * 2^32 / 1000 */
|
||||
+
|
||||
+ /* For frequency counters, we'll need to know the ratio of the previous
|
||||
+ * value to add to current value depending on the current millisecond.
|
||||
+ * The principle is that during the first millisecond, we use 999/1000
|
||||
+ * of the past value and that during the last millisecond we use 0/1000
|
||||
+ * of the past value. In summary, we only use the past value during the
|
||||
+ * first 999 ms of a second, and the last ms is used to complete the
|
||||
+ * current measure. The value is scaled to (2^32-1) so that a simple
|
||||
+ * multiply followed by a shift gives us the final value.
|
||||
+ */
|
||||
+ ms_left_scaled = (999U - curr_sec_ms) * 4294967U;
|
||||
now_ms = now.tv_sec * 1000 + curr_sec_ms;
|
||||
return;
|
||||
}
|
||||
--
|
||||
1.7.1
|
||||
|
@ -0,0 +1,35 @@
|
||||
From d978423607b6666ca8dd3257d860558ead1b94af Mon Sep 17 00:00:00 2001
|
||||
From: Willy Tarreau <w@1wt.eu>
|
||||
Date: Sun, 30 Dec 2012 00:50:35 +0100
|
||||
Subject: BUG/MINOR: http: don't process abortonclose when request was sent
|
||||
|
||||
option abortonclose may cause a valid connection to be aborted just
|
||||
after the request has been sent. This is because we check for it
|
||||
during the session establishment sequence before checking for write
|
||||
activity. So if the abort and the connect complete at the same time,
|
||||
the abort is still considered. Let's check for an explicity partial
|
||||
write before aborting.
|
||||
|
||||
This fix should be backported to 1.4 too.
|
||||
(cherry picked from commit a7a7ebc38280d7a04192bf95e6852222f4bd8140)
|
||||
---
|
||||
src/session.c | 3 ++-
|
||||
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/src/session.c b/src/session.c
|
||||
index 239d4f5..6211a45 100644
|
||||
--- a/src/session.c
|
||||
+++ b/src/session.c
|
||||
@@ -203,7 +203,8 @@ int sess_update_st_con_tcp(struct session *s, struct stream_interface *si)
|
||||
}
|
||||
|
||||
/* OK, maybe we want to abort */
|
||||
- if (unlikely((rep->flags & BF_SHUTW) ||
|
||||
+ if (!(req->flags & BF_WRITE_PARTIAL) &&
|
||||
+ unlikely((rep->flags & BF_SHUTW) ||
|
||||
((req->flags & BF_SHUTW_NOW) && /* FIXME: this should not prevent a connection from establishing */
|
||||
(((req->flags & (BF_OUT_EMPTY|BF_WRITE_ACTIVITY)) == BF_OUT_EMPTY) ||
|
||||
s->be->options & PR_O_ABRT_CLOSE)))) {
|
||||
--
|
||||
1.7.1
|
||||
|
Loading…
x
Reference in New Issue
Block a user