Re: [PATCH] fix #660

2020-07-15 Thread Willy Tarreau
On Thu, Jul 16, 2020 at 02:06:48AM +0500,  ??? wrote:
> I attached only the first patch at a time.

Patch applied, thanks Ilya!
Willy



Plaintext HTTP/2 and HTTP/1.1 in the same proxy with HAproxy 2.2

2020-07-15 Thread James Brown
Hello everybody:

I'm experimenting a bit with plaintext HTTP/2 backends (for gRPC ) and
encountering some weird issues. My goal is to be able to support etcd,
which multiplexes a normal good API on HTTP/1.1 with a gRPC API on HTTP/2
on the same plaintext port. I'm doing my testing on HAproxy 2.2.0 so that I
can get the PRI upgrade support.

In order to pass through HTTP/2 to the backend, it seems like I need "proto
h2" on the `server` line? Otherwise I see that the frontend connection is
HTTP/2 and the backend connection is HTTP/1.1 (verified with tcpdump on the
load balancer and the backend), which does not work for the gRPC use case.
Is this expected? One would think that the h2-upgrade functionality would
upgrade both the frontend *and* the backend connection. And, of course,
when "proto h2" is on the server line, HTTP/1.1 requests fail entirely.

As an aside: when "proto h2" is on the server line, is there any way to do
a healthcheck with HTTP/1.1? It is... very annoying to construct a gRPC
healthcheck message using the http-check send language, but the -vvv output
indicates that there's no way to pass a non-h2 proto.

I have no inclination to provision thousands of TLS certificates for all
these internal use-cases and would love to just get HTTP/2 working over
plaintext, but it kind of seems like even under HAproxy 2.2 this is still
not really functional.

Initial config looks something like the following:

frontend sys-etcd_fe
mode http
option http-buffer-request
option httplog
option log-separate-errors
timeout client 9s
timeout client-fin 12s
bind ::1:26462
default_backend sys-etcd_be

backend sys-etcd_be
mode http
option forwardfor
option redispatch
retries 3
timeout connect 4s
timeout server 90s
timeout tunnel 3600s
server host1 10.132.15.129:26462 weight 16

This works fine for HTTP/1.1 but cannot be used to transit gRPC traffic
because it doesn't support plaintext HTTP/2. Even if the client connects
with HTTP/2 (e.g., with --http2 in curl, or with a gRPC client), that only
affects the frontend connection, not the backend connection.

The following config passes HTTP/2 but does not work for HTTP/1.1 at all:

frontend sys-etcd_fe
mode http
option http-buffer-request
option httplog
option log-separate-errors
timeout client 9s
timeout client-fin 12s
bind ::1:26462
default_backend sys-etcd_be

backend sys-etcd_be
mode http
option forwardfor
option redispatch
retries 3
http-check connect proto h2
http-check send meth POST uri /etcdserverpb.Maintenance/Status body
"0" ver HTTP/2 hdr Host etcd hdr Content-Type application/grpc
http-check expect status 200
timeout connect 4s
timeout server 90s
timeout tunnel 3600s
server host1 10.132.15.129:26462 weight 16 proto h2 check


This is the best config I've got so far, which feels like it shouldn't
work, but does:


frontend sys-etcd_fe
mode http
option http-buffer-request
option httplog
option log-separate-errors
timeout client 9s
timeout client-fin 12s
bind ::1:26462
use_backend sys-etcd_be_h2 if { fc_http_major eq 2 }
default_backend sys-etcd_be_h1

backend sys-etc_be_h1
mode http
option forwardfor
option redispatch
option httpchk /health
retries 3
timeout connect 4s
timeout server 90s
timeout tunnel 3600s
server host1 10.132.15.129:26462 weight 16 check

backend sys-etcd_be_h2
mode http
option forwardfor
option redispatch
retries 3
http-check connect proto h2
http-check send meth POST uri /etcdserverpb.Maintenance/Status body
"0" ver HTTP/2 hdr Host etcd hdr Content-Type application/grpc
http-check expect status 200
timeout connect 4s
timeout server 90s
timeout tunnel 3600s
server host1 10.132.15.129:26462 weight 16 proto h2 check

HAproxy version output:


$ /usr/sbin/haproxy  -vvv
HA-Proxy version 2.2.0 2020/07/07 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2
2025.
Known bugs: http://www.haproxy.org/bugs/bugs-2.2.0.html
Running on: Linux 5.4.15-1ep.el6.x86_64 #1 SMP Mon Jan 27 17:13:12 UTC 2020
x86_64
Build options :
  TARGET  = linux-glibc
  CPU = generic
  CC  = gcc
  CFLAGS  = -m64 -march=x86-64 -O2 -g -Wall -Wextra
-Wdeclaration-after-statement -fwrapv -Wno-unused-label -Wno-sign-compare
-Wno-unused-parameter -Wno-clobbered -Wno-missing-field-initializers
-Wtype-limits
  OPTIONS = USE_PCRE=1 USE_OPENSSL=1 USE_LUA=1 USE_ZLIB=1 USE_TFO=1 USE_NS=

Feature list : +EPOLL -KQUEUE +NETFILTER +PCRE -PCRE_JIT -PCRE2 -PCRE2_JIT
+POLL -PRIVATE_CACHE +THREAD -PTHREAD_PSHARED +BACKTRACE -STATIC_PCRE
-STATIC_PCRE2 +TPROXY +LINUX_TPROXY +LINUX_SPLICE +LIBCRYPT +CRYPT_H
+GETADDRINFO +OPENSSL +LUA +FUTEX +ACCEPT4 +ZLIB -SLZ +CPU_AFFINITY +TFO
-NS +DL +RT -DEVICEATLAS -51DEGREES -WURFL -SYSTEMD -OBSOLETE_LINKER +PRCTL
+THREAD_DUMP -EVPORTS

Default 

Re: [PATCH] fix #660

2020-07-15 Thread Илья Шипицин
I attached only the first patch at a time.

ср, 15 июл. 2020 г. в 13:08, Илья Шипицин :

>
>
> ср, 15 июл. 2020 г. в 12:00, Willy Tarreau :
>
>> Hi Ilya,
>>
>> > From 4f62799eba5db5fe6400d458877677f098da3b13 Mon Sep 17 00:00:00 2001
>> > From: Ilya Shipitsin 
>> > Date: Sun, 12 Jul 2020 15:24:55 +0500
>> > Subject: [PATCH] src/server.c: add extra guards when loading state file
>> >
>> > this should fix #660
>> >
>> > we can only load 'local' state file, if file is corrupted,
>> > we should check filepath against NULL
>> >
>> > also, global server state file should be properly closed upon read.
>> > otherwise, it might leak on haproxy reload.
>> >
>> > when reading global server state file we should check string lenght,
>> > if file was corrupted we might observe overflow otherwise.
>>
>> So do I understand it right that there are actually two unrelated, or
>> maybe even three bugs there ? If so, please always take care of splitting
>> them (one fix per bug) so that they could be independently reviewed and
>> backported as needed (or sometimes possibly reverted if the fix causes
>> unexpected breakage).
>>
>> > ---
>> >  src/server.c | 9 ++---
>> >  1 file changed, 6 insertions(+), 3 deletions(-)
>> >
>> > diff --git a/src/server.c b/src/server.c
>> > index 05b19d4e1..54239c63c 100644
>> > --- a/src/server.c
>> > +++ b/src/server.c
>> > @@ -3265,6 +3265,7 @@ void apply_server_state(void)
>> >   /* free up memory in case of error during the
>> processing of the line */
>> >   free(line);
>> >   }
>> > + fclose(f);
>> >   }
>> >   out_load_server_state_in_tree:
>>
>> I had a look at the patch in its context and this will still leak in the
>> case where global_file_version == 0.
>>
>> The right way to do it would instead to add this after this label
>> "out_load_server_state_in_tree" :
>>
>> if (f) {
>> fclose(f);
>> f = NULL;
>> }
>>
>> > @@ -3360,6 +3361,8 @@ void apply_server_state(void)
>> >   goto next;
>> >
>> >   st = container_of(node, struct
>> state_line, name_name);
>> > + if (strlen(st->line) >
>> SRV_STATE_LINE_MAXLEN)
>> > + goto next;
>>
>> So from what I'm seeing elsewhere in the code, this test will never match:
>> a line is read using fgets() with a size of SRV_STATE_LINE_MAXLEN (hence
>> it
>> will always read one less char), and it is passed to
>> srv_state_parse_line()
>> which returns an error when the '\n' is missing, hence the line is skipped
>> and never indexed, so this cannot happen at all.
>>
>> >   memcpy(mybuf, st->line, strlen(st->line));
>> >   mybuf[strlen(st->line)] = 0;
>> >
>> > @@ -3375,7 +3378,7 @@ void apply_server_state(void)
>> >
>> >   continue; /* next proxy in list */
>> >   }
>> > - else {
>> > + else if (filepath) {
>>
>> Is it a third issue ? The whole code is hard to follow for me but what is
>> the exact case you've tried to address here ? Looking through the code, it
>> looks like we could land there when the local file name is too large (but
>> apparently there is no error handling for this where this path name is
>> constructed) :-/
>>
>> >   /* load 'local' state file */
>> >   errno = 0;
>> >   f = fopen(filepath, "r");
>> > @@ -3447,9 +3450,9 @@ void apply_server_state(void)
>> >   /* now we can proceed with server's state
>> update */
>> >   srv_update_state(srv, version,
>> srv_params);
>> >   }
>> > + fileclose:
>> > + fclose(f);
>> >   }
>> > -fileclose:
>> > - fclose(f);
>> >   }
>>
>> I agree, this one definitely makes sense!
>>
>
>
> I will address comments today or tomorrow
>
>
>>
>> Thanks!
>> Willy
>>
>
From 8c231a2a3b776a623f64b9fe496b3667a4af4bfb Mon Sep 17 00:00:00 2001
From: Ilya Shipitsin 
Date: Thu, 16 Jul 2020 02:02:40 +0500
Subject: [PATCH] BUG/MEDIUM: src/server.c: resolve file handle leak on reload

during reload, server state file is read and file handle is not released
this was indepently reported in #738 and #660

partially resolves #660
---
 src/server.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/src/server.c b/src/server.c
index 05b19d4e1..bd3dcf886 100644
--- a/src/server.c
+++ b/src/server.c
@@ -3268,6 +3268,11 @@ void apply_server_state(void)
 	}
  out_load_server_state_in_tree:
 
+	if (f) {
+		fclose(f);
+		f = NULL;
+	}
+
 	/* parse all proxies and load states form tree (global file) or from local file */
 	for (curproxy = proxies_list; curproxy != NULL; curproxy = curproxy->next) {
 		/* servers are only in backends */
@@ 

[PATCH] DOC/MINOR: haproxy: Add description which delimiter is used for h1-case-adjust-file

2020-07-15 Thread Aleksandar Lazic

Hi.

This patch is a proposal to add the to the doc the delimiter for 
h1-case-adjust-file.

Regards

Aleks

>From d1b1061a54bb254c722cdfc984cde3466eabf5a1 Mon Sep 17 00:00:00 2001
From: Alex 
Date: Wed, 15 Jul 2020 21:31:18 +0200
Subject: [PATCH] DOC/MINOR: haproxy: Add description which delimiter is used for
 h1-case-adjust-file

---
 doc/configuration.txt | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/doc/configuration.txt b/doc/configuration.txt
index 2a4672b05..6c2e9f4b6 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -907,14 +907,15 @@ h1-case-adjust  
   "option h1-case-adjust-bogus-server".
 
 h1-case-adjust-file 
-  Defines a file containing a list of key/value pairs used to adjust the case
-  of some header names before sending them to HTTP/1 clients or servers. The
-  file  must contain 2 header names per line. The first one must be
-  in lower case and both must not differ except for their case. Lines which
-  start with '#' are ignored, just like empty lines. Leading and trailing tabs
-  and spaces are stripped. Duplicate entries are not allowed. Please note that
-  no transformation will be applied unless "option h1-case-adjust-bogus-client"
-  or "option h1-case-adjust-bogus-server" is specified in a proxy.
+  Defines a file containing a list of key/value pairs separated by spaces 
+  used to adjust the case of some header names before sending them to HTTP/1 
+  clients or servers. The file  must contain 2 header names per 
+  line separated by spaces. The first one must be in lower case and both must 
+  not differ except for their case. Lines which start with '#' are ignored, 
+  just like empty lines. Leading and trailing tabs and spaces are stripped. 
+  Duplicate entries are not allowed. Please note that no transformation will be
+  applied unless "option h1-case-adjust-bogus-client" or 
+  "option h1-case-adjust-bogus-server" is specified in a proxy.
 
   If this directive is repeated, only the last one will be processed.  It is an
   alternative to the directive "h1-case-adjust" if a lot of header names need
-- 
2.20.1



[PATCH] BUG/MEDIUM: fcgi-app: fix memory leak in fcgi_flt_http_headers

2020-07-15 Thread Harris Kaufmann

When the loop is continued early, the memory for param_rule is not freed. This
can leak memory per request, which will eventually consume all available memory
on the server.
---
 src/fcgi-app.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/fcgi-app.c b/src/fcgi-app.c
index d7285bfa6..412584c66 100644
--- a/src/fcgi-app.c
+++ b/src/fcgi-app.c
@@ -448,8 +448,10 @@ static int fcgi_flt_http_headers(struct stream *s, struct 
filter *filter, struct

b_reset(value);
value->data = build_logline(s, value->area, value->size, 
param_rule->value);
-   if (!value->data)
+   if (!value->data) {
+   pool_free(pool_head_fcgi_param_rule, param_rule);
continue;
+   }
if (!http_add_header(htx, param_rule->name, ist2(value->area, 
value->data)))
goto rewrite_err;
pool_free(pool_head_fcgi_param_rule, param_rule);
--
2.27.0



Re: proposing a haproxy 2.0.16 release (was [BUG] haproxy retries dispatch to wrong server)

2020-07-15 Thread Christopher Faulet




Am 11.07.20 um 00:03 schrieb Tim Düsterhus:

Lukas,

Am 10.07.20 um 21:04 schrieb Lukas Tribus:

I finally pushed this fix in the 2.0. Note the same bug affected the HTTP proxy
mode (using http_proxy option). In this case, the connection retries is now
disabled (on the 2.0 only) because the destination address is definitely lost.
It was the easiest way to work around the bug without backporting a bunch of
sensitive patches from the 2.1.


Given the importance and impact of this bug you just fixed (at least 5
independent people already reported it on GH and ML) and the amount of
other important fixes already in the tree (including at least one
crash fix), I'm suggesting to release 2.0.16. Unless there are other
important open bugs with ongoing troubleshooting?




Agreed. With 2.2 being released this is a good opportunity to release
updates for all branches down to 1.9 at least to properly mark the
latter as EoL.

I'd also appreciate at least backports happening without a release for
1.6 and 1.7, allowing us to close off old, fixed, issues on GitHub.


Bumping this.



Fully agree. I will try to emit the 2.0.16 this Friday. For the backports in 
older versions, it is probably a good idea too. We just need some time to do so. 
No promise on this point :)


--
Christopher Faulet



Re: proposing a haproxy 2.0.16 release (was [BUG] haproxy retries dispatch to wrong server)

2020-07-15 Thread Tim Düsterhus
William,
Christopher,

Am 11.07.20 um 00:03 schrieb Tim Düsterhus:
> Lukas,
> 
> Am 10.07.20 um 21:04 schrieb Lukas Tribus:
>>> I finally pushed this fix in the 2.0. Note the same bug affected the HTTP 
>>> proxy
>>> mode (using http_proxy option). In this case, the connection retries is now
>>> disabled (on the 2.0 only) because the destination address is definitely 
>>> lost.
>>> It was the easiest way to work around the bug without backporting a bunch of
>>> sensitive patches from the 2.1.
>>
>> Given the importance and impact of this bug you just fixed (at least 5
>> independent people already reported it on GH and ML) and the amount of
>> other important fixes already in the tree (including at least one
>> crash fix), I'm suggesting to release 2.0.16. Unless there are other
>> important open bugs with ongoing troubleshooting?
>>
>>
> 
> Agreed. With 2.2 being released this is a good opportunity to release
> updates for all branches down to 1.9 at least to properly mark the
> latter as EoL.
> 
> I'd also appreciate at least backports happening without a release for
> 1.6 and 1.7, allowing us to close off old, fixed, issues on GitHub.

Bumping this.

Best regards
Tim Düsterhus



Re: Handling of pidfile in daemon and master-worker mode

2020-07-15 Thread Willy Tarreau
Hi Takeshi,

On Sat, Jul 11, 2020 at 04:44:41PM +, mizuta.take...@fujitsu.com wrote:
> If multiple haproxy are started under these specifications, the behavior as:
> 
>  - in daemon mode
> 
>Run  /usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid,
>then /usr/sbin/haproxy -D -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid.
> 
> - The pidfile created by the former is overwritten by the latter.
> - The contents of the pidfile are pids for the latter nbproc.
> - The haproxy processes have been started for both the former and the 
> latter.
(...)

But this is not the correct behavior, I mean, you're not supposed to be
purposely starting multiple processes in parallel on a same pid file. Same
for the master-worker mode.

The purpose of the pidfile is to be usable to send the reload signal from
external tools or scripts, so the second process is expected to have either
-sf or -st .

Now if you're talking about a case where it is run by accident, this is
different, but in this case the pidfile is not the right way to address
such operational mistakes. One of them is to set "noreuseport" on a bind
line to prevent the new process from binding to the same address as the
old one. In this case the new process will fail to start and your pidfile
remains safe.

Hoping this helps,
Willy



Re: [PATCH] fix #660

2020-07-15 Thread Илья Шипицин
ср, 15 июл. 2020 г. в 12:00, Willy Tarreau :

> Hi Ilya,
>
> > From 4f62799eba5db5fe6400d458877677f098da3b13 Mon Sep 17 00:00:00 2001
> > From: Ilya Shipitsin 
> > Date: Sun, 12 Jul 2020 15:24:55 +0500
> > Subject: [PATCH] src/server.c: add extra guards when loading state file
> >
> > this should fix #660
> >
> > we can only load 'local' state file, if file is corrupted,
> > we should check filepath against NULL
> >
> > also, global server state file should be properly closed upon read.
> > otherwise, it might leak on haproxy reload.
> >
> > when reading global server state file we should check string lenght,
> > if file was corrupted we might observe overflow otherwise.
>
> So do I understand it right that there are actually two unrelated, or
> maybe even three bugs there ? If so, please always take care of splitting
> them (one fix per bug) so that they could be independently reviewed and
> backported as needed (or sometimes possibly reverted if the fix causes
> unexpected breakage).
>
> > ---
> >  src/server.c | 9 ++---
> >  1 file changed, 6 insertions(+), 3 deletions(-)
> >
> > diff --git a/src/server.c b/src/server.c
> > index 05b19d4e1..54239c63c 100644
> > --- a/src/server.c
> > +++ b/src/server.c
> > @@ -3265,6 +3265,7 @@ void apply_server_state(void)
> >   /* free up memory in case of error during the
> processing of the line */
> >   free(line);
> >   }
> > + fclose(f);
> >   }
> >   out_load_server_state_in_tree:
>
> I had a look at the patch in its context and this will still leak in the
> case where global_file_version == 0.
>
> The right way to do it would instead to add this after this label
> "out_load_server_state_in_tree" :
>
> if (f) {
> fclose(f);
> f = NULL;
> }
>
> > @@ -3360,6 +3361,8 @@ void apply_server_state(void)
> >   goto next;
> >
> >   st = container_of(node, struct state_line,
> name_name);
> > + if (strlen(st->line) >
> SRV_STATE_LINE_MAXLEN)
> > + goto next;
>
> So from what I'm seeing elsewhere in the code, this test will never match:
> a line is read using fgets() with a size of SRV_STATE_LINE_MAXLEN (hence it
> will always read one less char), and it is passed to srv_state_parse_line()
> which returns an error when the '\n' is missing, hence the line is skipped
> and never indexed, so this cannot happen at all.
>
> >   memcpy(mybuf, st->line, strlen(st->line));
> >   mybuf[strlen(st->line)] = 0;
> >
> > @@ -3375,7 +3378,7 @@ void apply_server_state(void)
> >
> >   continue; /* next proxy in list */
> >   }
> > - else {
> > + else if (filepath) {
>
> Is it a third issue ? The whole code is hard to follow for me but what is
> the exact case you've tried to address here ? Looking through the code, it
> looks like we could land there when the local file name is too large (but
> apparently there is no error handling for this where this path name is
> constructed) :-/
>
> >   /* load 'local' state file */
> >   errno = 0;
> >   f = fopen(filepath, "r");
> > @@ -3447,9 +3450,9 @@ void apply_server_state(void)
> >   /* now we can proceed with server's state
> update */
> >   srv_update_state(srv, version, srv_params);
> >   }
> > + fileclose:
> > + fclose(f);
> >   }
> > -fileclose:
> > - fclose(f);
> >   }
>
> I agree, this one definitely makes sense!
>


I will address comments today or tomorrow


>
> Thanks!
> Willy
>


Re: [PATCH] fix #660

2020-07-15 Thread Willy Tarreau
Hi Ilya,

> From 4f62799eba5db5fe6400d458877677f098da3b13 Mon Sep 17 00:00:00 2001
> From: Ilya Shipitsin 
> Date: Sun, 12 Jul 2020 15:24:55 +0500
> Subject: [PATCH] src/server.c: add extra guards when loading state file
> 
> this should fix #660
> 
> we can only load 'local' state file, if file is corrupted,
> we should check filepath against NULL
> 
> also, global server state file should be properly closed upon read.
> otherwise, it might leak on haproxy reload.
> 
> when reading global server state file we should check string lenght,
> if file was corrupted we might observe overflow otherwise.

So do I understand it right that there are actually two unrelated, or
maybe even three bugs there ? If so, please always take care of splitting
them (one fix per bug) so that they could be independently reviewed and
backported as needed (or sometimes possibly reverted if the fix causes
unexpected breakage).

> ---
>  src/server.c | 9 ++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/src/server.c b/src/server.c
> index 05b19d4e1..54239c63c 100644
> --- a/src/server.c
> +++ b/src/server.c
> @@ -3265,6 +3265,7 @@ void apply_server_state(void)
>   /* free up memory in case of error during the 
> processing of the line */
>   free(line);
>   }
> + fclose(f);
>   }
>   out_load_server_state_in_tree:

I had a look at the patch in its context and this will still leak in the
case where global_file_version == 0.

The right way to do it would instead to add this after this label
"out_load_server_state_in_tree" :

if (f) {
fclose(f);
f = NULL;
}

> @@ -3360,6 +3361,8 @@ void apply_server_state(void)
>   goto next;
>  
>   st = container_of(node, struct state_line, 
> name_name);
> + if (strlen(st->line) > SRV_STATE_LINE_MAXLEN)
> + goto next;

So from what I'm seeing elsewhere in the code, this test will never match:
a line is read using fgets() with a size of SRV_STATE_LINE_MAXLEN (hence it
will always read one less char), and it is passed to srv_state_parse_line()
which returns an error when the '\n' is missing, hence the line is skipped
and never indexed, so this cannot happen at all.

>   memcpy(mybuf, st->line, strlen(st->line));
>   mybuf[strlen(st->line)] = 0;
>  
> @@ -3375,7 +3378,7 @@ void apply_server_state(void)
>  
>   continue; /* next proxy in list */
>   }
> - else {
> + else if (filepath) {

Is it a third issue ? The whole code is hard to follow for me but what is
the exact case you've tried to address here ? Looking through the code, it
looks like we could land there when the local file name is too large (but
apparently there is no error handling for this where this path name is
constructed) :-/

>   /* load 'local' state file */
>   errno = 0;
>   f = fopen(filepath, "r");
> @@ -3447,9 +3450,9 @@ void apply_server_state(void)
>   /* now we can proceed with server's state 
> update */
>   srv_update_state(srv, version, srv_params);
>   }
> + fileclose:
> + fclose(f);
>   }
> -fileclose:
> - fclose(f);
>   }

I agree, this one definitely makes sense!

Thanks!
Willy



Re: OSX builds in Travis

2020-07-15 Thread Willy Tarreau
On Sat, Jul 11, 2020 at 10:03:29PM +0500,  ??? wrote:
> I decided to switch to the latest osx available (list:
> https://docs.travis-ci.com/user/reference/osx/#macos-version )
> I attached updated patch

OK applied now, thank you Ilya! We'll see how it performs :-)

Willy